Implementing Settings API on Open Event Frontend to View and Update Admin Settings

This blog article will illustrate how the admin settings are displayed and updated on the admin settings page in Open Event Frontend, using the settings API. It will also illustrate the use of the notification service to display corresponding notifications on whether the update operation is successful or not. Our discussion primarily will involve the admin/settings/index route to illustrate the process, all other admin settings route work exactly the same way.

The primary end point of Open Event API with which we are concerned with for fetching tickets for an event is

GET /v1/settings

Since there are multiple  routes under admin/settings  including admin/settings/index, and they all will share the same setting model, it is efficient to make the call for Event on the settings route, rather than repeating it for each sub route, so the model for settings route is:

model() {
 return this.store.queryRecord(setting, {});
}

It is important to note that, we need not specify the model for index route or in fact for any of the sub routes of settings.  This is because it is the default behaviour of ember that if the model for a route is not found, it will automatically look for it in the parent  route.  

And hence all that is needed to be done to make the model available in the system settings form  is to pass it while calling the form component.

<div class="ui basic {{if isLoading 'loading' ''}} segment">
 {{forms/admin/settings/system-form save='updateSettings' settings=model}}
</div>

Thus the model properties will be available in the form via settings alias. Next, we need to bind the value property  of the input fields to the corresponding model properties.  Here is a sample snippet on so as to how to achieve that, for the full code please refer to the codebase or the resources below.

<div class="field">
 {{ui-radio label=(t 'Development') current=settings.appEnvironment name='environment' value='development' onChange=(action (mut settings.appEnvironment))}}
</div>
<div class="field">
 {{ui-radio label=(t 'Staging') current=settings.appEnvironment name='environment' value='staging'}}
</div>
<div class="field">
 {{ui-radio label=(t 'Production') current=settings.appEnvironment name='environment' value='production'}}
</div>
<div class="field">
 <label>
   {{t 'App Name'}}
 </label>
 {{input type='text' name='app_name' value=settings.appName}}
</div>
<div class="field">
 <label>
   {{t 'Tagline'}}
 </label>
 {{input type='text' name='tag_line' value=settings.tagline}}
</div>

In the example above, appName, tagLine and appEnvironment are binded to the actual properties in the model. After the required changes have been done, the user next submits the form which triggers the submit action. If the validation is successful, the action updateSettings residing in the controller of the route is triggered, this is where the primary operations happen.

updateSettings() {
 this.set('isLoading', true);
 let settings = this.get('model');
 settings.save()
   .then(() => {
     this.set('isLoading', false);
     this.notify.success(this.l10n.t('Settings have been saved successfully.'));
   })
   .catch(()=> {
     this.set('isLoading', false);
     this.notify.error(this.l10n.t('An unexpected error has occured. Settings not saved.'));
   });
}

The controller action first sets the isLoading property to true. This adds the semantic UI class loading to the segment containing the form, and it and so the form goes in the loading state, to let the user know the requests is being processed. Then the save()  call occurs and this makes a PATCH request to the API to update the values stored inside the database. And if the PATCH request is successful, the .then() clause executes, which in addition to setting the isLoading as false.

However, in case there is an unexpected error and the PATCH request fails, the .catch() executes. After setting isLoading to false, it notifies the user of the error via an error notification.

Resources

Published by

CosmicCoder96

GSOC 17 @ FOSSASIA | Full Stack Developer | Swimmer