@brightlayer-ui/react-native-template-authentication-typescript 3.0.1-alpha.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -9
- package/README.md +10 -8
- package/package.json +2 -2
- package/template/.prettierrc.js +0 -2
- package/template/App.tsx +37 -9
- package/template/Gemfile +11 -2
- package/template/android/app/build.gradle +15 -14
- package/template/android/app/src/main/AndroidManifest.xml +2 -1
- package/template/android/app/src/main/java/com/example/MainApplication.kt +4 -11
- package/template/android/app/src/main/res/drawable/rn_edit_text_material.xml +2 -1
- package/template/android/build.gradle +6 -6
- package/template/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/template/android/gradle/wrapper/gradle-wrapper.properties +1 -1
- package/template/android/gradle.properties +1 -3
- package/template/android/gradlew +13 -11
- package/template/android/gradlew.bat +19 -12
- package/template/android/settings.gradle +3 -1
- package/template/babel.config.js +1 -1
- package/template/ios/Podfile +3 -27
- package/template/ios/Podfile.lock +2234 -662
- package/template/ios/example/AppDelegate.swift +48 -0
- package/template/ios/example/Info.plist +16 -26
- package/template/ios/example/PrivacyInfo.xcprivacy +37 -0
- package/template/ios/example.xcodeproj/project.pbxproj +26 -268
- package/template/ios/exampleTests/Info.plist +31 -18
- package/template/okta.config.js +10 -0
- package/template/package.json +55 -46
- package/template/src/components/UserMenuComponent.tsx +40 -5
- package/template/src/contexts/RegistrationContext.tsx +26 -0
- package/template/src/navigation/index.tsx +56 -61
- package/template/src/navigation/navigation-drawer.tsx +8 -9
- package/template/src/screens/ChangePassword.tsx +20 -4
- package/template/src/screens/OktaLogin.tsx +58 -0
- package/template/translations/i18n.ts +5 -5
- package/template/yarn.lock +8616 -0
- package/template/_gitignore +0 -64
- package/template/ios/example/AppDelegate.h +0 -6
- package/template/ios/example/AppDelegate.mm +0 -31
- package/template/ios/example/main.m +0 -10
- package/template/ios/exampleTests/exampleTests.m +0 -66
|
@@ -2,23 +2,36 @@
|
|
|
2
2
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
3
|
<plist version="1.0">
|
|
4
4
|
<dict>
|
|
5
|
-
<key>
|
|
6
|
-
<
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
5
|
+
<key>NSPrivacyAccessedAPITypes</key>
|
|
6
|
+
<array>
|
|
7
|
+
<dict>
|
|
8
|
+
<key>NSPrivacyAccessedAPIType</key>
|
|
9
|
+
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
|
|
10
|
+
<key>NSPrivacyAccessedAPITypeReasons</key>
|
|
11
|
+
<array>
|
|
12
|
+
<string>C617.1</string>
|
|
13
|
+
</array>
|
|
14
|
+
</dict>
|
|
15
|
+
<dict>
|
|
16
|
+
<key>NSPrivacyAccessedAPIType</key>
|
|
17
|
+
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
|
|
18
|
+
<key>NSPrivacyAccessedAPITypeReasons</key>
|
|
19
|
+
<array>
|
|
20
|
+
<string>CA92.1</string>
|
|
21
|
+
</array>
|
|
22
|
+
</dict>
|
|
23
|
+
<dict>
|
|
24
|
+
<key>NSPrivacyAccessedAPIType</key>
|
|
25
|
+
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
|
|
26
|
+
<key>NSPrivacyAccessedAPITypeReasons</key>
|
|
27
|
+
<array>
|
|
28
|
+
<string>35F9.1</string>
|
|
29
|
+
</array>
|
|
30
|
+
</dict>
|
|
31
|
+
</array>
|
|
32
|
+
<key>NSPrivacyCollectedDataTypes</key>
|
|
33
|
+
<array/>
|
|
34
|
+
<key>NSPrivacyTracking</key>
|
|
35
|
+
<false/>
|
|
23
36
|
</dict>
|
|
24
37
|
</plist>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
oidc: {
|
|
3
|
+
clientId: process.env.OKTA_CLIENT_ID,
|
|
4
|
+
redirectUri: process.env.OKTA_REDIRECT_URI,
|
|
5
|
+
endSessionRedirectUri: process.env.OKTA_LOGOUT_REDIRECT_URI,
|
|
6
|
+
discoveryUri: process.env.OKTA_ISSUER,
|
|
7
|
+
scopes: ['openid', 'profile', 'offline_access', 'groups'],
|
|
8
|
+
requireHardwareBackedKeyStore: false,
|
|
9
|
+
},
|
|
10
|
+
};
|
package/template/package.json
CHANGED
|
@@ -16,63 +16,72 @@
|
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@brightlayer-ui/colors": "^4.0.0",
|
|
19
|
-
"@brightlayer-ui/
|
|
20
|
-
"@brightlayer-ui/react-native-
|
|
21
|
-
"@brightlayer-ui/react-native-
|
|
22
|
-
"@react-native-
|
|
19
|
+
"@brightlayer-ui/icons-svg": "^1.15.0",
|
|
20
|
+
"@brightlayer-ui/react-native-auth-workflow": "^8.0.0",
|
|
21
|
+
"@brightlayer-ui/react-native-components": "^9.0.0",
|
|
22
|
+
"@brightlayer-ui/react-native-themes": "^8.0.0",
|
|
23
|
+
"@brightlayer-ui/react-native-vector-icons": "^3.0.0",
|
|
24
|
+
"@okta/okta-react-native": "^2.17.0",
|
|
25
|
+
"@react-native-async-storage/async-storage": "^2.2.0",
|
|
26
|
+
"@react-native-community/masked-view": "^0.1.11",
|
|
27
|
+
"@react-native-vector-icons/material-design-icons": "^12.2.0",
|
|
28
|
+
"@react-native-vector-icons/material-icons": "^12.2.0",
|
|
29
|
+
"@react-native/new-app-screen": "0.80.0",
|
|
23
30
|
"@react-navigation/drawer": "^6.6.6",
|
|
24
31
|
"@react-navigation/native": "^6.1.9",
|
|
25
32
|
"@react-navigation/native-stack": "^6.9.26",
|
|
26
33
|
"@react-navigation/stack": "^6.3.20",
|
|
27
|
-
"
|
|
34
|
+
"date-fns": "^4.1.0",
|
|
35
|
+
"i18next": "^25.2.1",
|
|
28
36
|
"intl-pluralrules": "^2.0.1",
|
|
29
|
-
"react": "
|
|
30
|
-
"react-i18next": "^
|
|
31
|
-
"react-native": "0.
|
|
32
|
-
"react-native-
|
|
33
|
-
"react-native-
|
|
34
|
-
"react-native-
|
|
35
|
-
"react-native-
|
|
37
|
+
"react": "^19.1.0",
|
|
38
|
+
"react-i18next": "^15.5.3",
|
|
39
|
+
"react-native": "^0.80.0",
|
|
40
|
+
"react-native-dotenv": "^3.4.11",
|
|
41
|
+
"react-native-gesture-handler": "^2.26.0",
|
|
42
|
+
"react-native-keyboard-aware-scroll-view": "^0.9.5",
|
|
43
|
+
"react-native-modal": "^13.0.2",
|
|
44
|
+
"react-native-pager-view": "^6.8.1",
|
|
45
|
+
"react-native-paper": "^5.14.5",
|
|
46
|
+
"react-native-reanimated": "^3.18.0",
|
|
36
47
|
"react-native-restart": "^0.0.27",
|
|
37
|
-
"react-native-safe-area-context": "^
|
|
38
|
-
"react-native-screens": "^
|
|
39
|
-
"react-native-select-dropdown": "^
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"react-native-keyboard-aware-scroll-view": "^0.9.3",
|
|
45
|
-
"react-native-modal": "^12.0.2",
|
|
46
|
-
"react-native-svg": "^12.1.0",
|
|
47
|
-
"react-native-svg-transformer": "^1.3.0",
|
|
48
|
-
"react-native-vector-icons": "^9.2.0",
|
|
49
|
-
"react-native-webview": "^13.8.1"
|
|
48
|
+
"react-native-safe-area-context": "^5.5.0",
|
|
49
|
+
"react-native-screens": "^4.11.1",
|
|
50
|
+
"react-native-select-dropdown": "^4.0.1",
|
|
51
|
+
"react-native-svg": "^15.12.0",
|
|
52
|
+
"react-native-svg-transformer": "^1.5.1",
|
|
53
|
+
"react-native-vector-icons": "^10.2.0",
|
|
54
|
+
"react-native-webview": "^13.15.0"
|
|
50
55
|
},
|
|
51
56
|
"devDependencies": {
|
|
52
|
-
"@babel/core": "^7.
|
|
53
|
-
"@babel/preset-env": "^7.
|
|
54
|
-
"@babel/runtime": "^7.
|
|
55
|
-
"@brightlayer-ui/eslint-config": "^
|
|
57
|
+
"@babel/core": "^7.27.7",
|
|
58
|
+
"@babel/preset-env": "^7.27.2",
|
|
59
|
+
"@babel/runtime": "^7.27.6",
|
|
60
|
+
"@brightlayer-ui/eslint-config": "^4.0.0",
|
|
56
61
|
"@brightlayer-ui/prettier-config": "^1.0.3",
|
|
57
|
-
"@react-native/
|
|
58
|
-
"@react-native/
|
|
59
|
-
"@react-native/
|
|
60
|
-
"@react-native/
|
|
61
|
-
"@
|
|
62
|
+
"@react-native-community/cli": "19.0.0",
|
|
63
|
+
"@react-native-community/cli-platform-android": "19.0.0",
|
|
64
|
+
"@react-native-community/cli-platform-ios": "19.0.0",
|
|
65
|
+
"@react-native/babel-preset": "0.80.0",
|
|
66
|
+
"@react-native/eslint-config": "0.80.0",
|
|
67
|
+
"@react-native/metro-config": "0.80.0",
|
|
68
|
+
"@react-native/typescript-config": "0.80.0",
|
|
69
|
+
"@types/jest": "^30.0.0",
|
|
70
|
+
"@types/react": "^19.1.8",
|
|
62
71
|
"@types/react-native-vector-icons": "^6.4.18",
|
|
63
|
-
"@types/react-test-renderer": "^
|
|
64
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
65
|
-
"@typescript-eslint/parser": "^
|
|
66
|
-
"babel-jest": "^
|
|
67
|
-
"eslint": "^
|
|
68
|
-
"eslint-config-prettier": "^
|
|
69
|
-
"eslint-plugin-react": "^7.
|
|
70
|
-
"eslint-plugin-react-hooks": "^
|
|
71
|
-
"jest": "^
|
|
72
|
+
"@types/react-test-renderer": "^19.1.0",
|
|
73
|
+
"@typescript-eslint/eslint-plugin": "^8.35.0",
|
|
74
|
+
"@typescript-eslint/parser": "^8.35.0",
|
|
75
|
+
"babel-jest": "^30.0.2",
|
|
76
|
+
"eslint": "^9.29.0",
|
|
77
|
+
"eslint-config-prettier": "^10.1.5",
|
|
78
|
+
"eslint-plugin-react": "^7.37.5",
|
|
79
|
+
"eslint-plugin-react-hooks": "^5.2.0",
|
|
80
|
+
"jest": "^30.0.3",
|
|
72
81
|
"jest-transform-stub": "^2.0.0",
|
|
73
|
-
"prettier": "
|
|
74
|
-
"react-test-renderer": "
|
|
75
|
-
"typescript": "5.
|
|
82
|
+
"prettier": "3.6.2",
|
|
83
|
+
"react-test-renderer": "19.1.0",
|
|
84
|
+
"typescript": "5.8.3"
|
|
76
85
|
},
|
|
77
86
|
"prettier": "@brightlayer-ui/prettier-config"
|
|
78
87
|
}
|
|
@@ -2,7 +2,6 @@ import { InfoListItemProps, UserMenu } from '@brightlayer-ui/react-native-compon
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { Avatar } from 'react-native-paper';
|
|
4
4
|
import * as BLUIColors from '@brightlayer-ui/colors';
|
|
5
|
-
import { IconFamily } from '@brightlayer-ui/react-native-components/core/__types__';
|
|
6
5
|
import SelectDropdown from 'react-native-select-dropdown';
|
|
7
6
|
import { useTranslation } from 'react-i18next';
|
|
8
7
|
import { useExtendedTheme } from '@brightlayer-ui/react-native-themes';
|
|
@@ -11,6 +10,8 @@ import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
|
11
10
|
import { LocalStorage } from '../store/local-storage';
|
|
12
11
|
import { useNavigation } from '@react-navigation/native';
|
|
13
12
|
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
|
|
13
|
+
import { revokeAccessToken, clearTokens, signOut } from '@okta/okta-react-native';
|
|
14
|
+
import { IconFamily } from '@brightlayer-ui/react-native-components/core/__types__';
|
|
14
15
|
|
|
15
16
|
const SwapIcon: IconFamily = {
|
|
16
17
|
family: 'material',
|
|
@@ -53,10 +54,43 @@ export const UserMenuComponent: React.FC<UserMenuExampleProps> = (props) => {
|
|
|
53
54
|
console.error('Error setting new language:', error);
|
|
54
55
|
}
|
|
55
56
|
};
|
|
56
|
-
const logout = (): void => {
|
|
57
|
+
const logout = async (): Promise<void> => {
|
|
58
|
+
// Clear local credentials first
|
|
57
59
|
LocalStorage.clearAuthCredentials();
|
|
60
|
+
|
|
61
|
+
// Try to sign out from Okta, but continue with local logout even if it fails
|
|
62
|
+
try {
|
|
63
|
+
await signOut();
|
|
64
|
+
} catch (signOutError) {
|
|
65
|
+
// eslint-disable-next-line no-console
|
|
66
|
+
console.error('Sign out from Okta failed:', signOutError);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
await revokeAccessToken();
|
|
71
|
+
} catch (revokeError) {
|
|
72
|
+
// eslint-disable-next-line no-console
|
|
73
|
+
console.error('Token revocation failed:', revokeError);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
await clearTokens();
|
|
78
|
+
} catch (clearError) {
|
|
79
|
+
// eslint-disable-next-line no-console
|
|
80
|
+
console.error('Clear tokens failed:', clearError);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Always proceed with local logout regardless of Okta errors
|
|
58
84
|
app.onUserNotAuthenticated();
|
|
59
85
|
};
|
|
86
|
+
const handleLogout = (): void => {
|
|
87
|
+
logout().catch((error) => {
|
|
88
|
+
// Handle any errors here if needed
|
|
89
|
+
console.error('Logout process failed:', error);
|
|
90
|
+
// Even if logout fails, ensure user is logged out locally
|
|
91
|
+
app.onUserNotAuthenticated();
|
|
92
|
+
});
|
|
93
|
+
};
|
|
60
94
|
const changePassword = (): void => {
|
|
61
95
|
navigation.navigate('ChangePassword');
|
|
62
96
|
};
|
|
@@ -81,8 +115,9 @@ export const UserMenuComponent: React.FC<UserMenuExampleProps> = (props) => {
|
|
|
81
115
|
rightComponent: (
|
|
82
116
|
<SelectDropdown
|
|
83
117
|
defaultValue={languageOptions.find((option) => option.value === i18n.language)}
|
|
84
|
-
|
|
85
|
-
|
|
118
|
+
onSelect={(item) => {
|
|
119
|
+
void handleLanguageChange(item.value);
|
|
120
|
+
}}
|
|
86
121
|
data={languageOptions}
|
|
87
122
|
buttonStyle={{ backgroundColor: theme.colors.background }}
|
|
88
123
|
buttonTextStyle={{ color: theme.colors.primary }}
|
|
@@ -95,7 +130,7 @@ export const UserMenuComponent: React.FC<UserMenuExampleProps> = (props) => {
|
|
|
95
130
|
),
|
|
96
131
|
},
|
|
97
132
|
{ title: t('USER_MENU.CHANGE_PASSWORD'), icon: LockIcon, onPress: (): void => changePassword() },
|
|
98
|
-
{ title: t('USER_MENU.LOG_OUT'), icon: ExitToAppIcon, onPress:
|
|
133
|
+
{ title: t('USER_MENU.LOG_OUT'), icon: ExitToAppIcon, onPress: handleLogout },
|
|
99
134
|
];
|
|
100
135
|
|
|
101
136
|
return (
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React, { createContext, useState, useContext, ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
type RegistrationContextType = {
|
|
4
|
+
isRequestingCode: number;
|
|
5
|
+
setIsRequestingCode: (value: number) => void;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const RegistrationContext = createContext<RegistrationContextType | undefined>(undefined);
|
|
9
|
+
|
|
10
|
+
export const RegistrationProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
|
|
11
|
+
const [isRequestingCode, setIsRequestingCode] = useState(0);
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<RegistrationContext.Provider value={{ isRequestingCode, setIsRequestingCode }}>
|
|
15
|
+
{children}
|
|
16
|
+
</RegistrationContext.Provider>
|
|
17
|
+
);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const useRegistrationContext = (): RegistrationContextType => {
|
|
21
|
+
const context = useContext(RegistrationContext);
|
|
22
|
+
if (!context) {
|
|
23
|
+
throw new Error('useRegistrationContext must be used within a RegistrationProvider');
|
|
24
|
+
}
|
|
25
|
+
return context;
|
|
26
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { ReactNode } from 'react';
|
|
1
|
+
import React, { ReactNode, useCallback } from 'react';
|
|
2
2
|
import { NavigationContainer, createNavigationContainerRef, useNavigation } from '@react-navigation/native';
|
|
3
3
|
import { useApp } from '../contexts/AppContextProvider';
|
|
4
4
|
import {
|
|
@@ -16,7 +16,6 @@ import { Dimensions, View } from 'react-native';
|
|
|
16
16
|
import { ProjectAuthUIActions } from '../actions/AuthUIActions';
|
|
17
17
|
import { ProjectRegistrationUIActions } from '../actions/RegistrationUIActions';
|
|
18
18
|
|
|
19
|
-
import { Login } from '../screens/Login';
|
|
20
19
|
import { ChangePassword } from '../screens/ChangePassword';
|
|
21
20
|
import { Registration } from '../screens/Registration';
|
|
22
21
|
import { RegistrationInvite } from '../screens/RegistrationInvite';
|
|
@@ -25,9 +24,11 @@ import { Homepage } from '../screens/Homepage';
|
|
|
25
24
|
import Locations from '../screens/Locations';
|
|
26
25
|
import Dashboard from '../screens/Dashboard';
|
|
27
26
|
import { NativeStackNavigationProp, createNativeStackNavigator } from '@react-navigation/native-stack';
|
|
27
|
+
import { OktaLogin } from '../screens/OktaLogin';
|
|
28
28
|
|
|
29
29
|
const Stack = createNativeStackNavigator();
|
|
30
30
|
const Drawer = createDrawerNavigator();
|
|
31
|
+
const LoginStack = createNativeStackNavigator();
|
|
31
32
|
const navigationRef = createNavigationContainerRef();
|
|
32
33
|
|
|
33
34
|
export type RootStackParamList = {
|
|
@@ -48,6 +49,57 @@ const AuthRouter = (): any => {
|
|
|
48
49
|
const { email, rememberMe } = app.loginData;
|
|
49
50
|
const navigation = useNavigation<NativeStackNavigationProp<any>>();
|
|
50
51
|
|
|
52
|
+
const LoginNavigatorComponent = useCallback(
|
|
53
|
+
() => (
|
|
54
|
+
<LoginStack.Navigator screenOptions={{ headerShown: false }}>
|
|
55
|
+
<LoginStack.Screen name="Login" component={OktaLogin} />
|
|
56
|
+
<LoginStack.Screen name="ForgotPassword" component={ForgotPasswordScreen} />
|
|
57
|
+
<LoginStack.Screen name="ResetPassword" component={ResetPasswordScreen} />
|
|
58
|
+
<LoginStack.Screen name="ContactSupport" component={ContactSupportScreen} />
|
|
59
|
+
</LoginStack.Navigator>
|
|
60
|
+
),
|
|
61
|
+
[]
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
const DrawerNavigatorComponent = (): any => (
|
|
65
|
+
<Drawer.Navigator
|
|
66
|
+
screenOptions={{
|
|
67
|
+
headerShown: false,
|
|
68
|
+
drawerType: 'front',
|
|
69
|
+
drawerStyle: { backgroundColor: 'transparent' },
|
|
70
|
+
}}
|
|
71
|
+
drawerContent={(props: any): ReactNode => <CustomDrawerContent {...props} />}
|
|
72
|
+
backBehavior="history"
|
|
73
|
+
initialRouteName="LoginScreen"
|
|
74
|
+
>
|
|
75
|
+
{!app.isAuthenticated && <Drawer.Screen name="LoginScreen" component={LoginNavigatorComponent} />}
|
|
76
|
+
|
|
77
|
+
{app.isAuthenticated && (
|
|
78
|
+
<>
|
|
79
|
+
<Drawer.Screen name="Homepage" component={Homepage} />
|
|
80
|
+
<Drawer.Screen name="Dashboard" component={Dashboard} />
|
|
81
|
+
<Drawer.Screen name="Locations" component={Locations} />
|
|
82
|
+
|
|
83
|
+
<Drawer.Screen
|
|
84
|
+
name="ContactSupport"
|
|
85
|
+
options={{
|
|
86
|
+
swipeEnabled: false,
|
|
87
|
+
}}
|
|
88
|
+
component={ContactSupportScreen}
|
|
89
|
+
/>
|
|
90
|
+
|
|
91
|
+
<Drawer.Screen
|
|
92
|
+
name="ChangePassword"
|
|
93
|
+
options={{
|
|
94
|
+
swipeEnabled: false,
|
|
95
|
+
}}
|
|
96
|
+
component={ChangePassword}
|
|
97
|
+
/>
|
|
98
|
+
</>
|
|
99
|
+
)}
|
|
100
|
+
</Drawer.Navigator>
|
|
101
|
+
);
|
|
102
|
+
|
|
51
103
|
return (
|
|
52
104
|
<>
|
|
53
105
|
<AuthContextProvider
|
|
@@ -79,65 +131,7 @@ const AuthRouter = (): any => {
|
|
|
79
131
|
}}
|
|
80
132
|
rememberMeDetails={{ email: rememberMe ? email : '', rememberMe: rememberMe }}
|
|
81
133
|
>
|
|
82
|
-
|
|
83
|
-
screenOptions={{
|
|
84
|
-
headerShown: false,
|
|
85
|
-
drawerType: 'front',
|
|
86
|
-
drawerStyle: { backgroundColor: 'transparent' },
|
|
87
|
-
}}
|
|
88
|
-
drawerContent={(props: any): ReactNode => <CustomDrawerContent {...props} />}
|
|
89
|
-
backBehavior="history"
|
|
90
|
-
initialRouteName="Login"
|
|
91
|
-
>
|
|
92
|
-
{!app.isAuthenticated && (
|
|
93
|
-
<Drawer.Screen
|
|
94
|
-
options={{
|
|
95
|
-
swipeEnabled: false,
|
|
96
|
-
}}
|
|
97
|
-
name="Login"
|
|
98
|
-
component={Login}
|
|
99
|
-
/>
|
|
100
|
-
)}
|
|
101
|
-
{!app.isAuthenticated && (
|
|
102
|
-
<Drawer.Screen
|
|
103
|
-
options={{
|
|
104
|
-
swipeEnabled: false,
|
|
105
|
-
}}
|
|
106
|
-
name="ForgotPassword"
|
|
107
|
-
component={ForgotPasswordScreen}
|
|
108
|
-
/>
|
|
109
|
-
)}
|
|
110
|
-
{!app.isAuthenticated && (
|
|
111
|
-
<Drawer.Screen
|
|
112
|
-
options={{
|
|
113
|
-
swipeEnabled: false,
|
|
114
|
-
}}
|
|
115
|
-
name="ResetPassword"
|
|
116
|
-
component={ResetPasswordScreen}
|
|
117
|
-
/>
|
|
118
|
-
)}
|
|
119
|
-
|
|
120
|
-
{app.isAuthenticated && <Drawer.Screen name="Homepage" component={Homepage} />}
|
|
121
|
-
{app.isAuthenticated && <Drawer.Screen name="Dashboard" component={Dashboard} />}
|
|
122
|
-
{app.isAuthenticated && <Drawer.Screen name="Locations" component={Locations} />}
|
|
123
|
-
|
|
124
|
-
<Drawer.Screen
|
|
125
|
-
name="ContactSupport"
|
|
126
|
-
options={{
|
|
127
|
-
swipeEnabled: false,
|
|
128
|
-
}}
|
|
129
|
-
component={ContactSupportScreen}
|
|
130
|
-
/>
|
|
131
|
-
{app.isAuthenticated && (
|
|
132
|
-
<Drawer.Screen
|
|
133
|
-
name="ChangePassword"
|
|
134
|
-
options={{
|
|
135
|
-
swipeEnabled: false,
|
|
136
|
-
}}
|
|
137
|
-
component={ChangePassword}
|
|
138
|
-
/>
|
|
139
|
-
)}
|
|
140
|
-
</Drawer.Navigator>
|
|
134
|
+
{DrawerNavigatorComponent()}
|
|
141
135
|
</AuthContextProvider>
|
|
142
136
|
</>
|
|
143
137
|
);
|
|
@@ -201,6 +195,7 @@ const RegistrationRouter = (): any => {
|
|
|
201
195
|
</>
|
|
202
196
|
);
|
|
203
197
|
};
|
|
198
|
+
|
|
204
199
|
export const MainRouter = (): any => {
|
|
205
200
|
const { height, width } = Dimensions.get('screen');
|
|
206
201
|
return (
|
|
@@ -1,24 +1,22 @@
|
|
|
1
|
-
import { Drawer, DrawerBody, DrawerHeader, DrawerNavGroup } from '@brightlayer-ui/react-native-components';
|
|
2
|
-
import React, { useState, useCallback, useEffect } from 'react';
|
|
1
|
+
import { Drawer, DrawerBody, DrawerHeader, DrawerNavGroup, NavItem } from '@brightlayer-ui/react-native-components';
|
|
2
|
+
import React, { useState, useCallback, useEffect, useMemo } from 'react';
|
|
3
|
+
import { StackNavigationProp } from '@react-navigation/stack';
|
|
3
4
|
import { RootStackParamList } from './index';
|
|
4
5
|
import { DrawerActions } from '@react-navigation/native';
|
|
5
6
|
import { useTranslation } from 'react-i18next';
|
|
6
7
|
import { IconFamily } from '@brightlayer-ui/react-native-components/core/__types__';
|
|
7
|
-
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
|
|
8
8
|
|
|
9
9
|
export type NavDrawerProps = {
|
|
10
|
-
navigation:
|
|
10
|
+
navigation: StackNavigationProp<RootStackParamList, 'NavigationDrawer'>;
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
export const NavigationDrawer: React.FC<NavDrawerProps> = ({ navigation }) => {
|
|
14
14
|
const [selected, setSelected] = useState('Home');
|
|
15
15
|
const { t } = useTranslation();
|
|
16
16
|
const navigationState = navigation.getState();
|
|
17
|
-
|
|
18
17
|
const Homepage: IconFamily = { family: 'material', name: 'home', direction: 'ltr' };
|
|
19
18
|
const Dashboard: IconFamily = { family: 'material', name: 'dashboard', direction: 'ltr' };
|
|
20
19
|
const Notifications: IconFamily = { family: 'material', name: 'notifications', direction: 'ltr' };
|
|
21
|
-
|
|
22
20
|
const selectItem = useCallback(
|
|
23
21
|
(id: any) => {
|
|
24
22
|
navigation.navigate(id);
|
|
@@ -27,8 +25,8 @@ export const NavigationDrawer: React.FC<NavDrawerProps> = ({ navigation }) => {
|
|
|
27
25
|
[navigation]
|
|
28
26
|
);
|
|
29
27
|
|
|
30
|
-
const navGroupItems =
|
|
31
|
-
() => [
|
|
28
|
+
const navGroupItems = useMemo(
|
|
29
|
+
(): NavItem[] => [
|
|
32
30
|
{
|
|
33
31
|
title: `${t('TOOLBAR_MENU.HOME_PAGE')}`,
|
|
34
32
|
itemID: 'Homepage',
|
|
@@ -45,7 +43,8 @@ export const NavigationDrawer: React.FC<NavDrawerProps> = ({ navigation }) => {
|
|
|
45
43
|
icon: Notifications,
|
|
46
44
|
},
|
|
47
45
|
],
|
|
48
|
-
|
|
46
|
+
|
|
47
|
+
[]
|
|
49
48
|
);
|
|
50
49
|
|
|
51
50
|
useEffect(() => {
|
|
@@ -2,14 +2,30 @@ import React from 'react';
|
|
|
2
2
|
import { ChangePasswordScreen } from '@brightlayer-ui/react-native-auth-workflow';
|
|
3
3
|
import { useApp } from '../contexts/AppContextProvider';
|
|
4
4
|
import { LocalStorage } from '../store/local-storage';
|
|
5
|
+
import { clearTokens, revokeAccessToken } from '@okta/okta-react-native';
|
|
5
6
|
|
|
6
|
-
export const ChangePassword = (): JSX.Element => {
|
|
7
|
+
export const ChangePassword = (): React.JSX.Element => {
|
|
7
8
|
const app = useApp();
|
|
8
|
-
const logOut = (): void => {
|
|
9
|
+
const logOut = async (): Promise<void> => {
|
|
9
10
|
LocalStorage.clearAuthCredentials();
|
|
11
|
+
try {
|
|
12
|
+
await revokeAccessToken();
|
|
13
|
+
await clearTokens();
|
|
14
|
+
} catch (_error) {
|
|
15
|
+
// eslint-disable-next-line no-console
|
|
16
|
+
console.log(_error as Error);
|
|
17
|
+
}
|
|
10
18
|
app.onUserNotAuthenticated();
|
|
11
|
-
|
|
19
|
+
// below line is not need for okta workflow
|
|
20
|
+
// app.setLoginData({ email: '', rememberMe: false });
|
|
12
21
|
};
|
|
13
22
|
|
|
14
|
-
|
|
23
|
+
const handleLogout = (): void => {
|
|
24
|
+
logOut().catch((error) => {
|
|
25
|
+
// Handle any errors here if needed
|
|
26
|
+
console.error(error);
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
return <ChangePasswordScreen onFinish={handleLogout} showSuccessScreen />;
|
|
15
31
|
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Image } from 'react-native';
|
|
3
|
+
import {
|
|
4
|
+
OktaAuthContextProvider,
|
|
5
|
+
OktaLoginScreenProps,
|
|
6
|
+
OktaRedirectLoginScreen,
|
|
7
|
+
} from '@brightlayer-ui/react-native-auth-workflow';
|
|
8
|
+
import { useApp } from '../contexts/AppContextProvider';
|
|
9
|
+
import { useNavigation } from '@react-navigation/native';
|
|
10
|
+
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
|
|
11
|
+
import i18nAppInstance from '../../translations/i18n';
|
|
12
|
+
import oktaConfig from '../../okta.config';
|
|
13
|
+
|
|
14
|
+
export const OktaLogin: React.FC<React.PropsWithChildren<OktaLoginScreenProps>> = () => {
|
|
15
|
+
const app = useApp();
|
|
16
|
+
const navigation = useNavigation<NativeStackNavigationProp<any>>();
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<OktaAuthContextProvider
|
|
20
|
+
language={app.language}
|
|
21
|
+
i18n={i18nAppInstance}
|
|
22
|
+
navigate={(destination: -1 | string) => {
|
|
23
|
+
if (typeof destination === 'string') {
|
|
24
|
+
switch (destination) {
|
|
25
|
+
case 'SelfRegister':
|
|
26
|
+
case 'RegisterInvite':
|
|
27
|
+
navigation.navigate('RegistrationProviderExample', { screen: destination });
|
|
28
|
+
break;
|
|
29
|
+
default:
|
|
30
|
+
navigation.navigate(destination);
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
} else if (destination === -1) {
|
|
34
|
+
navigation.goBack();
|
|
35
|
+
}
|
|
36
|
+
}}
|
|
37
|
+
routeConfig={{
|
|
38
|
+
LOGIN: 'Login',
|
|
39
|
+
FORGOT_PASSWORD: 'ForgotPassword',
|
|
40
|
+
RESET_PASSWORD: 'ResetPassword',
|
|
41
|
+
REGISTER_INVITE: 'RegisterInvite',
|
|
42
|
+
REGISTER_SELF: 'SelfRegister',
|
|
43
|
+
SUPPORT: 'ContactSupport',
|
|
44
|
+
}}
|
|
45
|
+
>
|
|
46
|
+
<OktaRedirectLoginScreen
|
|
47
|
+
projectImage={
|
|
48
|
+
<Image
|
|
49
|
+
style={{ width: '100%' }}
|
|
50
|
+
resizeMode="contain"
|
|
51
|
+
source={require('../assets/images/eaton_stacked_logo.png')}
|
|
52
|
+
/>
|
|
53
|
+
}
|
|
54
|
+
oktaConfigObject={oktaConfig.oidc}
|
|
55
|
+
/>
|
|
56
|
+
</OktaAuthContextProvider>
|
|
57
|
+
);
|
|
58
|
+
};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import i18next from 'i18next';
|
|
2
2
|
import { AppDictionaries } from './dictionary';
|
|
3
3
|
import { initReactI18next } from 'react-i18next';
|
|
4
|
-
import { NativeModules, Platform } from 'react-native';
|
|
4
|
+
// import { NativeModules, Platform } from 'react-native';
|
|
5
5
|
|
|
6
|
-
const locale =
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
const locale = 'en';
|
|
7
|
+
// Platform.OS === 'ios'
|
|
8
|
+
// ? NativeModules.SettingsManager.settings.AppleLocale
|
|
9
|
+
// : NativeModules.I18nManager.localeIdentifier;
|
|
10
10
|
void i18next
|
|
11
11
|
.use(initReactI18next) // passes i18n down to react-i18next
|
|
12
12
|
.init(
|