@microsoft/power-apps-native-host 0.2.25 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -10
- package/compatibility/current.json +31 -4
- package/lib/NOTICE.txt +1325 -24
- package/lib/commonjs/auth/AuthContext.js +110 -33
- package/lib/commonjs/bridge/NativePowerAppsBridge.js +11 -18
- package/lib/commonjs/bridge/PowerPagesBridge.js +27 -8
- package/lib/commonjs/bridge/bridgeState.js +40 -0
- package/lib/commonjs/config/babelConfig.js +13 -0
- package/lib/commonjs/config/expoConfig.js +71 -0
- package/lib/commonjs/config/metroConfig.js +70 -0
- package/lib/commonjs/config/metroLogger.js +182 -0
- package/lib/commonjs/config/tamaguiConfig.js +98 -0
- package/lib/commonjs/connections/ConnectionSetupScreen.js +459 -80
- package/lib/commonjs/connections/PowerPlatformConnectionApi.js +946 -0
- package/lib/commonjs/connections/connectionMetadata.js +127 -0
- package/lib/commonjs/connections/connectionState.js +96 -0
- package/lib/commonjs/connections/disambiguate.js +19 -11
- package/lib/commonjs/connections/resolveConnections.js +348 -0
- package/lib/commonjs/connections/types.js +106 -0
- package/lib/commonjs/{platform → connections}/useConnectionRefs.js +130 -65
- package/lib/commonjs/connections/useConnectionSetup.js +111 -52
- package/lib/commonjs/controls/FilePicker.js +6 -0
- package/lib/commonjs/controls/ImagePicker.js +8 -0
- package/lib/commonjs/index.js +167 -4
- package/lib/commonjs/logger.js +9 -6
- package/lib/commonjs/offline/createOfflineHostActivationCallbacks.js +61 -0
- package/lib/commonjs/offline/useOfflineIntegrationWithStartupGate.js +48 -0
- package/lib/commonjs/offline/useOfflineIntegrationWithStartupGate.web.js +13 -0
- package/lib/commonjs/platform/DataverseDataSources.js +18 -0
- package/lib/commonjs/platform/DataverseGlobalDiscoveryApi.js +94 -0
- package/lib/commonjs/platform/GlobalDiscovery.js +51 -0
- package/lib/commonjs/platform/PowerPlatformEnvironmentApi.js +6 -106
- package/lib/commonjs/provider/PowerAppsHostProvider.js +157 -25
- package/lib/commonjs/provider/PowerAppsProvider.js +178 -134
- package/lib/commonjs/provider/SessionDetailsGesture.js +208 -0
- package/lib/commonjs/telemetry/OfflineSdkTelemetry.js +95 -0
- package/lib/commonjs/telemetry/OfflineSdkTelemetry.web.js +9 -0
- package/lib/commonjs/telemetry/index.js +22 -3
- package/lib/module/auth/AuthContext.js +110 -33
- package/lib/module/bridge/NativePowerAppsBridge.js +12 -19
- package/lib/module/bridge/PowerPagesBridge.js +27 -8
- package/lib/module/bridge/bridgeState.js +34 -0
- package/lib/module/config/babelConfig.js +9 -0
- package/lib/module/config/expoConfig.js +67 -0
- package/lib/module/config/metroConfig.js +65 -0
- package/lib/module/config/metroLogger.js +175 -0
- package/lib/module/config/tamaguiConfig.js +93 -0
- package/lib/module/connections/ConnectionSetupScreen.js +460 -81
- package/lib/module/connections/PowerPlatformConnectionApi.js +932 -0
- package/lib/module/connections/connectionMetadata.js +112 -0
- package/lib/module/connections/connectionState.js +82 -0
- package/lib/module/connections/disambiguate.js +19 -12
- package/lib/module/connections/resolveConnections.js +343 -0
- package/lib/module/connections/types.js +91 -0
- package/lib/module/{platform → connections}/useConnectionRefs.js +131 -66
- package/lib/module/connections/useConnectionSetup.js +113 -54
- package/lib/module/controls/FilePicker.js +6 -0
- package/lib/module/controls/ImagePicker.js +8 -0
- package/lib/module/index.js +14 -4
- package/lib/module/logger.js +8 -6
- package/lib/module/offline/createOfflineHostActivationCallbacks.js +55 -0
- package/lib/module/offline/useOfflineIntegrationWithStartupGate.js +44 -0
- package/lib/module/offline/useOfflineIntegrationWithStartupGate.web.js +9 -0
- package/lib/module/platform/DataverseDataSources.js +13 -0
- package/lib/module/platform/DataverseGlobalDiscoveryApi.js +89 -0
- package/lib/module/platform/GlobalDiscovery.js +45 -0
- package/lib/module/platform/PowerPlatformEnvironmentApi.js +5 -104
- package/lib/module/provider/PowerAppsHostProvider.js +160 -28
- package/lib/module/provider/PowerAppsProvider.js +182 -138
- package/lib/module/provider/SessionDetailsGesture.js +203 -0
- package/lib/module/telemetry/OfflineSdkTelemetry.js +91 -0
- package/lib/module/telemetry/OfflineSdkTelemetry.web.js +5 -0
- package/lib/module/telemetry/index.js +15 -4
- package/lib/typescript/commonjs/auth/AuthContext.d.ts +3 -1
- package/lib/typescript/commonjs/auth/AuthContext.web.d.ts +1 -0
- package/lib/typescript/commonjs/bridge/bridgeState.d.ts +5 -0
- package/lib/typescript/commonjs/config/babelConfig.d.ts +12 -0
- package/lib/typescript/commonjs/config/expoConfig.d.ts +21 -0
- package/lib/typescript/commonjs/config/metroConfig.d.ts +6 -0
- package/lib/typescript/commonjs/config/metroLogger.d.ts +21 -0
- package/lib/typescript/commonjs/config/tamaguiConfig.d.ts +1792 -0
- package/lib/typescript/commonjs/connections/ConnectionSetupScreen.d.ts +28 -7
- package/lib/typescript/commonjs/{platform → connections}/PowerPlatformConnectionApi.d.ts +52 -43
- package/lib/typescript/commonjs/connections/connectionMetadata.d.ts +66 -0
- package/lib/typescript/commonjs/connections/connectionState.d.ts +16 -0
- package/lib/typescript/commonjs/connections/disambiguate.d.ts +4 -2
- package/lib/typescript/commonjs/{platform → connections}/resolveConnections.d.ts +22 -20
- package/lib/typescript/commonjs/connections/types.d.ts +129 -1
- package/lib/typescript/commonjs/{platform → connections}/useConnectionRefs.d.ts +36 -25
- package/lib/typescript/commonjs/connections/useConnectionSetup.d.ts +12 -8
- package/lib/typescript/commonjs/controls/FilePicker.d.ts +7 -1
- package/lib/typescript/commonjs/controls/ImagePicker.d.ts +9 -1
- package/lib/typescript/commonjs/index.d.ts +18 -10
- package/lib/typescript/commonjs/logger.d.ts +4 -4
- package/lib/typescript/commonjs/offline/createOfflineHostActivationCallbacks.d.ts +12 -0
- package/lib/typescript/commonjs/offline/useOfflineIntegrationWithStartupGate.d.ts +15 -0
- package/lib/typescript/commonjs/offline/useOfflineIntegrationWithStartupGate.web.d.ts +6 -0
- package/lib/typescript/commonjs/platform/DataverseDataSources.d.ts +28 -0
- package/lib/typescript/commonjs/platform/DataverseGlobalDiscoveryApi.d.ts +3 -0
- package/lib/typescript/commonjs/platform/GlobalDiscovery.d.ts +4 -0
- package/lib/typescript/commonjs/platform/PowerPlatformEnvironmentApi.d.ts +3 -74
- package/lib/typescript/commonjs/provider/PowerAppsHostProvider.d.ts +29 -18
- package/lib/typescript/commonjs/provider/PowerAppsProvider.d.ts +54 -9
- package/lib/typescript/commonjs/provider/SessionDetailsGesture.d.ts +13 -0
- package/lib/typescript/commonjs/telemetry/OfflineSdkTelemetry.d.ts +15 -0
- package/lib/typescript/commonjs/telemetry/OfflineSdkTelemetry.web.d.ts +2 -0
- package/lib/typescript/commonjs/telemetry/index.d.ts +13 -1
- package/lib/typescript/module/auth/AuthContext.d.ts +3 -1
- package/lib/typescript/module/auth/AuthContext.web.d.ts +1 -0
- package/lib/typescript/module/bridge/bridgeState.d.ts +5 -0
- package/lib/typescript/module/config/babelConfig.d.ts +12 -0
- package/lib/typescript/module/config/expoConfig.d.ts +21 -0
- package/lib/typescript/module/config/metroConfig.d.ts +6 -0
- package/lib/typescript/module/config/metroLogger.d.ts +21 -0
- package/lib/typescript/module/config/tamaguiConfig.d.ts +1792 -0
- package/lib/typescript/module/connections/ConnectionSetupScreen.d.ts +28 -7
- package/lib/typescript/module/{platform → connections}/PowerPlatformConnectionApi.d.ts +52 -43
- package/lib/typescript/module/connections/connectionMetadata.d.ts +66 -0
- package/lib/typescript/module/connections/connectionState.d.ts +16 -0
- package/lib/typescript/module/connections/disambiguate.d.ts +4 -2
- package/lib/typescript/module/{platform → connections}/resolveConnections.d.ts +22 -20
- package/lib/typescript/module/connections/types.d.ts +129 -1
- package/lib/typescript/module/{platform → connections}/useConnectionRefs.d.ts +36 -25
- package/lib/typescript/module/connections/useConnectionSetup.d.ts +12 -8
- package/lib/typescript/module/controls/FilePicker.d.ts +7 -1
- package/lib/typescript/module/controls/ImagePicker.d.ts +9 -1
- package/lib/typescript/module/index.d.ts +18 -10
- package/lib/typescript/module/logger.d.ts +4 -4
- package/lib/typescript/module/offline/createOfflineHostActivationCallbacks.d.ts +12 -0
- package/lib/typescript/module/offline/useOfflineIntegrationWithStartupGate.d.ts +15 -0
- package/lib/typescript/module/offline/useOfflineIntegrationWithStartupGate.web.d.ts +6 -0
- package/lib/typescript/module/platform/DataverseDataSources.d.ts +28 -0
- package/lib/typescript/module/platform/DataverseGlobalDiscoveryApi.d.ts +3 -0
- package/lib/typescript/module/platform/GlobalDiscovery.d.ts +4 -0
- package/lib/typescript/module/platform/PowerPlatformEnvironmentApi.d.ts +3 -74
- package/lib/typescript/module/provider/PowerAppsHostProvider.d.ts +29 -18
- package/lib/typescript/module/provider/PowerAppsProvider.d.ts +54 -9
- package/lib/typescript/module/provider/SessionDetailsGesture.d.ts +13 -0
- package/lib/typescript/module/telemetry/OfflineSdkTelemetry.d.ts +15 -0
- package/lib/typescript/module/telemetry/OfflineSdkTelemetry.web.d.ts +2 -0
- package/lib/typescript/module/telemetry/index.d.ts +13 -1
- package/package.json +52 -13
- package/scripts/build-codegen-package.js +283 -0
- package/scripts/start-web.mjs +9 -5
- package/scripts/upgrade/runtime.js +139 -24
- package/scripts/upgrade-authoring.js +274 -180
- package/scripts/upgrade.js +10 -16
- package/src/config/generated-config.d.ts +4 -0
- package/src/config/index.d.ts +3 -0
- package/src/config/tsconfig.json +26 -0
- package/lib/commonjs/platform/PowerPlatformConnectionApi.js +0 -606
- package/lib/commonjs/platform/resolveConnections.js +0 -264
- package/lib/module/platform/PowerPlatformConnectionApi.js +0 -595
- package/lib/module/platform/resolveConnections.js +0 -259
|
@@ -42,14 +42,16 @@
|
|
|
42
42
|
*/
|
|
43
43
|
|
|
44
44
|
import React, { useState, useEffect, useCallback } from 'react';
|
|
45
|
-
import { View, Text, TouchableOpacity, ActivityIndicator, StyleSheet, ScrollView } from 'react-native';
|
|
45
|
+
import { View, Text, TouchableOpacity, ActivityIndicator, StyleSheet, ScrollView, Switch, TextInput } from 'react-native';
|
|
46
46
|
import * as WebBrowser from 'expo-web-browser';
|
|
47
47
|
import * as Linking from 'expo-linking';
|
|
48
48
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
49
49
|
import { useConnectionSetup } from "../connections/useConnectionSetup.js";
|
|
50
|
-
import { fetchConnectorMetadata, fetchConnectionsForConnector } from "
|
|
50
|
+
import { fetchConnectorMetadata, fetchConnectionsForConnector } from "./PowerPlatformConnectionApi.js";
|
|
51
51
|
import { powerPlatformScope } from "../platform/PowerPlatformEnvironmentApi.js";
|
|
52
52
|
import { ConnectionStatus } from "../connections/types.js";
|
|
53
|
+
import { normalizeApiId } from "./types.js";
|
|
54
|
+
import { connectionIdsEqual, extractConnectionId } from "./disambiguate.js";
|
|
53
55
|
|
|
54
56
|
// ---------------------------------------------------------------------------
|
|
55
57
|
// Types
|
|
@@ -61,12 +63,17 @@ import { ConnectionStatus } from "../connections/types.js";
|
|
|
61
63
|
// ---------------------------------------------------------------------------
|
|
62
64
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
63
65
|
function ConnectorSetupStep({
|
|
66
|
+
localRefId,
|
|
64
67
|
connectorId,
|
|
65
68
|
apiId,
|
|
66
69
|
environmentId,
|
|
67
70
|
region,
|
|
68
71
|
acquireToken,
|
|
72
|
+
onSignOut,
|
|
69
73
|
isvClientId,
|
|
74
|
+
gatewayObjectIdHint,
|
|
75
|
+
parameterSetName,
|
|
76
|
+
sharedConnectionId,
|
|
70
77
|
onConnected,
|
|
71
78
|
renderOAuthWebView
|
|
72
79
|
}) {
|
|
@@ -80,18 +87,24 @@ function ConnectorSetupStep({
|
|
|
80
87
|
// useConnectionSetup) so the hook stays focused on connection flow only.
|
|
81
88
|
const [isLoadingMetadata, setIsLoadingMetadata] = useState(true);
|
|
82
89
|
const [metadata, setMetadata] = useState(null);
|
|
90
|
+
const [metadataError, setMetadataError] = useState(null);
|
|
91
|
+
const [metadataReload, setMetadataReload] = useState(0);
|
|
83
92
|
const [showOAuthModal, setShowOAuthModal] = useState(false);
|
|
84
|
-
|
|
85
|
-
const [
|
|
93
|
+
const [existingConnected, setExistingConnected] = useState([]);
|
|
94
|
+
const [existingRepairable, setExistingRepairable] = useState([]);
|
|
95
|
+
const [selectedParameterSet, setSelectedParameterSet] = useState(parameterSetName ?? '');
|
|
96
|
+
const [parameterValues, setParameterValues] = useState({});
|
|
97
|
+
const [gatewayObjectId, setGatewayObjectId] = useState(gatewayObjectIdHint ?? '');
|
|
86
98
|
const setup = useConnectionSetup({
|
|
87
99
|
connectorId,
|
|
88
100
|
environmentId,
|
|
89
101
|
region,
|
|
90
102
|
acquireToken,
|
|
91
103
|
isvClientId,
|
|
104
|
+
sharedConnectionId,
|
|
92
105
|
onConnected: instance => {
|
|
93
106
|
setShowOAuthModal(false);
|
|
94
|
-
onConnected(
|
|
107
|
+
onConnected(localRefId, instance);
|
|
95
108
|
},
|
|
96
109
|
oauthRedirectUrl,
|
|
97
110
|
polling: {
|
|
@@ -103,46 +116,94 @@ function ConnectorSetupStep({
|
|
|
103
116
|
// Fetch connector metadata and check for existing non-connected connections.
|
|
104
117
|
useEffect(() => {
|
|
105
118
|
let cancelled = false;
|
|
119
|
+
setIsLoadingMetadata(true);
|
|
120
|
+
setMetadata(null);
|
|
121
|
+
setMetadataError(null);
|
|
122
|
+
setExistingConnected([]);
|
|
123
|
+
setExistingRepairable([]);
|
|
124
|
+
setSelectedParameterSet(parameterSetName ?? '');
|
|
125
|
+
setParameterValues({});
|
|
126
|
+
setGatewayObjectId(gatewayObjectIdHint ?? '');
|
|
106
127
|
async function load() {
|
|
107
128
|
const token = await acquireToken([powerPlatformScope(region)]);
|
|
108
129
|
if (!token || cancelled) {
|
|
109
130
|
if (!cancelled) {
|
|
110
|
-
|
|
111
|
-
displayName: connectorId,
|
|
112
|
-
iconUri: '',
|
|
113
|
-
description: ''
|
|
114
|
-
});
|
|
131
|
+
setMetadataError('Unable to acquire a token to load connector setup.');
|
|
115
132
|
setIsLoadingMetadata(false);
|
|
116
133
|
}
|
|
117
134
|
return;
|
|
118
135
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
136
|
+
try {
|
|
137
|
+
const [meta, instances] = await Promise.all([fetchConnectorMetadata(connectorId, environmentId, region, token), fetchConnectionsForConnector(connectorId, environmentId, region, token)]);
|
|
138
|
+
if (cancelled) return;
|
|
139
|
+
if (!meta) throw new Error('Connector metadata is unavailable.');
|
|
140
|
+
const resolvedMetadata = meta;
|
|
141
|
+
setMetadata(resolvedMetadata);
|
|
142
|
+
const preferredSet = resolvedMetadata.parameterSets.find(set => set.name === parameterSetName) ?? resolvedMetadata.parameterSets[0];
|
|
143
|
+
setSelectedParameterSet(preferredSet?.name ?? '');
|
|
144
|
+
setParameterValues(Object.fromEntries((preferredSet?.parameters ?? []).filter(parameter => parameter.defaultValue !== undefined).map(parameter => [parameter.name, parameter.defaultValue])));
|
|
126
145
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
146
|
+
// If there's already a Connected instance the disambiguation didn't pick
|
|
147
|
+
// (e.g., appeared after the initial load), use it directly.
|
|
148
|
+
const sharedId = sharedConnectionId ? extractConnectionId(sharedConnectionId) : undefined;
|
|
149
|
+
const eligibleInstances = sharedId ? instances.filter(instance => connectionIdsEqual(instance.id, sharedId)) : instances;
|
|
150
|
+
setExistingConnected(eligibleInstances.filter(instance => instance.status === ConnectionStatus.Connected));
|
|
151
|
+
setExistingRepairable(sharedId ? [] : eligibleInstances.filter(instance => instance.status !== ConnectionStatus.Connected));
|
|
152
|
+
} catch (error) {
|
|
153
|
+
if (!cancelled) {
|
|
154
|
+
setMetadataError(error instanceof Error ? error.message : 'Unable to load connector setup.');
|
|
155
|
+
}
|
|
156
|
+
} finally {
|
|
157
|
+
if (!cancelled) setIsLoadingMetadata(false);
|
|
158
|
+
}
|
|
132
159
|
}
|
|
133
160
|
void load();
|
|
134
161
|
return () => {
|
|
135
162
|
cancelled = true;
|
|
136
163
|
};
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
164
|
+
}, [acquireToken, connectorId, environmentId, gatewayObjectIdHint, parameterSetName, region, sharedConnectionId, metadataReload]);
|
|
165
|
+
const handleUseExisting = useCallback(async instance => {
|
|
166
|
+
await setup.useExisting(instance);
|
|
167
|
+
}, [setup]);
|
|
168
|
+
const activeParameterSet = metadata?.parameterSets.find(set => (set.name ?? '') === selectedParameterSet) ?? metadata?.parameterSets[0];
|
|
169
|
+
const selectedCapability = gatewayObjectIdHint ? 'gateway' : 'cloud';
|
|
170
|
+
const visibleParameters = activeParameterSet?.parameters.filter(parameter => !parameter.hidden && (!parameter.capabilities?.length || parameter.capabilities.some(capability => capability.toLowerCase() === selectedCapability))) ?? [];
|
|
171
|
+
const requiredParametersComplete = visibleParameters.every(parameter => {
|
|
172
|
+
if (!parameter.required) return true;
|
|
173
|
+
const value = parameterValues[parameter.name];
|
|
174
|
+
if (typeof value === 'object' && value && 'pfx' in value) {
|
|
175
|
+
return Boolean(value.pfx && value.password);
|
|
142
176
|
}
|
|
143
|
-
|
|
177
|
+
return value !== undefined && value !== '';
|
|
178
|
+
});
|
|
179
|
+
const buildInput = useCallback(() => ({
|
|
180
|
+
parameterSetName: activeParameterSet?.name,
|
|
181
|
+
gatewayObjectId: gatewayObjectId || undefined,
|
|
182
|
+
gatewayParameterName: activeParameterSet?.gatewayParameterName,
|
|
183
|
+
parameters: parameterValues
|
|
184
|
+
}), [activeParameterSet?.name, gatewayObjectId, parameterValues]);
|
|
144
185
|
const handleConnect = useCallback(async () => {
|
|
145
|
-
await setup.startCreate();
|
|
186
|
+
await setup.startCreate(buildInput());
|
|
187
|
+
}, [setup, buildInput]);
|
|
188
|
+
const handleRepair = useCallback(async instance => {
|
|
189
|
+
const instanceParameterSet = metadata?.parameterSets.find(parameterSet => parameterSet.name === instance.parameterSetName) ?? activeParameterSet;
|
|
190
|
+
const requiresApiConsent = instanceParameterSet?.requiresApiConsent ?? metadata?.hasOAuthParameter ?? false;
|
|
191
|
+
const input = buildInput();
|
|
192
|
+
const hasEditableInput = Object.keys(input.parameters).length > 0 || Boolean(input.gatewayObjectId);
|
|
193
|
+
await setup.startRepair(instance, !requiresApiConsent || hasEditableInput ? input : undefined, requiresApiConsent);
|
|
194
|
+
}, [setup, metadata, activeParameterSet, buildInput]);
|
|
195
|
+
const completeOAuthRedirect = useCallback(async redirectUrl => {
|
|
196
|
+
let code;
|
|
197
|
+
if (redirectUrl) {
|
|
198
|
+
try {
|
|
199
|
+
const raw = new URL(redirectUrl).searchParams.get('code') ?? '';
|
|
200
|
+
if (/^[0-9a-f]{32}$/i.test(raw)) code = raw;
|
|
201
|
+
} catch {
|
|
202
|
+
setup.reset();
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
await setup.completeConsent(code);
|
|
146
207
|
}, [setup]);
|
|
147
208
|
|
|
148
209
|
// Open OAuth UI when consentUrl becomes available (set by startCreate in the hook).
|
|
@@ -156,29 +217,24 @@ function ConnectorSetupStep({
|
|
|
156
217
|
// custom-scheme redirect (e.g. expo-app://oauth-callback).
|
|
157
218
|
void (async () => {
|
|
158
219
|
const result = await WebBrowser.openAuthSessionAsync(setup.consentUrl, oauthRedirectUrl);
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
const raw = params.get('code') ?? '';
|
|
164
|
-
// CommitTokenCode is a 32-char lowercase hex string.
|
|
165
|
-
if (/^[0-9a-f]{32}$/i.test(raw)) {
|
|
166
|
-
code = raw;
|
|
167
|
-
}
|
|
220
|
+
if (result.type === 'success') {
|
|
221
|
+
await completeOAuthRedirect(result.url);
|
|
222
|
+
} else {
|
|
223
|
+
setup.reset();
|
|
168
224
|
}
|
|
169
|
-
await setup.completeConsent(code);
|
|
170
225
|
})();
|
|
171
226
|
}
|
|
172
227
|
}
|
|
173
|
-
}, [setup.phase, setup.consentUrl, renderOAuthWebView, oauthRedirectUrl]);
|
|
174
|
-
const handleWebViewDismiss = useCallback(async
|
|
228
|
+
}, [setup.phase, setup.consentUrl, renderOAuthWebView, oauthRedirectUrl, completeOAuthRedirect]);
|
|
229
|
+
const handleWebViewDismiss = useCallback(async redirectUrl => {
|
|
175
230
|
setShowOAuthModal(false);
|
|
176
|
-
await setup.checkNow();
|
|
177
|
-
}, [setup]);
|
|
231
|
+
if (redirectUrl) await completeOAuthRedirect(redirectUrl);else await setup.checkNow();
|
|
232
|
+
}, [completeOAuthRedirect, setup]);
|
|
178
233
|
const displayName = metadata?.displayName ?? connectorId;
|
|
179
234
|
const description = metadata?.description ?? '';
|
|
180
235
|
if (isLoadingMetadata) {
|
|
181
236
|
return /*#__PURE__*/_jsx(View, {
|
|
237
|
+
testID: `powerApps.connectionSetup.connector.${connectorId}`,
|
|
182
238
|
style: styles.connectorCard,
|
|
183
239
|
children: /*#__PURE__*/_jsx(View, {
|
|
184
240
|
style: styles.metadataLoading,
|
|
@@ -188,7 +244,36 @@ function ConnectorSetupStep({
|
|
|
188
244
|
})
|
|
189
245
|
});
|
|
190
246
|
}
|
|
247
|
+
if (metadataError || !metadata) {
|
|
248
|
+
return /*#__PURE__*/_jsxs(View, {
|
|
249
|
+
style: styles.connectorCard,
|
|
250
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
251
|
+
style: styles.connectorName,
|
|
252
|
+
children: connectorId
|
|
253
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
254
|
+
style: styles.errorText,
|
|
255
|
+
children: metadataError ?? 'Unable to load connector setup.'
|
|
256
|
+
}), /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
257
|
+
style: styles.button,
|
|
258
|
+
onPress: () => setMetadataReload(value => value + 1),
|
|
259
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
260
|
+
style: styles.buttonText,
|
|
261
|
+
children: "Retry"
|
|
262
|
+
})
|
|
263
|
+
}), onSignOut ? /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
264
|
+
style: [styles.button, styles.buttonSecondary],
|
|
265
|
+
onPress: () => {
|
|
266
|
+
void onSignOut();
|
|
267
|
+
},
|
|
268
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
269
|
+
style: styles.buttonTextSecondary,
|
|
270
|
+
children: "Sign out"
|
|
271
|
+
})
|
|
272
|
+
}) : null]
|
|
273
|
+
});
|
|
274
|
+
}
|
|
191
275
|
return /*#__PURE__*/_jsxs(View, {
|
|
276
|
+
testID: `powerApps.connectionSetup.connector.${connectorId}`,
|
|
192
277
|
style: styles.connectorCard,
|
|
193
278
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
194
279
|
style: styles.connectorName,
|
|
@@ -196,33 +281,140 @@ function ConnectorSetupStep({
|
|
|
196
281
|
}), description ? /*#__PURE__*/_jsx(Text, {
|
|
197
282
|
style: styles.connectorDescription,
|
|
198
283
|
children: description
|
|
199
|
-
}) : null, setup.phase === 'idle' && /*#__PURE__*/
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
284
|
+
}) : null, setup.phase === 'idle' && !sharedConnectionId && (metadata?.parameterSets.length ?? 0) > 1 ? /*#__PURE__*/_jsxs(View, {
|
|
285
|
+
style: styles.fieldGroup,
|
|
286
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
287
|
+
style: styles.fieldLabel,
|
|
288
|
+
children: "Authentication type"
|
|
289
|
+
}), /*#__PURE__*/_jsx(View, {
|
|
290
|
+
style: styles.choiceRow,
|
|
291
|
+
children: metadata?.parameterSets.map(parameterSet => /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
292
|
+
style: [styles.choiceButton, selectedParameterSet === (parameterSet.name ?? '') && styles.choiceButtonSelected],
|
|
293
|
+
onPress: () => {
|
|
294
|
+
setSelectedParameterSet(parameterSet.name ?? '');
|
|
295
|
+
setParameterValues(Object.fromEntries(parameterSet.parameters.filter(parameter => parameter.defaultValue !== undefined).map(parameter => [parameter.name, parameter.defaultValue])));
|
|
296
|
+
},
|
|
205
297
|
children: /*#__PURE__*/_jsx(Text, {
|
|
206
|
-
style: styles.
|
|
207
|
-
children:
|
|
298
|
+
style: selectedParameterSet === (parameterSet.name ?? '') ? styles.choiceTextSelected : styles.choiceText,
|
|
299
|
+
children: parameterSet.displayName
|
|
208
300
|
})
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
|
|
301
|
+
}, parameterSet.name ?? 'default'))
|
|
302
|
+
})]
|
|
303
|
+
}) : null, setup.phase === 'idle' && !sharedConnectionId && visibleParameters.map(parameter => /*#__PURE__*/_jsxs(View, {
|
|
304
|
+
style: styles.fieldGroup,
|
|
305
|
+
children: [/*#__PURE__*/_jsxs(Text, {
|
|
306
|
+
style: styles.fieldLabel,
|
|
307
|
+
children: [parameter.displayName, parameter.required ? ' *' : '']
|
|
308
|
+
}), parameter.allowedValues?.length ? /*#__PURE__*/_jsx(View, {
|
|
309
|
+
style: styles.choiceRow,
|
|
310
|
+
children: parameter.allowedValues.map(option => /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
311
|
+
style: [styles.choiceButton, parameterValues[parameter.name] === option.value && styles.choiceButtonSelected],
|
|
312
|
+
onPress: () => setParameterValues(values => ({
|
|
313
|
+
...values,
|
|
314
|
+
[parameter.name]: option.value
|
|
315
|
+
})),
|
|
212
316
|
children: /*#__PURE__*/_jsx(Text, {
|
|
213
|
-
style: styles.
|
|
214
|
-
children:
|
|
317
|
+
style: parameterValues[parameter.name] === option.value ? styles.choiceTextSelected : styles.choiceText,
|
|
318
|
+
children: option.displayName
|
|
215
319
|
})
|
|
320
|
+
}, option.value))
|
|
321
|
+
}) : parameter.type === 'boolean' ? /*#__PURE__*/_jsx(Switch, {
|
|
322
|
+
value: Boolean(parameterValues[parameter.name]),
|
|
323
|
+
onValueChange: value => setParameterValues(values => ({
|
|
324
|
+
...values,
|
|
325
|
+
[parameter.name]: value
|
|
326
|
+
}))
|
|
327
|
+
}) : parameter.type === 'clientcertificate' ? /*#__PURE__*/_jsxs(_Fragment, {
|
|
328
|
+
children: [/*#__PURE__*/_jsx(TextInput, {
|
|
329
|
+
style: styles.textInput,
|
|
330
|
+
placeholder: "PFX certificate (base64)",
|
|
331
|
+
autoCapitalize: "none",
|
|
332
|
+
value: parameterValues[parameter.name]?.pfx ?? '',
|
|
333
|
+
onChangeText: pfx => setParameterValues(values => ({
|
|
334
|
+
...values,
|
|
335
|
+
[parameter.name]: {
|
|
336
|
+
pfx,
|
|
337
|
+
password: values[parameter.name]?.password ?? ''
|
|
338
|
+
}
|
|
339
|
+
}))
|
|
340
|
+
}), /*#__PURE__*/_jsx(TextInput, {
|
|
341
|
+
style: styles.textInput,
|
|
342
|
+
placeholder: "Certificate password",
|
|
343
|
+
secureTextEntry: true,
|
|
344
|
+
value: parameterValues[parameter.name]?.password ?? '',
|
|
345
|
+
onChangeText: password => setParameterValues(values => ({
|
|
346
|
+
...values,
|
|
347
|
+
[parameter.name]: {
|
|
348
|
+
pfx: values[parameter.name]?.pfx ?? '',
|
|
349
|
+
password
|
|
350
|
+
}
|
|
351
|
+
}))
|
|
216
352
|
})]
|
|
217
|
-
}) : /*#__PURE__*/_jsx(
|
|
218
|
-
style: styles.
|
|
353
|
+
}) : /*#__PURE__*/_jsx(TextInput, {
|
|
354
|
+
style: styles.textInput,
|
|
355
|
+
secureTextEntry: parameter.type === 'securestring',
|
|
356
|
+
keyboardType: parameter.type === 'integer' ? 'number-pad' : 'default',
|
|
357
|
+
autoCapitalize: "none",
|
|
358
|
+
value: String(parameterValues[parameter.name] ?? ''),
|
|
359
|
+
onChangeText: value => setParameterValues(values => ({
|
|
360
|
+
...values,
|
|
361
|
+
[parameter.name]: parameter.type === 'integer' && value !== '' ? /^-?\d+$/.test(value) ? parseInt(value, 10) : '' : value
|
|
362
|
+
}))
|
|
363
|
+
})]
|
|
364
|
+
}, parameter.name)), setup.phase === 'idle' && !sharedConnectionId && gatewayObjectIdHint ? /*#__PURE__*/_jsxs(View, {
|
|
365
|
+
style: styles.fieldGroup,
|
|
366
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
367
|
+
style: styles.fieldLabel,
|
|
368
|
+
children: "Gateway"
|
|
369
|
+
}), /*#__PURE__*/_jsx(TextInput, {
|
|
370
|
+
style: styles.textInput,
|
|
371
|
+
value: gatewayObjectId,
|
|
372
|
+
onChangeText: setGatewayObjectId,
|
|
373
|
+
autoCapitalize: "none"
|
|
374
|
+
})]
|
|
375
|
+
}) : null, setup.phase === 'idle' && /*#__PURE__*/_jsxs(_Fragment, {
|
|
376
|
+
children: [existingConnected.map((instance, index) => /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
377
|
+
testID: index === 0 ? `powerApps.connectionSetup.connector.${connectorId}.useExistingButton` : `powerApps.connectionSetup.connector.${connectorId}.useExistingButton.${instance.id}`,
|
|
378
|
+
style: [styles.button, styles.buttonSecondary],
|
|
379
|
+
onPress: () => handleUseExisting(instance),
|
|
380
|
+
children: /*#__PURE__*/_jsxs(Text, {
|
|
381
|
+
style: styles.buttonTextSecondary,
|
|
382
|
+
children: ["Use ", instance.displayName || instance.id]
|
|
383
|
+
})
|
|
384
|
+
}, instance.id)), existingRepairable.map(instance => /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
385
|
+
style: [styles.button, styles.buttonSecondary],
|
|
386
|
+
disabled: !requiredParametersComplete,
|
|
387
|
+
onPress: () => handleRepair(instance),
|
|
388
|
+
children: /*#__PURE__*/_jsxs(Text, {
|
|
389
|
+
style: styles.buttonTextSecondary,
|
|
390
|
+
children: ["Fix ", instance.displayName || instance.id]
|
|
391
|
+
})
|
|
392
|
+
}, instance.id)), sharedConnectionId && existingConnected.length === 0 ? /*#__PURE__*/_jsxs(View, {
|
|
393
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
394
|
+
style: styles.errorText,
|
|
395
|
+
children: "You do not have access to the shared connection required by this app."
|
|
396
|
+
}), onSignOut ? /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
397
|
+
style: [styles.button, styles.buttonSecondary],
|
|
398
|
+
onPress: () => {
|
|
399
|
+
void onSignOut();
|
|
400
|
+
},
|
|
401
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
402
|
+
style: styles.buttonTextSecondary,
|
|
403
|
+
children: "Sign out"
|
|
404
|
+
})
|
|
405
|
+
}) : null]
|
|
406
|
+
}) : !sharedConnectionId ? /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
407
|
+
testID: `powerApps.connectionSetup.connector.${connectorId}.${existingConnected.length ? 'createButton' : 'connectButton'}`,
|
|
408
|
+
style: [styles.button, !requiredParametersComplete && styles.buttonDisabled],
|
|
409
|
+
disabled: !requiredParametersComplete,
|
|
219
410
|
onPress: handleConnect,
|
|
220
411
|
children: /*#__PURE__*/_jsx(Text, {
|
|
221
412
|
style: styles.buttonText,
|
|
222
|
-
children:
|
|
413
|
+
children: existingConnected.length ? 'Create new' : metadata?.hasOAuthParameter ? 'Sign in' : 'Connect'
|
|
223
414
|
})
|
|
224
|
-
})
|
|
415
|
+
}) : null]
|
|
225
416
|
}), (setup.phase === 'creating' || setup.phase === 'confirming') && /*#__PURE__*/_jsxs(View, {
|
|
417
|
+
testID: `powerApps.connectionSetup.connector.${connectorId}.${setup.phase}`,
|
|
226
418
|
style: styles.statusRow,
|
|
227
419
|
children: [/*#__PURE__*/_jsx(ActivityIndicator, {
|
|
228
420
|
size: "small",
|
|
@@ -232,6 +424,7 @@ function ConnectorSetupStep({
|
|
|
232
424
|
children: setup.phase === 'creating' ? 'Creating connection…' : 'Confirming…'
|
|
233
425
|
})]
|
|
234
426
|
}), setup.phase === 'oauth' && /*#__PURE__*/_jsxs(View, {
|
|
427
|
+
testID: `powerApps.connectionSetup.connector.${connectorId}.oauth`,
|
|
235
428
|
style: styles.statusRow,
|
|
236
429
|
children: [/*#__PURE__*/_jsx(ActivityIndicator, {
|
|
237
430
|
size: "small",
|
|
@@ -240,30 +433,43 @@ function ConnectorSetupStep({
|
|
|
240
433
|
style: styles.statusText,
|
|
241
434
|
children: "Waiting for sign-in\u2026"
|
|
242
435
|
}), /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
243
|
-
|
|
436
|
+
testID: `powerApps.connectionSetup.connector.${connectorId}.doneButton`,
|
|
437
|
+
onPress: () => handleWebViewDismiss(),
|
|
244
438
|
children: /*#__PURE__*/_jsx(Text, {
|
|
245
439
|
style: styles.linkText,
|
|
246
440
|
children: "Done"
|
|
247
441
|
})
|
|
248
442
|
})]
|
|
249
443
|
}), setup.phase === 'connected' && /*#__PURE__*/_jsx(View, {
|
|
444
|
+
testID: `powerApps.connectionSetup.connector.${connectorId}.connected`,
|
|
250
445
|
style: styles.statusRow,
|
|
251
446
|
children: /*#__PURE__*/_jsx(Text, {
|
|
252
447
|
style: styles.successText,
|
|
253
448
|
children: "\u2713 Connected"
|
|
254
449
|
})
|
|
255
450
|
}), setup.phase === 'error' && /*#__PURE__*/_jsxs(View, {
|
|
451
|
+
testID: `powerApps.connectionSetup.connector.${connectorId}.error`,
|
|
256
452
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
257
453
|
style: styles.errorText,
|
|
258
454
|
children: setup.errorMessage ?? 'Connection failed'
|
|
259
455
|
}), /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
456
|
+
testID: `powerApps.connectionSetup.connector.${connectorId}.retryButton`,
|
|
260
457
|
style: [styles.button, styles.buttonDanger],
|
|
261
458
|
onPress: setup.reset,
|
|
262
459
|
children: /*#__PURE__*/_jsx(Text, {
|
|
263
460
|
style: styles.buttonText,
|
|
264
461
|
children: "Retry"
|
|
265
462
|
})
|
|
266
|
-
})
|
|
463
|
+
}), onSignOut ? /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
464
|
+
style: [styles.button, styles.buttonSecondary],
|
|
465
|
+
onPress: () => {
|
|
466
|
+
void onSignOut();
|
|
467
|
+
},
|
|
468
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
469
|
+
style: styles.buttonTextSecondary,
|
|
470
|
+
children: "Sign out"
|
|
471
|
+
})
|
|
472
|
+
}) : null]
|
|
267
473
|
}), showOAuthModal && setup.consentUrl && renderOAuthWebView ? renderOAuthWebView(setup.consentUrl, handleWebViewDismiss) : null]
|
|
268
474
|
});
|
|
269
475
|
}
|
|
@@ -286,15 +492,31 @@ export function ConnectionSetupScreen({
|
|
|
286
492
|
environmentId,
|
|
287
493
|
region = 'prod',
|
|
288
494
|
acquireToken,
|
|
495
|
+
onSignOut,
|
|
289
496
|
isvClientId,
|
|
290
497
|
onAllConnected,
|
|
291
498
|
onSkip,
|
|
499
|
+
consentDetails = [],
|
|
500
|
+
resourceConsents = [],
|
|
501
|
+
onConsentDeclined,
|
|
502
|
+
showReview = true,
|
|
292
503
|
renderOAuthWebView,
|
|
293
504
|
title = 'Set up connections'
|
|
294
505
|
}) {
|
|
295
506
|
// resolvedIds accumulates as each connector is connected.
|
|
296
507
|
const [resolvedIds, setResolvedIds] = useState({});
|
|
508
|
+
const [isSubmittingConsent, setIsSubmittingConsent] = useState(false);
|
|
509
|
+
const [consentError, setConsentError] = useState(null);
|
|
510
|
+
const [consentDeclined, setConsentDeclined] = useState(false);
|
|
511
|
+
const autoCompletionStartedRef = React.useRef(false);
|
|
297
512
|
const insets = useSafeAreaInsets();
|
|
513
|
+
const missingReferencesKey = React.useMemo(() => missingConnectors.map(connector => `${connector.localRefId}:${normalizeApiId(connector.apiId)}`).sort().join('|'), [missingConnectors]);
|
|
514
|
+
useEffect(() => {
|
|
515
|
+
setResolvedIds({});
|
|
516
|
+
setConsentError(null);
|
|
517
|
+
setConsentDeclined(false);
|
|
518
|
+
autoCompletionStartedRef.current = false;
|
|
519
|
+
}, [missingReferencesKey]);
|
|
298
520
|
|
|
299
521
|
// Build connectorId (short name) for each missing entry from the schemaMap.
|
|
300
522
|
// schemaMap keys are data source names; we need to find the ConnectorSchema
|
|
@@ -310,26 +532,38 @@ export function ConnectionSetupScreen({
|
|
|
310
532
|
}
|
|
311
533
|
return map;
|
|
312
534
|
}, [schemaMap]);
|
|
313
|
-
const handleConnected = useCallback((
|
|
535
|
+
const handleConnected = useCallback((localRefId, instance) => {
|
|
314
536
|
setResolvedIds(prev => ({
|
|
315
537
|
...prev,
|
|
316
|
-
[
|
|
538
|
+
[localRefId]: instance.id
|
|
317
539
|
}));
|
|
318
540
|
}, []);
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
541
|
+
const allResolved = missingConnectors.every(mc => resolvedIds[mc.localRefId] !== undefined);
|
|
542
|
+
const handleAllow = useCallback(async () => {
|
|
543
|
+
if (!allResolved || isSubmittingConsent) return;
|
|
544
|
+
setIsSubmittingConsent(true);
|
|
545
|
+
setConsentError(null);
|
|
546
|
+
try {
|
|
547
|
+
await onAllConnected(resolvedIds);
|
|
548
|
+
} catch (error) {
|
|
549
|
+
setConsentError(error instanceof Error ? error.message : 'Unable to save connection consent.');
|
|
550
|
+
} finally {
|
|
551
|
+
setIsSubmittingConsent(false);
|
|
328
552
|
}
|
|
329
|
-
}, [
|
|
553
|
+
}, [allResolved, isSubmittingConsent, onAllConnected, resolvedIds]);
|
|
554
|
+
const handleDecline = useCallback(async () => {
|
|
555
|
+
setConsentDeclined(true);
|
|
556
|
+
await onConsentDeclined?.();
|
|
557
|
+
}, [onConsentDeclined]);
|
|
558
|
+
useEffect(() => {
|
|
559
|
+
if (showReview || !allResolved || autoCompletionStartedRef.current) return;
|
|
560
|
+
autoCompletionStartedRef.current = true;
|
|
561
|
+
void handleAllow();
|
|
562
|
+
}, [allResolved, handleAllow, showReview]);
|
|
330
563
|
const resolvedCount = Object.keys(resolvedIds).length;
|
|
331
564
|
const total = missingConnectors.length;
|
|
332
565
|
return /*#__PURE__*/_jsxs(View, {
|
|
566
|
+
testID: "powerApps.connectionSetup.root",
|
|
333
567
|
style: [styles.container, {
|
|
334
568
|
paddingTop: insets.top,
|
|
335
569
|
paddingBottom: insets.bottom
|
|
@@ -337,41 +571,121 @@ export function ConnectionSetupScreen({
|
|
|
337
571
|
children: [/*#__PURE__*/_jsxs(ScrollView, {
|
|
338
572
|
contentContainerStyle: styles.scrollContent,
|
|
339
573
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
574
|
+
testID: "powerApps.connectionSetup.title",
|
|
340
575
|
style: styles.title,
|
|
341
576
|
children: title
|
|
342
|
-
}), /*#__PURE__*/
|
|
577
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
343
578
|
style: styles.subtitle,
|
|
344
|
-
children:
|
|
579
|
+
children: total > 0 ? `This app needs ${total === 1 ? 'a connection' : `${total} connections`} to work. Sign in to each service below${showReview ? ', then review access' : ''}.` : 'Review the connections and resources this app will use.'
|
|
345
580
|
}), resolvedCount > 0 && /*#__PURE__*/_jsxs(Text, {
|
|
581
|
+
testID: "powerApps.connectionSetup.progress",
|
|
346
582
|
style: styles.progressText,
|
|
347
583
|
children: [resolvedCount, " of ", total, " connected"]
|
|
348
584
|
}), missingConnectors.map(mc => {
|
|
349
|
-
const connectorId = connectorIdByApiId[mc.apiId];
|
|
585
|
+
const connectorId = mc.connectorId ?? connectorIdByApiId[normalizeApiId(mc.apiId)];
|
|
350
586
|
if (!connectorId) {
|
|
351
587
|
// Unknown connector — skip rendering.
|
|
352
588
|
return null;
|
|
353
589
|
}
|
|
354
|
-
const isResolved = resolvedIds[mc.
|
|
590
|
+
const isResolved = resolvedIds[mc.localRefId] !== undefined;
|
|
355
591
|
if (isResolved) {
|
|
356
592
|
return /*#__PURE__*/_jsx(View, {
|
|
593
|
+
testID: `powerApps.connectionSetup.connector.${connectorId}.resolved`,
|
|
357
594
|
style: [styles.connectorCard, styles.connectorCardResolved],
|
|
358
595
|
children: /*#__PURE__*/_jsxs(Text, {
|
|
359
596
|
style: styles.successText,
|
|
360
597
|
children: ["\u2713 ", connectorId.replace('shared_', '')]
|
|
361
598
|
})
|
|
362
|
-
}, mc.
|
|
599
|
+
}, mc.localRefId);
|
|
363
600
|
}
|
|
364
601
|
return /*#__PURE__*/_jsx(ConnectorSetupStep, {
|
|
602
|
+
localRefId: mc.localRefId,
|
|
365
603
|
connectorId: connectorId,
|
|
366
604
|
apiId: mc.apiId,
|
|
367
605
|
environmentId: environmentId,
|
|
368
606
|
region: region,
|
|
369
607
|
acquireToken: acquireToken,
|
|
608
|
+
onSignOut: onSignOut,
|
|
370
609
|
isvClientId: isvClientId,
|
|
610
|
+
gatewayObjectIdHint: mc.gatewayObjectIdHint,
|
|
611
|
+
parameterSetName: mc.parameterSetName,
|
|
612
|
+
sharedConnectionId: mc.sharedConnectionId,
|
|
371
613
|
onConnected: handleConnected,
|
|
372
614
|
renderOAuthWebView: renderOAuthWebView
|
|
373
|
-
}, mc.
|
|
374
|
-
})
|
|
615
|
+
}, mc.localRefId);
|
|
616
|
+
}), showReview && allResolved && !consentDeclined ? /*#__PURE__*/_jsxs(View, {
|
|
617
|
+
style: styles.consentSection,
|
|
618
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
619
|
+
style: styles.consentTitle,
|
|
620
|
+
children: "Review access"
|
|
621
|
+
}), consentDetails.map(detail => /*#__PURE__*/_jsxs(View, {
|
|
622
|
+
style: styles.consentItem,
|
|
623
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
624
|
+
style: styles.connectorName,
|
|
625
|
+
children: detail.displayName
|
|
626
|
+
}), detail.description ? /*#__PURE__*/_jsx(Text, {
|
|
627
|
+
style: styles.connectorDescription,
|
|
628
|
+
children: detail.description
|
|
629
|
+
}) : null, detail.appActions.length > 0 ? /*#__PURE__*/_jsxs(Text, {
|
|
630
|
+
style: styles.consentActions,
|
|
631
|
+
children: ["Uses: ", detail.appActions.join(', ')]
|
|
632
|
+
}) : null]
|
|
633
|
+
}, detail.localRefId)), resourceConsents.length > 0 ? /*#__PURE__*/_jsxs(View, {
|
|
634
|
+
style: styles.consentItem,
|
|
635
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
636
|
+
style: styles.connectorName,
|
|
637
|
+
children: "Protected resources"
|
|
638
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
639
|
+
style: styles.connectorDescription,
|
|
640
|
+
children: resourceConsents.map(resource => resource.displayName).join(', ')
|
|
641
|
+
})]
|
|
642
|
+
}) : null, consentError ? /*#__PURE__*/_jsxs(View, {
|
|
643
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
644
|
+
style: styles.errorText,
|
|
645
|
+
children: consentError
|
|
646
|
+
}), onSignOut ? /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
647
|
+
style: [styles.button, styles.buttonSecondary],
|
|
648
|
+
onPress: () => {
|
|
649
|
+
void onSignOut();
|
|
650
|
+
},
|
|
651
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
652
|
+
style: styles.buttonTextSecondary,
|
|
653
|
+
children: "Sign out"
|
|
654
|
+
})
|
|
655
|
+
}) : null]
|
|
656
|
+
}) : null, /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
657
|
+
style: [styles.button, isSubmittingConsent && styles.buttonDisabled],
|
|
658
|
+
disabled: isSubmittingConsent,
|
|
659
|
+
onPress: handleAllow,
|
|
660
|
+
children: isSubmittingConsent ? /*#__PURE__*/_jsx(ActivityIndicator, {
|
|
661
|
+
size: "small",
|
|
662
|
+
color: "#FFF"
|
|
663
|
+
}) : /*#__PURE__*/_jsx(Text, {
|
|
664
|
+
style: styles.buttonText,
|
|
665
|
+
children: "Allow"
|
|
666
|
+
})
|
|
667
|
+
}), /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
668
|
+
style: styles.skipButton,
|
|
669
|
+
onPress: handleDecline,
|
|
670
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
671
|
+
style: styles.skipText,
|
|
672
|
+
children: "Do not allow"
|
|
673
|
+
})
|
|
674
|
+
})]
|
|
675
|
+
}) : null, showReview && consentDeclined ? /*#__PURE__*/_jsxs(View, {
|
|
676
|
+
style: styles.consentSection,
|
|
677
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
678
|
+
style: styles.consentTitle,
|
|
679
|
+
children: "Access was not granted"
|
|
680
|
+
}), /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
681
|
+
style: styles.button,
|
|
682
|
+
onPress: () => setConsentDeclined(false),
|
|
683
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
684
|
+
style: styles.buttonText,
|
|
685
|
+
children: "Review again"
|
|
686
|
+
})
|
|
687
|
+
})]
|
|
688
|
+
}) : null]
|
|
375
689
|
}), onSkip ? /*#__PURE__*/_jsx(View, {
|
|
376
690
|
style: styles.footer,
|
|
377
691
|
children: /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
@@ -467,6 +781,9 @@ const styles = StyleSheet.create({
|
|
|
467
781
|
buttonDanger: {
|
|
468
782
|
backgroundColor: '#C4262E'
|
|
469
783
|
},
|
|
784
|
+
buttonDisabled: {
|
|
785
|
+
backgroundColor: '#A8A8A8'
|
|
786
|
+
},
|
|
470
787
|
buttonText: {
|
|
471
788
|
color: '#FFF',
|
|
472
789
|
fontWeight: '600',
|
|
@@ -522,5 +839,67 @@ const styles = StyleSheet.create({
|
|
|
522
839
|
alignItems: 'center',
|
|
523
840
|
justifyContent: 'center',
|
|
524
841
|
minHeight: 48
|
|
842
|
+
},
|
|
843
|
+
fieldGroup: {
|
|
844
|
+
marginTop: 12,
|
|
845
|
+
gap: 6
|
|
846
|
+
},
|
|
847
|
+
fieldLabel: {
|
|
848
|
+
color: '#333',
|
|
849
|
+
fontSize: 13,
|
|
850
|
+
fontWeight: '600'
|
|
851
|
+
},
|
|
852
|
+
textInput: {
|
|
853
|
+
minHeight: 42,
|
|
854
|
+
borderWidth: 1,
|
|
855
|
+
borderColor: '#C8C8C8',
|
|
856
|
+
borderRadius: 6,
|
|
857
|
+
paddingHorizontal: 10,
|
|
858
|
+
color: '#1A1A1A',
|
|
859
|
+
backgroundColor: '#FFF'
|
|
860
|
+
},
|
|
861
|
+
choiceRow: {
|
|
862
|
+
flexDirection: 'row',
|
|
863
|
+
flexWrap: 'wrap',
|
|
864
|
+
gap: 8
|
|
865
|
+
},
|
|
866
|
+
choiceButton: {
|
|
867
|
+
borderWidth: 1,
|
|
868
|
+
borderColor: '#C8C8C8',
|
|
869
|
+
borderRadius: 6,
|
|
870
|
+
paddingHorizontal: 10,
|
|
871
|
+
paddingVertical: 8
|
|
872
|
+
},
|
|
873
|
+
choiceButtonSelected: {
|
|
874
|
+
borderColor: '#0078D4',
|
|
875
|
+
backgroundColor: '#EFF6FC'
|
|
876
|
+
},
|
|
877
|
+
choiceText: {
|
|
878
|
+
color: '#333',
|
|
879
|
+
fontSize: 13
|
|
880
|
+
},
|
|
881
|
+
choiceTextSelected: {
|
|
882
|
+
color: '#0078D4',
|
|
883
|
+
fontSize: 13,
|
|
884
|
+
fontWeight: '600'
|
|
885
|
+
},
|
|
886
|
+
consentSection: {
|
|
887
|
+
marginTop: 12,
|
|
888
|
+
paddingTop: 16,
|
|
889
|
+
borderTopWidth: StyleSheet.hairlineWidth,
|
|
890
|
+
borderTopColor: '#D8D8D8'
|
|
891
|
+
},
|
|
892
|
+
consentTitle: {
|
|
893
|
+
fontSize: 18,
|
|
894
|
+
fontWeight: '700',
|
|
895
|
+
color: '#1A1A1A',
|
|
896
|
+
marginBottom: 12
|
|
897
|
+
},
|
|
898
|
+
consentItem: {
|
|
899
|
+
marginBottom: 12
|
|
900
|
+
},
|
|
901
|
+
consentActions: {
|
|
902
|
+
fontSize: 13,
|
|
903
|
+
color: '#444'
|
|
525
904
|
}
|
|
526
905
|
});
|