upload method

Future<List<FileResource>?> upload(
  1. dynamic callback(
    1. RequestProgress,
    2. bool
    ), {
  2. Dio? dioTestClient,
})

Implementation

Future<List<FileResource>?> upload(Function(RequestProgress, bool) callback,
    {Dio? dioTestClient}) async {
  callback(
      RequestProgress(
          resourceName: this.apiResourceName as String,
          message:
              'Retrieving ${this.apiResourceName?.toLowerCase()} from phone database....',
          status: '',
          percentage: 0),
      false);
  List<FileResource> fileResources =
      await this.where(attribute: 'synced', value: false).get();

  callback(
      RequestProgress(
          resourceName: this.apiResourceName as String,
          message:
              '${fileResources.length} ${this.apiResourceName?.toLowerCase()} retrieved successfully',
          status: '',
          percentage: 50),
      false);

  callback(
      RequestProgress(
          resourceName: this.apiResourceName as String,
          message:
              'Uploading ${fileResources.length} ${this.apiResourceName?.toLowerCase()} into the server...',
          status: '',
          percentage: 51),
      false);

  final uploadQueue = Queue(parallel: 50);
  num availableUploadItemCount = 0;
  List fileResourceResponses = [];

  fileResources.forEach((fileResource) async {
    final mimeType =
        lookupMimeType(fileResource.localFilePath)?.split('/') ?? [];
    availableUploadItemCount++;
    var formData = FormData.fromMap({
      'file': await MultipartFile.fromFile(fileResource.localFilePath,
          contentType: MediaType(mimeType[0], mimeType[1]))
    });
    uploadQueue.add(() async {
      final fileResourceResponse = await HttpClient.post(
          this.apiResourceName as String, formData,
          database: this.database, dioTestClient: dioTestClient);
      fileResourceResponses.add({
        'fileResourceId': fileResource.id,
        'fileResourceResponse': fileResourceResponse.body
      });
      return fileResourceResponse;
    });
  });

  if (availableUploadItemCount == 0) {
    uploadQueue.cancel();
  } else {
    await uploadQueue.onComplete;
  }

  callback(
      RequestProgress(
          resourceName: this.apiResourceName as String,
          message:
              'Upload for ${fileResources.length} ${this.apiResourceName?.toLowerCase()} is completed.',
          status: '',
          percentage: 75),
      true);

  callback(
      RequestProgress(
          resourceName: this.apiResourceName as String,
          message: 'Saving import summaries into the phone database...',
          status: '',
          percentage: 76),
      true);

  final queue = Queue(parallel: 50);
  final formValueUpdateQueue = Queue(parallel: 50);
  num availableItemCount = 0;
  num availableElementCount = 0;

  fileResources.forEach((fileResource) {
    final fileResourceResponse = fileResourceResponses.lastWhere(
        (response) => response['fileResourceId'] == fileResource.id,
        orElse: (() => null));

    if (fileResourceResponse != null) {
      final importSummary = fileResourceResponse['fileResourceResponse'];
      availableItemCount++;
      final resourceId = importSummary['response']?['fileResource']?['id'];

      final syncFailed = importSummary['status'] != 'OK';
      fileResource.synced = !syncFailed;
      fileResource.dirty = true;
      fileResource.syncFailed = syncFailed;
      fileResource.resourceId = resourceId;
      fileResource.storageStatus =
          importSummary['response']?['fileResource']?['storageStatus'];
      fileResource.lastSyncDate = DateTime.now().toIso8601String();
      fileResource.lastSyncSummary = importSummary.toString();
      queue.add(() =>
          FileResourceQuery(database: database).setData(fileResource).save());

      if (resourceId != null) {
        switch (fileResource.elementType) {
          case 'TRACKED_ENTITY_ATTRIBUTE':
            availableElementCount++;
            formValueUpdateQueue.add(() => this
                .updateTrackedEntityAttributeValue(
                    attribute: fileResource.elementId,
                    trackedEntityInstance: fileResource.formInstance,
                    resourceId: resourceId));
            break;
          case 'DATA_ELEMENT':
            availableElementCount++;
            formValueUpdateQueue.add(() => this.updateDataElementValue(
                dataElement: fileResource.elementId,
                event: fileResource.formInstance,
                resourceId: resourceId));
            break;
          default:
            break;
        }
      }
    }
  });

  if (availableItemCount == 0) {
    queue.cancel();
  } else {
    await queue.onComplete;
  }

  callback(
      RequestProgress(
          resourceName: this.apiResourceName as String,
          message: 'Import summaries saved succussfully',
          status: '',
          percentage: 85),
      true);

  if (availableElementCount == 0) {
    formValueUpdateQueue.cancel();
  } else {
    await formValueUpdateQueue.onComplete;
  }

  return await FileResourceQuery(database: database)
      .byIds(fileResources
          .map((fileResource) => fileResource.id as String)
          .toList())
      .get();
}