-
Notifications
You must be signed in to change notification settings - Fork 194
Appmaker Architectural Draft
NB: Some of this is currently aspirational
Repository:
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.
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()
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()
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()
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()
<!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>
The designer
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).
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.
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 likedocument.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");
});