You are currently viewing Implementing Event Export API in Open Event Frontend

Implementing Event Export API in Open Event Frontend

In Open Event Frontend, a user can export a particular event in the zip format and download that. While dealing with an issue, we had to implement the facility of exporting the event and downloading it with a single click of button. We achieved it as follows:

The endpoints for the event export API return the responses which are not in the format of the JSON API response as we have for others like tickets, events, etc. Their responses are just the JSON objects which are not having any relationship with any model. We have four checkboxes in our template component which are used to customise the data to be present in the zip file which is to be exported. The component name is ‘download-zip’. The content of which are the checkboxes as follows:

<div class="ui form">
  <div class="field">
    {{ui-checkbox class='toggle' label=(t 'Image') checked=data.exportData.dataImage onChange=(action (mut data.exportData.dataImage))}}
  </div>
  <div class="field">
    {{ui-checkbox class='toggle' label=(t 'Video') checked=data.exportData.dataVideo onChange=(action (mut data.exportData.dataVideo))}}
  </div>
  <div class="field">
    {{ui-checkbox class='toggle' label=(t 'Audio') checked=data.exportData.dataAudio onChange=(action (mut data.exportData.dataAudio))}}
  </div>
  <div class="field">
    {{ui-checkbox class='toggle' label=(t 'Document') checked=data.exportData.dataDocument onChange=(action (mut data.exportData.dataDocument))}}
  </div>
  <div class="ui basic segment less left padding">
    <button class="ui blue button" {{action 'startGeneration'}}>
      {{t 'Start'}}
    </button>
    <button class="ui button">
      {{t 'Download'}}
    </button>
  </div>
</div>

Thus, the above code shows the four checkboxes namely audio, video, image, document used to customise the zip file generated. We also have a ‘start’ button which is used to trigger the event export. On clicking the ‘start’ button, we are handling an action called ‘startGeneration’ where we make the requests to the server which returns the event download links in response. The action is being handled in the parent controller i.e export.js.

startGeneration() {
      this.set('isLoading', true);
      let payload = this.get('data');
      this.get('loader')
        .post(`/events/${this.get('model.id')}/export/json`, payload)
        .then(exportJobInfo => {
          this.requestLoop(exportJobInfo);
        })
        .catch(() => {
          this.get('notify').error(this.l10n.t('Unexpected error occurred.'));
        });
}

As we can see, we are getting the payload from the form in the template which is shown previously above. Since the response we get from the server is not JSON API formatted, we cannot use the ember data to make requests and get a response. Thus, we use an add on called ‘loader’ which is used to make requests and get responses.
As per the server, to obtain the download URL of an event, first, we make a POST request to the URL shown in the code above with the payload that we get from the form.
On getting the response, we resolve the promise by calling the method on the same controller called ‘requestLoop’ and pass the response returned by the POST request we made which is nothing but the ‘task_url’.

The ‘requestLoop’ method makes a GET request to the task_url that we got from the previous POST to get the ‘download_url’ for the event.

requestLoop(exportJobInfo) {
    run.later(() => {
      this.get('loader')
        .load(exportJobInfo.task_url, { withoutPrefix: true })
        .then(exportJobStatus => {
          if (exportJobStatus.state === 'SUCCESS') {
            this.set('isLoading', false);
            this.set('isDownloadDisabled', false);
            this.set('eventDownloadUrl', exportJobStatus.result.download_url);
            this.set('eventExportStatus', exportJobStatus.state);
            this.get('notify').success(this.l10n.t('Event exported.'));
          } else if (exportJobStatus.state === 'WAITING') {
            this.requestLoop(exportJobInfo);
            this.set('eventExportStatus', exportJobStatus.state);
            this.get('notify').alert(this.l10n.t('Event export is going on.'));
          } else {
            this.set('isLoading', false);
            this.set('eventExportStatus', exportJobStatus.state);
            this.get('notify').error(this.l10n.t('Event export failed.'));
          }
        })
        .catch(() => {
          this.set('isLoading', false);
          this.set('eventExportStatus', 'FAILURE');
          this.get('notify').error(this.l10n.t('Event export failed.'));
        });
    }, 3000);
  }

Thus, the above code shows the ‘requestLoop’ method which runs according to the response returned by the GET to the ‘task_url’. Thus, we have three states as the response of the GET to ‘task_url’. They are:
‘FAILURE’
‘WAITING’
‘SUCCESS’
As we can see in the method, we use the logic that once the event is exported successfully or if there is any failure, we stop the loop and set the status. If the server returns ‘WAITING’ then we keep on running loop until the server returns the state ‘SUCCESS’ or ‘FAILURE’.

Thus, once the event is exported successfully, we pass the download URL returned by the server to the template and link it with the download button. Thus clicking the download button, the user can download the event as a zip file.

Resources:
Github documentation of loader.js

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.