Skip to content
This repository has been archived by the owner on Mar 30, 2019. It is now read-only.

Appmaker Architectural Draft

Pomax edited this page Sep 12, 2014 · 7 revisions

NB: Some of this is currently aspirational

Repository:

mozilla-appmaker/appmaker

Ceci -- /public/ceci/

This is the home of the polymer custom elements that appmaker apps use. Core things that Ceci does is to structure a broadcast model components, a card-based navigation system and to expose helpers to apps.

ceci-app.html

This is primarily a container for cards. It also has a unique ID used to namespace external services.

<ceci-app id="ceci-app-c72ee1be-e415-4324-9d8a-a6e9c04d9754">

Public methods:

#addCard()
#removeCard(index)
#countCards()
#clearCards()

ceci-card.html

Within a ceci-app, one card at a time can be shown. These are containers used for navigation. They themselves can listen to broadcast events and respond by "showing".

<ceci-card visible>
...
</ceci-card>

Public methods:

#show()

ceci-element.html & ceci-element-designer.html

This is the base element that Appmaker Components extend. <ceci-element> tags shouldn't be used directly in apps.

Public methods:

#broadcast(name, data)
#showContainingCard()

ceci-element.html

This is the base element that Appmaker Components extend. <ceci-element> tags shouldn't be used directly in apps.

Public methods:

#broadcast(name, data)
#showContainingCard()

ceci-broadcast.html

ceci-listen.html

Putting it all Together:

<!doctype html>
<html>
  <head>
    <script src="polymer.min.js"></script>
    <link rel="import" href="ceci-broadcast.html">
    <link rel="import" href="ceci-listen.html">
    <link rel="import" href="ceci-element.html">
    <link rel="import" href="ceci-app.html">
    <link rel="import" href="ceci-card.html">
    <link rel="import" href="ceci-button.html">
    <link rel="import" href="ceci-hello.html">
    <style>
    </style>
  </head>
  <body>
    <ceci-app>
      <ceci-card visible>
        <ceci-listen on="green" for="show"></ceci-listen>
        <ceci-top>
          <ceci-button label="Say hello!" value="hi"></ceci-button>
        </ceci-top>
        <ceci-middle>
          <ceci-button label="Flip!"><ceci-broadcast on="red" from="click"></ceci-broadcast></ceci-button>
          <ceci-hello><ceci-listen on="blue" for="hello"></ceci-listen></ceci-hello>
        </ceci-middle>
        <ceci-bottom>
          <ceci-button label="Say goodbye!" value="bye"><ceci-broadcast on="blue" from="click"></ceci-broadcast></ceci-button>
        </ceci-bottom>
      </ceci-card>
      <ceci-card>
        <ceci-listen on="red" for="show"></ceci-listen>
        <ceci-top></ceci-top>
        <ceci-middle>
          <ceci-hello status="UHOH"></ceci-hello>
        </ceci-middle>
        <ceci-bottom>
          <ceci-button label="Go back!"><ceci-broadcast on="green" from="click"></ceci-broadcast></ceci-button>
        </ceci-bottom>
      </ceci-card>
    </ceci-app>
  </body>
</html>

Designer

The designer

Component Setup -- /routes/components.js, /views/components/

Exposes a UI & API that let's a user enter a base url/endpoint for their component. (i.e. http://secretrobotron.github.io/bob-button/)

They are then returned the HTML snippet for including their component in-page:

<link 
  rel="import" 
  href="https://secretrobotoron-components.appmaker.mozilalabs.com/bob-button.html"
>

We can then maintain a mapping of user(1)..component(*) and a mapping of component(1)..base_url(1).

Component Proxy -- /routes/component-proxy.js

This proxy provides two major features:

  • Provide some level of isolation between publicly authored components by serving them on a per-user subdomain.
  • Serve components regardless of their source over SSL

The proxy service uses the data generated by Component Setup to respond to the following request: https://{user}-components.appmaker.mozilalabs.com/{component-name}/(.*)

https://{user}-components.appmaker.mozilalabs.com/index.(html/js) & https://appmaker-components.appmaker.mozilalabs.com/index.(html/js)

Should serve indexes of all components under each user.

appmaker can just be an account without an associated persona login.

Code Helpers

There are some helper functions and code patterns that Appmaker uses to make life as a developer on the codebase easier, which for the moment are housed here:

  • NodeList has an .array() function that turns the list into an array for normal processing, so that things like document.querySelectorAll(...).array() can be used instead of Array prototype rewrapping. For example:
var hidden = document.querySelectorAll(".hidden").array();
hidden.forEach(function(e) {
  e.classList.remove("hidden");
});

instead of

var hidden = document.querySelectorAll(".hidden");
Array.prototype.slice.call(hidden).forEach(function(e) {
  e.classList.remove("hidden");
});