Merge branch 'master' into development_sikander

development_sikander
Sikander Saleem 9 months ago
commit df07a5f9f6

@ -21,6 +21,7 @@ import 'package:mohem_flutter_app/models/get_quotation_analysis_list_model.dart'
import 'package:mohem_flutter_app/models/get_stamp_ms_notification_body_list_model.dart';
import 'package:mohem_flutter_app/models/get_stamp_ns_notification_body_list_model.dart';
import 'package:mohem_flutter_app/models/get_user_item_type_list.dart';
import 'package:mohem_flutter_app/models/itg_forms_models/itg_forms_attachments_model.dart';
import 'package:mohem_flutter_app/models/itg_forms_models/itg_request_model.dart';
import 'package:mohem_flutter_app/models/member_information_list_model.dart';
import 'package:mohem_flutter_app/models/notification_get_respond_attributes_list_model.dart';
@ -364,6 +365,21 @@ class WorkListApiClient {
}, url, postParams);
}
Future<List<ITGFormsAttachmentsModel>?> getITGFormAttachments(String requestType, taskId, itemId, String employeeNumber) async {
String url = "${ApiConsts.cocRest}ITGGetFormDetialsAttachment";
Map<String, dynamic> postParams = {
"RequestType": requestType,
"TaskID": taskId,
"ItemIDStr": itemId,
"EmployeeNumber": employeeNumber,
};
postParams.addAll(AppState().postParamsJson);
return await ApiClient().postJsonForObject((json) {
ItgFormsModel responseData = ItgFormsModel.fromJson(json);
return responseData.itgFormAttachmentsList;
}, url, postParams);
}
Future<ITGRequest?> rejectITGRequest(String requestType, taskId, itemId, String employeeNumber, String comments) async {
String url = "${ApiConsts.cocRest}ITGRejectRequest";
Map<String, dynamic> postParams = {

@ -68,8 +68,9 @@ extension EmailValidator on String {
style: TextStyle(fontSize: 10, fontStyle: fontStyle ?? FontStyle.normal, fontWeight: isBold ? FontWeight.bold : FontWeight.w600, color: color ?? MyColors.darkTextColor, letterSpacing: -0.4),
);
Widget toText11({Color? color, FontWeight? weight, bool isUnderLine = false, bool isBold = false, int maxLine = 0}) => Text(
Widget toText11({Color? color, FontWeight? weight, bool isUnderLine = false, bool isBold = false, bool isCenter = false, int maxLine = 0}) => Text(
this,
textAlign: isCenter ? TextAlign.center : null,
maxLines: (maxLine > 0) ? maxLine : null,
style: TextStyle(
fontSize: 11,

@ -4,6 +4,7 @@
import 'dart:convert';
import 'package:mohem_flutter_app/models/itg_forms_models/itg_forms_attachments_model.dart';
import 'package:mohem_flutter_app/models/itg_forms_models/itg_request_model.dart';
import 'package:mohem_flutter_app/models/itg_forms_models/request_type_model.dart';
@ -84,7 +85,8 @@ class ItgFormsModel {
dynamic successMsgN;
dynamic vidaUpdatedResponse;
ITGRequest? itgRequest;
dynamic itgFormAttachmentsList;
// dynamic itgFormAttachmentsList;
List<ITGFormsAttachmentsModel>? itgFormAttachmentsList;
String? message;
dynamic mohemmItgDepartmentSectionsList;
dynamic mohemmItgProjectDepartmentsList;
@ -128,7 +130,11 @@ class ItgFormsModel {
successMsgN: json["SuccessMsgN"],
vidaUpdatedResponse: json["VidaUpdatedResponse"],
itgRequest: json['ITGRequest'] != null ? ITGRequest.fromJson(json['ITGRequest']) : null,
itgFormAttachmentsList: json["Itg_FormAttachmentsList"],
itgFormAttachmentsList:
json["Itg_FormAttachmentsList"] == null ? <ITGFormsAttachmentsModel>[] : json["Itg_FormAttachmentsList"]!.map<ITGFormsAttachmentsModel>((v) => ITGFormsAttachmentsModel.fromJson(v)).toList(),
// json["RequestType"] == null ? <RequestType>[] : json['RequestType']!.map<RequestType>((v) => RequestType.fromJson(v)).toList(),
message: json["Message"] == null ? null : json["Message"],
mohemmItgDepartmentSectionsList: json["Mohemm_ITG_DepartmentSectionsList"],
mohemmItgProjectDepartmentsList: json["Mohemm_ITG_ProjectDepartmentsList"],

@ -0,0 +1,25 @@
class ITGFormsAttachmentsModel {
String? fileBase64;
dynamic fileData;
String? fileName;
String? fileType;
ITGFormsAttachmentsModel(
{this.fileBase64, this.fileData, this.fileName, this.fileType});
ITGFormsAttachmentsModel.fromJson(Map<String, dynamic> json) {
fileBase64 = json['fileBase64'];
fileData = json['fileData'];
fileName = json['fileName'];
fileType = json['fileType'];
}
Map<String, dynamic> toJson() {
Map<String, dynamic> data = new Map<String, dynamic>();
data['fileBase64'] = this.fileBase64;
data['fileData'] = this.fileData;
data['fileName'] = this.fileName;
data['fileType'] = this.fileType;
return data;
}
}

@ -102,8 +102,8 @@ class _NewPasswordScreenState extends State<NewPasswordScreen> {
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'^[a-zA-Z0-9]+$')),
// 8.height,
// passwordConstraintsUI(LocaleKeys.itShouldContainSpecialCharacter.tr(), checkRegEx(r'^[a-zA-Z0-9]+$')),
8.height,
passwordConstraintsUI(LocaleKeys.confirmPasswordMustMatch.tr(), password.text.isNotEmpty && password.text == confirmPassword.text),
],

@ -3,6 +3,7 @@ import 'dart:convert';
import 'package:easy_localization/src/public_ext.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:lottie/lottie.dart';
import 'package:mohem_flutter_app/api/worklist/worklist_api_client.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
@ -12,10 +13,12 @@ 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/itg_forms_models/allowed_actions_model.dart';
import 'package:mohem_flutter_app/models/itg_forms_models/itg_forms_attachments_model.dart';
import 'package:mohem_flutter_app/models/itg_forms_models/itg_request_model.dart';
import 'package:mohem_flutter_app/models/itg_forms_models/request_detail_model.dart';
import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart';
import 'package:mohem_flutter_app/ui/work_list/itg_fragments/approval_level_fragment.dart';
import 'package:mohem_flutter_app/ui/work_list/itg_fragments/attachments_fragment.dart';
import 'package:mohem_flutter_app/ui/work_list/itg_fragments/request_detail_fragment.dart';
import 'package:mohem_flutter_app/ui/work_list/sheets/delegate_sheet.dart';
import 'package:mohem_flutter_app/widgets/app_bar_widget.dart';
@ -44,9 +47,12 @@ class _ItgDetailScreenState extends State<ItgDetailScreen> {
bool isRejectAvailable = false;
List<AllowedActions> allowedActionList = [];
List<ITGFormsAttachmentsModel> itgFormAttachmentsList = [];
late DashboardProviderModel providerData;
bool isAttachmentLoaded = false;
@override
void initState() {
providerData = Provider.of<DashboardProviderModel>(context, listen: false);
@ -87,6 +93,7 @@ class _ItgDetailScreenState extends State<ItgDetailScreen> {
requestDetails = AppState().requestAllList![AppState().itgWorkListIndex!]; // ModalRoute.of(context)!.settings.arguments as WorkListResponseModel;
providerData.itgFormsModel!.totalCount = providerData.itgFormsModel!.totalCount! - 1;
getItgData();
getItgRequestAttachments();
}
}
@ -140,6 +147,7 @@ class _ItgDetailScreenState extends State<ItgDetailScreen> {
myTab(LocaleKeys.requestDetails.tr(), 0),
myTab(LocaleKeys.approvalLevel.tr(), 1),
myTab(LocaleKeys.requesterDetails.tr(), 2),
myTab(LocaleKeys.attachments.tr(), 3),
],
),
),
@ -157,6 +165,11 @@ class _ItgDetailScreenState extends State<ItgDetailScreen> {
voidCallback: reloadITG,
),
RequestDetailFragment(fields: itgRequest?.fieldGoups?[0].fields ?? []),
isAttachmentLoaded
? itgFormAttachmentsList.isEmpty
? Utils.getNoDataWidget(context)
: ITGAttachmentsFragment(itgFormAttachmentsList)
: showLoadingAnimation(),
],
).expanded,
if (isApproveAvailable || isRejectAvailable || isCloseAvailable)
@ -405,7 +418,7 @@ class _ItgDetailScreenState extends State<ItgDetailScreen> {
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
title.toText12(color: isSelected ? Colors.white : Colors.white.withOpacity(.74), isCenter: true),
title.toText11(color: isSelected ? Colors.white : Colors.white.withOpacity(.74), isCenter: true),
4.height,
Container(
height: 8,
@ -478,7 +491,7 @@ class _ItgDetailScreenState extends State<ItgDetailScreen> {
);
}
void performAnswerAction(String requestType, taskId, itemId, String employeeNumber, String comments) async {
void performAnswerAction(String requestType, taskId, itemId, String employeeNumber, String comments) async {
try {
Utils.showLoading(context);
ITGRequest? itgRequest = await WorkListApiClient().answerITGRequest(requestType, taskId, itemId, employeeNumber, "", comments);
@ -502,7 +515,7 @@ class _ItgDetailScreenState extends State<ItgDetailScreen> {
}
}
void performRejectAction(String requestType, taskId, itemId, String employeeNumber, String comments) async {
void performRejectAction(String requestType, taskId, itemId, String employeeNumber, String comments) async {
try {
Utils.showLoading(context);
ITGRequest? itgRequest = await WorkListApiClient().rejectITGRequest(requestType, taskId, itemId, employeeNumber, comments);
@ -526,7 +539,7 @@ class _ItgDetailScreenState extends State<ItgDetailScreen> {
}
}
void performApproveAction(String requestType, taskId, itemId, String employeeNumber, String comments) async {
void performApproveAction(String requestType, taskId, itemId, String employeeNumber, String comments) async {
try {
Utils.showLoading(context);
ITGRequest? itgRequest = await WorkListApiClient().approveITGRequest(requestType, taskId, itemId, employeeNumber, comments);
@ -576,6 +589,35 @@ class _ItgDetailScreenState extends State<ItgDetailScreen> {
}
}
Widget showLoadingAnimation() {
return Lottie.asset(
'assets/lottie/loading.json',
repeat: true,
reverse: false,
);
}
void getItgRequestAttachments() async {
try {
// Utils.showLoading(context);
itgFormAttachmentsList =
(await WorkListApiClient().getITGFormAttachments(requestDetails!.requestType!, requestDetails!.iD, requestDetails!.itemID, AppState().memberInformationList?.eMPLOYEENUMBER ?? ""))!;
// allowedActionList = itgRequest?.allowedActions ?? [];
// if (allowedActionList.isNotEmpty) {
// isCloseAvailable = allowedActionList.any((element) => element.action == "CLOSE");
// isApproveAvailable = itgRequest!.allowedActions!.any((element) => element.action == "Approve");
// isRejectAvailable = itgRequest!.allowedActions!.any((element) => element.action == "Reject");
// }
// Utils.hideLoading(context);
setState(() {
isAttachmentLoaded = true;
});
} catch (ex) {
Utils.hideLoading(context);
Utils.handleException(ex, context, null);
}
}
void reloadITG() {
animationIndex = animationIndex + 1;
AppState().requestAllList!.removeAt(AppState().itgWorkListIndex!);

@ -0,0 +1,100 @@
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.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/models/itg_forms_models/itg_forms_attachments_model.dart';
import 'package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart';
import 'package:open_file/open_file.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
class ITGAttachmentsFragment extends StatelessWidget {
List<ITGFormsAttachmentsModel> itgFormAttachmentsList;
ITGAttachmentsFragment(this.itgFormAttachmentsList);
@override
Widget build(BuildContext context) {
return ListView.separated(
itemCount: itgFormAttachmentsList.length,
itemBuilder: (context, index) {
return Row(
children: [
SvgPicture.asset(determineFileIcon(itgFormAttachmentsList[index].fileType ?? "")),
12.width,
(itgFormAttachmentsList[index].fileName ?? "").toText16().expanded,
],
).objectContainerView().onPress(() async {
try {
Permission.storage.isGranted.then(
(isGranted) {
if (!isGranted) {
Permission.manageExternalStorage.request().then(
(granted) async {
if (granted == PermissionStatus.granted) {
String path = await _createFileFromString(itgFormAttachmentsList[index].fileBase64 ?? "", itgFormAttachmentsList[index].fileType ?? "");
OpenFile.open(path);
} else {
showDialog(
context: context,
builder: (BuildContext cxt) => ConfirmDialog(
message: "You need to give storage permission to view files.",
onTap: () {
Navigator.pop(context);
},
),
);
}
},
);
}
},
);
} catch (ex) {
Utils.showToast("Cannot open file.");
}
});
},
separatorBuilder: (BuildContext context, int index) => 12.height,
).paddingAll(21);
}
String determineFileIcon(String fileContentType) {
String icon = "";
switch (fileContentType) {
case "pdf":
icon = "assets/images/pdf.svg";
break;
case "xls":
icon = "assets/images/xls.svg";
break;
case "xlsx":
icon = "assets/images/xls.svg";
break;
case "png":
icon = "assets/images/png.svg";
break;
case "jpg":
icon = "assets/images/jpg.svg";
break;
case "jpeg":
icon = "assets/images/jpg.svg";
break;
}
return icon;
}
Future<String> _createFileFromString(String encodedStr, String ext) async {
Uint8List bytes = base64.decode(encodedStr);
String dir = (await getApplicationDocumentsDirectory()).path;
File file = File("$dir/" + DateTime.now().millisecondsSinceEpoch.toString() + "." + ext);
await file.writeAsBytes(bytes);
return file.path;
}
}

@ -9,8 +9,10 @@ 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/models/get_attachement_list_model.dart';
import 'package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart';
import 'package:open_file/open_file.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
class AttachmentsFragment extends StatelessWidget {
final List<GetAttachementList> getAttachmentList;
@ -30,9 +32,32 @@ class AttachmentsFragment extends StatelessWidget {
],
).objectContainerView().onPress(() async {
try {
String path = await _createFileFromString(getAttachmentList[index].fILEDATA ?? "", getAttachmentList[index].fILECONTENTTYPE ?? "");
OpenFile.open(path);
} catch (ex) {Utils.showToast("Cannot open file.");
Permission.storage.isGranted.then(
(isGranted) {
if (!isGranted) {
Permission.manageExternalStorage.request().then(
(granted) async {
if (granted == PermissionStatus.granted) {
String path = await _createFileFromString(getAttachmentList[index].fILEDATA ?? "", getAttachmentList[index].fILECONTENTTYPE ?? "");
OpenFile.open(path);
} else {
showDialog(
context: context,
builder: (BuildContext cxt) => ConfirmDialog(
message: "You need to give storage permission to view files.",
onTap: () {
Navigator.pop(context);
},
),
);
}
},
);
}
},
);
} catch (ex) {
Utils.showToast("Cannot open file.");
}
});
},

Loading…
Cancel
Save