Plat/al, the web platform for alumni¶
This project holds the second generation of plat/al, Polytechnique.org’s PLATform for ALumni.
It provides the following features for alumni associations:
- Full directory, including advanced search functionalities
- Managing forlife email addresses, including complex setups (secondary domains, IMAP, GoogleApps)
- Event organization tools, including online payment
- And much more.
Contents:
Contributing¶
Resources¶
Source code | https://github.com/Polytechnique-org/platal2 |
Documentation | http://platal.readthedocs.org/ |
Milestones | https://github.com/Polytechnique-org/platal2/milestones |
Issues | https://github.com/Polytechnique-org/platal2/issues |
Help | #platal on chat.freenode.net |
Development process¶
- Dev
- Bugfixes go directly on
master
- Small features start with an issue describing the problem
- Begin the patchset with a piece of design documentation (might be a comment in the file)
- Big features must start through a design doc in the
docs/
folder - Don’t forget automated tests
- Always add a ChangeLog entry
- Bugfixes go directly on
- Deployment
- Merge
master
intoprod
- Add the release date to the ChangeLog
- Bump version numbers on the
prod
branch - Tag that commit
- Build the packages (
make dist
) from that tag - Merge back
prod
intomaster
- Merge
- Hotfixes
Things break after a release?
- Add the fix on the
prod
branch - Merge back
prod
intomaster
- Add the fix on the
Coding guidelines¶
A consistent codebase is important for readability. The coding guidelines should be used to improve readability; watch this talk for a few examples.
- Philosophy: The Zen of Python
- Beautiful is better than ugly.Explicit is better than implicit.Simple is better than complex.Complex is better than complicated.Flat is better than nested.Sparse is better than dense.Readability counts.Special cases aren’t special enough to break the rules.Although practicality beats purity.Errors should never pass silently.Unless explicitly silenced.In the face of ambiguity, refuse the temptation to guess.There should be one – and preferably only one – obvious way to do it.Although that way may not be obvious at first unless you’re Dutch.Now is better than never.Although never is often better than right now.If the implementation is hard to explain, it’s a bad idea.If the implementation is easy to explain, it may be a good idea.Namespaces are one honking great idea – let’s do more of those!
- Python
- Use Django’s style guide
- Javascript
- Use AirBnB’s coding rules
Testing¶
Software stack¶
Application components¶
Plat/al v2’s stack is split in two parts:
- Backend
Developed with Django, this component provides a REST-like API over the internal directory.
The API is built upon django-rest-framework; see the API documentation for details.
- Frontend
The user-facing website is a full javascript, single-page application.
It fetches data from the API, renders it, handles HTML events, and sends updates to the backend.
Front-end development¶
This project uses modern engineering methods for front-end development.
This means that:
- External libraries are loaded from NPM or from Bower
- The required versions are expressed in either
package.json
(for development and server-side dependencies) andbower.json
(for “in-browser” dependencies, both JS and CSS) - The build pipeline (concatenation, minification, optimization) might use Gulp
The build process includes:
- Loading development dependencies from NPM through
npm install
- Loading in-browser dependencies from Bower through
bower install
- Running JS compilation from project code and libraries, through
gulp build
Cache busting¶
For bandwidth efficiency, all assets (JS, CSS, images) SHOULD be served with a long cache duration (i.e cache forever).
This is possible if JS/CSS/image filenames include a hash of their content (e.g. platal.a244de499.js
)
This is performed using gulp-rev
as a last build step.
Components¶
Backend¶
The backend provides at least some features, including:
- The admin console
- A Rest-like API, used by dynamic parts of the website
- A simple
selftest
page, where admins can check that all features are working properly
Frontend¶
The front-end is based on a full-javascript, single-page application.
It is based upon the following components:
- UI: React.js
- Event/rendering loop: Flux
- Ajax wrapper: to be defined
- Event management: to be defined
Request handling¶
Using a split stack makes debug more complex; here is a short description of what happens:
A user hitting https://www.polytechnique.org/ receives a simple HTML document that:
- Declares where version-specific JS/CSS/... files should be loaded
- Declares where the API is located
- Starts rendering the DOM through React.js
In details, the request is handled as follows:
- The HTTP server (might be Django) receives the request
- It generates a static HTML page, including the related JS/CSS files and the URL to the API
- The browser parses this HTML page, and loads the JS/CSS
- The JS app sends a few queries to the API to fetch more information (e.g the user’s data)
- The JS app updates the DOM, triggering a HTML re-render
- When the user provides input, the JS app reacts by querying the API for the requested data
- Based on that new data, the JS app updates the DOM again, triggering another HTML rendering.
Remote services¶
The site enables a user to configure other services, e.g:
- Mailing lists
- Newsgroups
- Email redirection accounts
In order to provide an easily reusable platform, those services should expose a standardized configuration interface, using a simple HTTP/JSON API.
This ensures that all components can be upgraded without breaking the user configuration pages.
REST API¶
Migration from plat/al 1¶
For a smooth transition from the first version of plat/al, some rules are required.
- Coexistence
- The new site MUST reuse most URLs from the old site
- The Apache config can be used to switch sets of URLs to the new site
- Database
- The old MySQL database will be kept as the main storage engine
- An additional database can be used for specific needs of the new stack
- Old tables can be altered (e.g adding an
auto_increment
field) for greater compatibility
- Authentication
- Users SHALL authenticate only once during a session, even when switching versions
- The password (for strong authentication with sensitive tasks) MAY be required twice, as few pages require this for common usage
- Option 1: Use
authgroupex
from the new site to the old - Option 2: The new site reads the PHP sessions — but this might break logout
- Design
- Skin choice isn’t available on the new site
- Enforce the
NewDefault
skin for the old site once finished - Make sure the menu / header / footer have the same look between both sites
Archived design discussions¶
For future reference, this document lists a few elements that led to the current choice of technology, stack, ...
Front-end development¶
Two approaches are possible for frontend development:
- All pages are rendered through Django templates, with some dynamic JS code for some pages
- Django only serves the API, all pages are rendered in the browser in JS
Django templates¶
With this approach, a user’s request to https://www.polytechnique.org/ is handled as follows:
- The Django server receives the request
- It finds the correct
View
through its routing rules - The
View
builds a context, chooses the HTML template, and provides both to the template rendering engine - Django sends back the rendered HTML template to the browser
- The browser parses the HTML and presents
If the page is dynamic (e.g search, profile):
- The browser loads the related Javascript files
- The JS stack generates a HTML DOM section based on its state and (optional) API queries
- When the user provides input, the JS stack queries the API
- Based on the new data, the JS stack updates the DOM, triggering a HTML re-render
- Pros
- Closer to plat/al 1 design
- Easy to write a simple page
- The first page loads faster
- Cons
- Complex handling of mixups between Django HTML templates and React HTML templates
- Behavior of the pages is split between two codebases
- Each page loads the whole skeleton
React.js rendering¶
With this approach, a user hitting https://www.polytechnique.org/ receives a simple HTML document that:
- Declares where version-specific JS/CSS/... files should be loaded
- Declares where the API is located
- Starts rendering the DOM through React.js
In details, the request is handled as follows:
- The Django (or Express) server receives the request
- It generates a static HTML page, including the related JS/CSS files and the URL to the API
- The browser parses this HTML page, and loads the JS/CSS
- The JS app sends a few queries to the API to fetch more information (e.g the user’s data)
- The JS app updates the DOM, triggering a HTML re-render
- When the user provides input, the JS app reacts by querying the API for the requested data
- Based on that new data, the JS app updates the DOM again, triggering another HTML rendering.
On subsequent pages, only new data is loaded; the whole codebase was loaded along the first page.
- Pros
- Clean split of roles: Django provides the data, React provides the UI
- A single codebase for the whole UI
- Pages feel more dynamic
- Comes with great browser-based testing tools
- Rate-limiting searches is easier, since it’s a single entrypoint in the API
- Cons
- Unusual paradigm and language
- Adding a new page might be more complex (to be confirmed)
- The whole app must load before the user sees anything (can be avoided with e.g http://skitjs.com)