-->

Google App Maker how to create Data Source from Go

2019-01-14 20:23发布

问题:

Using GoogleAppMaker how to create a data source from google contacts. There is an employee HR example app but I want to similarly manage contacts (add, modify, delete) and use select criteria.

回答1:

At this time this task is not trivial in App Maker and it is pretty much generic. We can change question wording to CRUD operations with 3rd party datasources. Let's break it into smaller parts and address them separately.

Read/list contacts

This task is relatively easy. You need to use Calculated Model to proxy Apps Scripts Contacts API response. Once you create model with subset of fields from the Contact response you can create datasource for the model and bind it to List or Table widget. You can also try to find some inspiration in Calculated Model Sample.

// Server side script
function getContacts_() {
  var contacts = ContactsApp.getContacts();

  var records = contacts.map(function(contact) {
    var record = app.models.Contact.newRecord();

    record.FirstName = contact.getGivenName();
    record.LastName = contact.getFamilyName();

    var companies = contact.getCompanies();

    if (companies.length > 0) {
      var company = companies[0];

      record.Organization = company.getCompanyName();
      record.Title = company.getJobTitle();
    }

    var emails = contact.getEmails();

    if (emails.length > 0) {
      record.Email = emails[0].getAddress();
    }

    var phones = contact.getPhones();

    if (phones.length > 0) {
      record.Phone = phones[0].getPhoneNumber();
    }

    return record;
  });

  return records;
}

Create/Update/Delete

Since Calculated Models have some limitations, we need to turn on our imagination to create, update and delete records from their datasources. The basic strategy will be calling server side scripts for CUD operations in response to user actions on client side. To get user's input from UI we will need to utilize page's Custom Properties, one property for each Contact field:

Here are some snippets that should explain the idea

Create

// Client script
function onSubmitContactClick(submitButton) {
  var props = submitButton.root.properties;

  var contact = {
    FirstName: props.FirstName,
    LastName: props.LastName,
    Organization: props.Organization,
    ...
  };

  google.script.run
    .withSuccessHandler(function() {
      // Most likely we'll need to navigate user back to the
      // page with contacts list and reload its datasource
      // to reflect recent changes, because our `CUD` operations
      // are fully detached from the list datasource
      app.showPage(app.pages.Contacts);
      app.datasources.Contacts.load();
     })
    .withFailureHandler(function() {
       // TODO: Handle error
     })
    .createContact(contact);
}


// Server script
function createContact(contactDraft) {
 var contact = ContactsApp.createContact(contactDraft.FirsName,
                                         contactDraft.LastName,
                                         contactDraft.Email);

  contact.addCompany(contactDraft.Organization, contactDraft.Title);
  contact.addPhone(ContactsApp.Field.WORK_PHONE, contactDraft.Phone);
}

Update

Idea to update contact records will be very similar to the new contact creation flow, so I skip it for now.

Delete

Assuming that delete button is located inside contacts table row.

// Client script
function onDeleteContactClick(deleteButton) {
  var email = deleteButton.datasource.item.Email;

  google.script.run
    .withSuccessHandler(function() {
      // To update contacts list we can either reload the entire
      // datasource or explicitly remove deleted item on the client.
      // Second option will work way faster.
      var contactIndex = deleteButton.parent.childIndex;
      app.datasources.Contacts.items.splice(contactIndex, 1);
     })
    .withFailureHandler(function() {
      // TODO: Handle error
     })
    .deleteContact(contact);
}


// Server script
function deleteContact(email) {
  var contact = ContactsApp.getContact(email);
  ContactsApp.deleteContact(contact);
}