diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 6b4dca7..4b7acc9 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -43,6 +43,7 @@ "newString": "جديد", "setTheNewPassword": "قم بتعيين كلمة المرور الجديدة", "typeYourNewPasswordBelow": "اكتب كلمة المرور الجديدة أدناه", + "typeYourNewActiveDirectoryPasswordBelow": "اكتب كلمة مرور الدليل النشط الجديدة أدناه", "confirmPassword": "تأكيد كلمة المرور", "update": "تحديث", "title": "عنوان", @@ -527,5 +528,7 @@ "myTeam": "فريقي", "youCanPlayDemo": "لكن يمكنك لعب العرض", "connectHmgWifi": "قم بتوصيل HMG WIFI", - "connectedHmgWifi": "اتصال HMG WIFI" + "connectedHmgWifi": "اتصال HMG WIFI", + "itgForms": "نماذج (ITG)", + "resetAdPassword": "إعادة تعيين كلمة مرور AD" } \ No newline at end of file diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 3aa2705..3f460a1 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -43,6 +43,7 @@ "newString": "New", "setTheNewPassword": "Set the new password", "typeYourNewPasswordBelow": "Type your new password below", + "typeYourNewActiveDirectoryPasswordBelow": "Type new active directory password below", "confirmPassword": "Confirm Password", "update": "Update", "title": "Title", @@ -425,7 +426,7 @@ "typeCurrentPasswordBelow": "Type Your Current password below", "currentPassword": "Current password", "concurrentReports": "Concurrent Reports", - "EnterNewAddressMoved" : "Enter a new address if you have moved", + "EnterNewAddressMoved": "Enter a new address if you have moved", "CorrectAddress": "Correct or amend this address", "SelectChangeWantToMake": "Select the type of change you want to make", "profile": { @@ -470,7 +471,7 @@ "gameTime": "Game Time:", "joinMarathon": "Join Marathon", "joinDemoMarathon": "Join Demo Marathon", - "demo":"Demo", + "demo": "Demo", "minutes": "Minutes", "seconds": "Seconds", "note": "Note:", @@ -518,14 +519,16 @@ "startingIn": "Starting in", "youAreOutOfContest": "You are out of the contest.", "winners": "WINNERS!!!", - "expireAfter":"Expires After", - "oneWeek":"1 Week", - "twoWeek":"2 Week", + "expireAfter": "Expires After", + "oneWeek": "1 Week", + "twoWeek": "2 Week", "noUpcoming": "There is no upcoming", "fakeLocation": "We traced out that you try to use a fake location! This is considered a violation, and HR has been notified.", "noWinner": "Sad! No one won today.", - "myTeam" : "My Team", + "myTeam": "My Team", "youCanPlayDemo": "But you can play demo", "connectHmgWifi": "Connect HMG WIFI", - "connectedHmgWifi": "Connected HMG WIFI" + "connectedHmgWifi": "Connected HMG WIFI", + "itgForms": "ITG Forms", + "resetAdPassword": "Reset AD Password" } \ No newline at end of file diff --git a/lib/api/login_api_client.dart b/lib/api/login_api_client.dart index 7da7754..1b6b19e 100644 --- a/lib/api/login_api_client.dart +++ b/lib/api/login_api_client.dart @@ -145,4 +145,15 @@ class LoginApiClient { return responseData; }, url, postParams); } + + Future changePasswordFromActiveDirectorySession(String password, String email) async { + String url = "${ApiConsts.authenticationRest}SetPassword"; + Map postParams = {"EmailAddress": email, "Password": password, "generalid": "Cs2020@2016\$2958"}; + postParams.addAll(AppState().postParamsJson); + postParams["LogInTokenID"] = "@acT!V3D!r3Ct0rY"; // hard code token for active directory + return await ApiClient().postJsonForObject((json) { + GenericResponseModel responseData = GenericResponseModel.fromJson(json); + return responseData; + }, url, postParams); + } } diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 4d3025e..32b3fc7 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -8,6 +8,7 @@ class ApiConsts { static String baseUrlServices = baseUrl + "/Services/"; // server // static String baseUrlServices = "https://api.cssynapses.com/tangheem/"; // Live server static String utilitiesRest = baseUrlServices + "Utilities.svc/REST/"; + static String authenticationRest = baseUrlServices + "Authentication.svc/REST/"; static String erpRest = baseUrlServices + "ERP.svc/REST/"; static String swpRest = baseUrlServices + "SWP.svc/REST/"; static String user = baseUrlServices + "api/User/"; diff --git a/lib/config/routes.dart b/lib/config/routes.dart index 947bbcd..7ccb6ce 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -8,6 +8,7 @@ import 'package:mohem_flutter_app/ui/chat/chat_detailed_screen.dart'; import 'package:mohem_flutter_app/ui/chat/chat_home.dart'; import 'package:mohem_flutter_app/ui/chat/favorite_users_screen.dart'; import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart'; +import 'package:mohem_flutter_app/ui/landing/itg/change_itg_ad_password_screen.dart'; import 'package:mohem_flutter_app/ui/landing/itg/its_add_screen_video_image.dart'; import 'package:mohem_flutter_app/ui/landing/itg/survey_screen.dart'; import 'package:mohem_flutter_app/ui/landing/today_attendance_screen2.dart'; @@ -177,6 +178,7 @@ class AppRoutes { static const String subordinateLeave = "/subordinateLeave"; static const String changePassword = "/changePassword"; + static const String changeItgAdPasswordScreen = "/changeItgAdPasswordScreen"; //Chat static const String chat = "/chat"; @@ -289,7 +291,7 @@ class AppRoutes { subordinateLeave: (BuildContext context) => SubordinateLeave(), changePassword: (BuildContext context) => ChangePasswordScreen(), - + changeItgAdPasswordScreen: (BuildContext context) => ChangeItgAdPasswordScreen(), //Chat chat: (BuildContext context) => ChatHome(), chatDetailed: (BuildContext context) => ChatDetailScreen(), diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index 6a9040d..ba21c29 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -59,6 +59,7 @@ class CodegenLoader extends AssetLoader{ "newString": "جديد", "setTheNewPassword": "قم بتعيين كلمة المرور الجديدة", "typeYourNewPasswordBelow": "اكتب كلمة المرور الجديدة أدناه", + "typeYourNewActiveDirectoryPasswordBelow": "اكتب كلمة مرور الدليل النشط الجديدة أدناه", "confirmPassword": "تأكيد كلمة المرور", "update": "تحديث", "title": "عنوان", @@ -543,7 +544,9 @@ class CodegenLoader extends AssetLoader{ "myTeam": "فريقي", "youCanPlayDemo": "لكن يمكنك لعب العرض", "connectHmgWifi": "قم بتوصيل HMG WIFI", - "connectedHmgWifi": "اتصال HMG WIFI" + "connectedHmgWifi": "اتصال HMG WIFI", + "itgForms": "نماذج (ITG)", + "resetAdPassword": "إعادة تعيين كلمة مرور AD" }; static const Map en_US = { "mohemm": "Mohemm", @@ -590,6 +593,7 @@ static const Map en_US = { "newString": "New", "setTheNewPassword": "Set the new password", "typeYourNewPasswordBelow": "Type your new password below", + "typeYourNewActiveDirectoryPasswordBelow": "Type new active directory password below", "confirmPassword": "Confirm Password", "update": "Update", "title": "Title", @@ -1074,7 +1078,9 @@ static const Map en_US = { "myTeam": "My Team", "youCanPlayDemo": "But you can play demo", "connectHmgWifi": "Connect HMG WIFI", - "connectedHmgWifi": "Connected HMG WIFI" + "connectedHmgWifi": "Connected HMG WIFI", + "itgForms": "ITG Forms", + "resetAdPassword": "Reset AD Password" }; static const Map> mapLocales = {"ar_SA": ar_SA, "en_US": en_US}; } diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index 0e87cb4..343bf38 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -44,6 +44,7 @@ abstract class LocaleKeys { static const newString = 'newString'; static const setTheNewPassword = 'setTheNewPassword'; static const typeYourNewPasswordBelow = 'typeYourNewPasswordBelow'; + static const typeYourNewActiveDirectoryPasswordBelow = 'typeYourNewActiveDirectoryPasswordBelow'; static const confirmPassword = 'confirmPassword'; static const update = 'update'; static const title = 'title'; @@ -514,5 +515,7 @@ abstract class LocaleKeys { static const youCanPlayDemo = 'youCanPlayDemo'; static const connectHmgWifi = 'connectHmgWifi'; static const connectedHmgWifi = 'connectedHmgWifi'; + static const itgForms = 'itgForms'; + static const resetAdPassword = 'resetAdPassword'; } diff --git a/lib/provider/dashboard_provider_model.dart b/lib/provider/dashboard_provider_model.dart index d0f33df..0e18544 100644 --- a/lib/provider/dashboard_provider_model.dart +++ b/lib/provider/dashboard_provider_model.dart @@ -66,7 +66,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { if (attendanceTracking?.pSwipeIn != null) { isTimeRemainingInSeconds = calculateSeconds(attendanceTracking!.pRemainingHours ?? "00:00:00"); int totalShiftTimeInSeconds = calculateSeconds(attendanceTracking!.pScheduledHours ?? "00:00:00"); - if(isTimeRemainingInSeconds == 0 || totalShiftTimeInSeconds == 0) { + if (isTimeRemainingInSeconds == 0 || totalShiftTimeInSeconds == 0) { progress = 0; } else { progress = (isTimeRemainingInSeconds / totalShiftTimeInSeconds); @@ -245,7 +245,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } } - void getCategoryOffersListAPI(BuildContext context) async { + void getCategoryOffersListAPI(BuildContext context) async { try { // Utils.showLoading(context); getOffersList = await OffersAndDiscountsApiClient().getOffersList(0, 10); @@ -262,7 +262,25 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { List menus = []; for (int i = 0; i < getMenuEntriesList.length; i++) { if (getMenuEntriesList[i].parentMenuName!.isEmpty) { - menus.add(Menus(getMenuEntriesList[i], getMenuEntriesList.where((element) => getMenuEntriesList[i].menuName == element.parentMenuName).toList())); + GetMenuEntriesList abc = GetMenuEntriesList(requestType: "itg_forms", prompt: LocaleKeys.itgForms.tr()); + List list = getMenuEntriesList.where((element) => getMenuEntriesList[i].menuName == element.parentMenuName).toList(); + + if (getMenuEntriesList[i].menuName == "MBL_E_PROFESSIONALS_01") { + // hard coding this check to add change password for Active Directory + + GetMenuEntriesList activeDirectoryEntry = GetMenuEntriesList( + requestType: "RESET_ITG_AD_PASSWORD", + prompt: LocaleKeys.resetAdPassword.tr(), + parentMenuName: 'ITG_FORMS', + menuName: LocaleKeys.itgForms.tr(), + menuEntryType: "FUNCTION", //Reset AD Password + ); + getMenuEntriesList.add(activeDirectoryEntry); + + list.add(GetMenuEntriesList(requestType: "ITG_FORMS", prompt: LocaleKeys.itgForms.tr(), menuName: 'ITG_FORMS')); + } + + menus.add(Menus(getMenuEntriesList[i], list)); } } return menus; @@ -272,6 +290,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin { MohemmItgResponseItem? res = await DashboardApiClient().getITGPageNotification(); return res; } + void notify() { notifyListeners(); } diff --git a/lib/ui/landing/itg/change_itg_ad_password_screen.dart b/lib/ui/landing/itg/change_itg_ad_password_screen.dart new file mode 100644 index 0000000..cc84f96 --- /dev/null +++ b/lib/ui/landing/itg/change_itg_ad_password_screen.dart @@ -0,0 +1,166 @@ +import 'package:easy_localization/src/public_ext.dart'; +import 'package:flutter/material.dart'; +import 'package:mohem_flutter_app/api/login_api_client.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; +import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/classes/utils.dart'; +import 'package:mohem_flutter_app/extensions/int_extensions.dart'; +import 'package:mohem_flutter_app/extensions/string_extensions.dart'; +import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; +import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/models/generic_response_model.dart'; +import 'package:mohem_flutter_app/widgets/button/default_button.dart'; +import 'package:mohem_flutter_app/widgets/input_widget.dart'; + +class ChangeItgAdPasswordScreen extends StatefulWidget { + ChangeItgAdPasswordScreen({Key? key}) : super(key: key); + + @override + _ChangeItgAdPasswordScreenState createState() { + return _ChangeItgAdPasswordScreenState(); + } +} + +class _ChangeItgAdPasswordScreenState extends State { + TextEditingController password = TextEditingController(); + TextEditingController confirmPassword = TextEditingController(); + + @override + void initState() { + super.initState(); + } + + @override + void dispose() { + super.dispose(); + } + + void setNewPassword() async { + Utils.showLoading(context); + try { + GenericResponseModel response = await LoginApiClient().changePasswordFromActiveDirectorySession(password.text, AppState().memberInformationList!.eMPLOYEEEMAILADDRESS!); + Utils.hideLoading(context); + if ((response.messageStatus ?? 0) == 1) { + Utils.showToast(LocaleKeys.passwordChangedSuccessfully.tr()); + Navigator.pop(context); + } + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, (msg) { + Utils.confirmDialog(context, msg); + }); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Colors.transparent, + leading: IconButton( + icon: const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor), + onPressed: () => Navigator.pop(context), + ), + ), + body: Column( + children: [ + ListView( + padding: const EdgeInsets.all(21), + children: [ + LocaleKeys.changePassword.tr().toText24(isBold: true), + LocaleKeys.typeYourNewActiveDirectoryPasswordBelow.tr().toText16(), + 16.height, + InputWidget( + LocaleKeys.password.tr(), + "**********", + password, + onChange: (value) { + setState(() {}); + }, + ), + 12.height, + InputWidget( + LocaleKeys.confirmPassword.tr(), + "**********", + confirmPassword, + isTextIsPassword: true, + onChange: (value) { + setState(() {}); + }, + ), + 16.height, + passwordConstraintsUI(LocaleKeys.doNotUseRecentPassword.tr(), true), + 8.height, + passwordConstraintsUI(LocaleKeys.atLeastOneLowercase.tr(), checkRegEx(r'[a-z]')), + // 8.height, + // passwordConstraintsUI(LocaleKeys.atLeastOneUppercase.tr(), checkRegEx(r'[A-Z]')), + 8.height, + passwordConstraintsUI(LocaleKeys.atLeastOneNumeric.tr(), checkRegEx(r'[0-9]')), + 8.height, + passwordConstraintsUI(LocaleKeys.minimum8Characters.tr(), password.text.length >= 8), + 8.height, + passwordConstraintsUI(LocaleKeys.doNotAddRepeatingLetters.tr(), checkRepeatedChars(password.text)), + // 8.height, + // passwordConstraintsUI(LocaleKeys.itShouldContainSpecialCharacter.tr(), checkRegEx(r'[!@#$%^&*(),.?":{}|<>]')), + 8.height, + passwordConstraintsUI(LocaleKeys.confirmPasswordMustMatch.tr(), password.text.isNotEmpty && password.text == confirmPassword.text), + ], + ).expanded, + DefaultButton(LocaleKeys.changePassword.tr(), (!isPasswordCompliant(password.text, 8)) ? null : setNewPassword).insideContainer + ], + ), + ); + } + + bool checkRegEx(String pattern) { + return RegExp(pattern).hasMatch(password.text); + } + + String recentPassword = ""; + + bool isPasswordCompliant(String? password, int minLength) { + if (password == null || password.isEmpty) { + return false; + } + + // bool hasUppercase = password.contains(RegExp(r'[A-Z]')); + bool hasDigits = password.contains(RegExp(r'[0-9]')); + bool hasLowercase = password.contains(RegExp(r'[a-z]')); + // bool hasSpecialCharacters = password.contains(RegExp(r'[!@#$%^&*(),.?":{}|<>]')); + bool hasMinLength = password.length >= minLength; + bool isMatched = password == confirmPassword.text; + + return hasDigits && hasLowercase && hasMinLength && isMatched && checkRepeatedChars(password); + } + + bool checkRepeatedChars(String password) { + bool isNonRepeatedLetters = true; + if (password.length > 2) { + for (int i = 0; i < password.length; i++) { + String char = password[i]; + try { + if (char == password[i + 1]) { + isNonRepeatedLetters = false; + break; + } + } catch (ex) {} + } + } + return isNonRepeatedLetters; + } + + Widget passwordConstraintsUI(String description, bool check) { + return Row( + children: [ + 4.width, + SizedBox( + width: 12, + height: 12, + child: Checkbox(fillColor: MaterialStateProperty.all(MyColors.gradiantEndColor), shape: const CircleBorder(), value: check, onChanged: null), + ), + 8.width, + description.toText14() + ], + ); + } +} diff --git a/lib/ui/my_attendance/services_menu_list_screen.dart b/lib/ui/my_attendance/services_menu_list_screen.dart index 8e44324..44aac6a 100644 --- a/lib/ui/my_attendance/services_menu_list_screen.dart +++ b/lib/ui/my_attendance/services_menu_list_screen.dart @@ -57,6 +57,9 @@ class ServicesMenuListScreen extends StatelessWidget { } else if (servicesMenuData.list[index].requestType == "ABSENCE") { Navigator.pushNamed(context, AppRoutes.leaveBalance, arguments: servicesMenuData.selectedEmp); return; + } else if (servicesMenuData.list[index].requestType == "RESET_ITG_AD_PASSWORD") { + Navigator.pushNamed(context, AppRoutes.changeItgAdPasswordScreen); + return; } if (servicesMenuData.list[index].requestType == "EIT") { Navigator.pushNamed(context, AppRoutes.dynamicScreen,