Contents
- NodeJS (latest version, https://nodejs.org/en/)
- Firefox, Chrome or PhantomJS to launch unit tests
You can now install the node dependencies. To do so, launch in the folder in which you cloned this repository:
- Install node modules with yarn (recommended)
yarn
ornpm install
We rely on environment files managed by Aurelia for the configuration of the application. They can be found in ./aurelia_project/environments
. They are named like ENV.js
where ENV
corresponds the environment (dev, staging, prod) they relate to. We will build it to inject some configuration variable either from the environment or from CLI flags. The file used by the application loaded by the application is ./config/environment.json
and some of its values will be overridden by the config file built for the environment which is written in ./config/environment.ENV.json
. This file is built during the build-config
step.
You can override the host and port of the api to use for any environment by creating a .env
file at the root of the project. Put in it only the lines you need. A full .env
file will look like:
API_HOST=newhost API_PORT=8080
The list of assets to preload is also generated during the transpile step. It is only done once.
This allows you to develop the frontend without running an API locally (which is the default for the dev
environment). This is specially useful if you develop only on the frontend (eg you are a designer) and don't want to bother with the API.
To build the frontend for development and use the API from the staging server, create a .env
file at the root of the project with this content:
API_HOST=devapi.last-run.com API_PORT=80
- To launch the development server, use
yarn start
. This will compile the app for development in memory, launch a webserver, watch for any changes and reload your page once the changes are taken into account. - To launch tests on time, use
yarn test
. - To launch tests automatically when a modification is done, use ``nps test.watch`.
- To build the files for an environment, use
nps clean 'build.config --env dev' 'webpack.build --env.environment=dev' build.manifest
. You can also specify the version to use with--version VERSION
and the API version to use with--api-version API_VERSION
. For instance:nps clean 'build.config --env dev --version latest --api-version latest' 'webpack.build --env.environment=dev' build.manifest
- To clean the build folder, use
nps clean
- To lint the JS, SCSS and template files, use
yarn lint
. - To update the translations, use
yarn translate
. - To update the default names, use
nps update.defaultnames
.
Be sure that (this can be configured in your text editor or your IDE):
- Your files are encoded in UTF-8
- You use Unix style line ending (also called LF)
- You remove the trailing whitespaces
- You pull your code using
git pull --rebase=preserve
- Wrap your code in 100 characters to ease reading.
- Use spaces, not tabs.
- Use 4 spaces to indent and 8 for continuation indentation. It is intended to avoid lines starting far at in the right.
The code is written with the Aurelia JavaScript framework. We can distinguish three main categories:
- Pages: a web page used in the routers.
- Services: they are instanced once and injected as needed in the others elements (services or widgets) of the application. They provide state and useful methods. They are similar to services in AngularJS.
- Widgets: It is an element (component or Custom Element in Aurelia's terminology) instantiated in the DOM of the application. A widget can be instantiated multiple times and each instance is independent of the others. It consists of a JS file, an HTML template and, if needed, a SCSS file for its style. All these files are grouped in a folder named after the widget. They are similar to directives in AngularJS.
The code is then organized as follow:
- The
app
folder contains the code of the application (JS and HTML). It is structured as follow:- Directly in the folder the bootstrap files for the application.
- The
game
folder for everything related to the game. This folder is then split in:game.js
andgame.html
the main page for the game. It contains a router to navigate between create and play.create
for widgets and services used to create the game.play
for widgets and services used to play the game.services
for services common to create and play.widgets
for widgets common to create and play.
- The
site
folder for the page of the site and its widgets. - The
style
folder for global SCSS files. - The
widgets
folder for global widgets.
- The
assets
folder contains all the images, fonts, media files (if small!) of the application. - The
aurelia_project
folder contains:aurelia.json
the configuration file of aurelia-cli.- The tasks and libraries used by aurelia-cli to work.
- The
dist
folder (un-tracked) will contain the built bundles that are used in the browser. - The
locale
folder contains a subdirectory per lang. Each subdirectory contains a JS file exporting an object containing the translations for this language. These JS files are updated withnpm run translate
. - The
scripts
folder contains: JS scripts that don't belong to the app but are required for it to work (eg: tracking.js, polyfills.js). - The
templates
folder contains templates (eg: index.html). - Unit tests go into the
test/unit
folder. The structure of thetest/unit
folder should reflect the structure of the app.
- Tests files should have the same name than the file they are testing and end with the
.spec.js
extension. - Private methods and attributes starts with an underscore
_
. In a service this means that the method or the attribute shouldn't be accessed outside of it. In the JS part of a Custom Element, it means the method or attribute shouldn't be used in the HTML template.
We try to follow the same rules as the angular project towards commits. Each commit is constituted from a summary line, a body and eventually a footer. Each part are separated with a blank line.
The summary line is as follow: <type>(<scope>): <short description>
. It must not end with a dot and must be written in present imperative. Don't capitalize the fist letter. The whole line shouldn't be longer than 80 characters and if possible be between 70 and 75 characters. This is intended to have better logs.
The possible types are :
- chore for changes in the build process or auxiliary tools.
- doc for documentation
- feat for new features
- ref: for refactoring
- style for modifications that not change the meaning of the code.
- test: for tests
The body should be written in imperative. It can contain multiple paragraph. Feel free to use bullet points.
Use the footer to reference issue, pull requests or other commits.
This is a full example:
feat(css): use CSS sprites to speed page loading - Generate sprites with the gulp-sprite-generator plugin. - Add a build-sprites task in gulpfile Close #24
git hooks allow you to launch a script before or after a git command. They are very handy to automatically perform checks. If the script exits with a non 0 status, the git command will be aborted. You must write them in the .git/hooks/ folder in a file following the convention: <pre|post>-<git-action>
. You must not forget to make them executable, eg: chmod +x .git/hooks/pre-commit
.
In the case you don't want to launch the hooks, append the --no-verify
option to the git command you want to use.
This project uses pre-commit to handle git hooks automatically. To install the hooks, run pre-commit install
and pre-commit install --hook-type pre-push
.
The translations are generated from this google doc. Each sheet correspond to a part of the application: site (for all the pages of the site), game (for gobal game traductions), game/create, game/play, global (for global translations), cards (for the translations of names and descriptions of the cards), trumps (for the translations of the names and descriptions of the trumps). To update the JSON in the frontend, use either: npm run translate
The translations are performed in the browser by the aurelia-i18n plugin.
To translate something:
Add the relevant key in the spreadsheet.
Update the JSON files containing the translations.
In the HTML, use if possible (ie text/html that don't rely on aurelia binding):
the
t
tag with the key as value. For instance:<span t="site.connection_button"></span>
. If the translated text contains HMTL, add[html]
before the key:<span t="[html]site.homepage.pitch"></span>
. If you need some value provided by aurelia in the code, delimit it with __ and use thet-params.bind
to supply the value. Eg, use the valueC'est le tour de <br><strong>__playerName__</strong>
and this code to supplyplayerName
:<p class="centered-important" t="[html]game.play.whose_turn_message" t-params.bind="{playerName: currentPlayerName}"> </p>
the TValueConverter (if you cannot use the option above):
${ 'TAKEN' | t}
.
If you need to translate trough the code:
- Inject the I18N service.
- Translate with
this._i18n.tr('cards.queen_red')
orthis._i18n.tr('cards.queen_red', {toto: 'toto'})
if the value requires some string to be replaced.
See the plugin page on github for the full documentation.
Put the id of the translation (eg site.page_title.home
) in the title property of the route definition.
In order for the translations to be correctly applied to the popup, the data
object passed to the popup.display
function must contain a translate key. This key must be associated with an object like:
{
// The messages used in the popup template (like ``title``) associated with their translation key.
messages: {
POPUP_KEY: TRANSLATION_KEY,
},
// Dynamic parameters to use in the translation of messages strings.
// They will be translated before the messages. This is required to
// translate the parameters before they are injected in the message
// string.
paramsToTranslate: {
PARAM_NAME: TRANSLATION_KEY,
},
// Optionnal params for the translations that don't need translations.
params: {
PARAM_NAME: VALE,
}
}
Complete data
example:
let popupData = {
selectedChoice: otherPlayerNames[selectedIndex],
choices: otherPlayerNames,
translate: {
messages: {
title: `trumps.${this.normalizeTrumpName()}`,
description: `trumps.${this.normalizeTrumpName()}_description`,
message: 'game.play.select_trump_target',
},
paramsToTranslate: {
trumpname: `trumps.${this.normalizeTrumpName()}`,
},
},
};
Associated translation to the 'game.play.select_trump_target'
to illustrate usage of the params:
"Who should be the target of {{trumpname}}?"
- Add the main image in
assets/game/heroes/<hero-name>.png
(used in hero selection) - Add the circled image in
assets/game/heroes/<hero-name>-circle.png
(used in the game) - Add the name of the hero in the array named
heroes
in all the environment files inaurelia_project/environments
- Add the image of its power under
assets/game/cards/powers
as :- The normalized name of the power (see existing files in this folder for examples).
- Symlink this file with
ln -s POWER_NAME.png HERO_NAME.png
- Modify the list located here: https://docs.google.com/spreadsheets/d/1Ees-A_yNQTfba7wH-flbrJunLMiTcTOUsbHqUTyOKm8/edit#gid=0
- Run
npm run default-names
- Create the model and its view in the
app/game/widgets/popups
folder. They must be named after the type of the popup. So for thetransition
popup, you will needtransition.js
andtransition.html
. - Add the require to the file in
app/game/widgets/popups/popups.html
- If you need specific style for your popup, add a SCSS file named after the type of the popup and wrap your code in
aot-popup .popup-TYPE
. You can then require the style file as usual in the view:<require from="./TYPE.css"></require>
. - That's it, the
compose
element will take care of the rest.
- Change the versions in
package.json
. - Run
yarn upgrade
to update them. - Run lint with
yarn lint
- Run tests with
yarn test
- Build the application for with
yarn start
and thennps clean 'build.config --env prod' 'webpack.build --env.environment=prod'
- Commit and push the changes.
- Update the version in
package.json
. - Diff the
aurelia_project
folder with one from a new and similar project. To create a project:- Run
au new tmp
. - Follow the instructions. Use ES6 and SASS to have similar tasks.
- Run
- Update files in
aurelia_project/tasks
based on the diff. - Check that the build and test tasks are running correctly.