Ember

Salt

Ember Only

If your site is purely Ember i.e. no Django, then set the profile to ember e.g:

# sites/my.sls
sites:
  mysite.hatherleigh.info:
    backup: none
    profile: ember
    ssl: True
    letsencrypt: True

To build for production:

rm -rf dist/ node_modules/; and pnpm install;
pnpm ember build --environment="production"
tar -cvzf mysite-0.0.0.tar.gz dist/

To deploy:

# on my laptop
scp mysite-0.0.0.tar.gz cloud-a.my.vpn:repo/release/

# on the server
sudo -i -u web
cd /home/web/repo/project/mysite.hatherleigh.info/ember/
tar --strip-components=1 -xzf /home/patrick/repo/release/mysite-0.0.0.tar.gz

To create the certificate:

init-letsencrypt mysite.hatherleigh.info - /home/web/repo/project/mysite.hatherleigh.info/ember/

Django and Ember

If your Django site has an Ember front end, then add ember: True to your sites file:

# sites/my.sls
sites:
  www.hatherleigh.info:
    package: hatherleigh_info
    profile: django
    ember: True

The default path for your Django app will be /back/ and the default path for your Ember app will be /. If you want to override this, then you can set the ember_path and django_path as follows:

# sites/my.sls
sites:
  www.hatherleigh.info:
    package: hatherleigh_info
    profile: django
    ember: True
    ember_path: front
    django_path: back

Tip

To set the django_path to the default (/): django_path: /

Note

Don’t append or prepend a / to the ember_path or django_path. The Salt state files will take care of the /.

If you set an ember_path (other than /), set the rootURL in the production environment (config/environment.js):

if (environment === "production") {
  ENV.rootURL = "/front/"
}

Installation

Prerequisites

Using pnpm (and not volta), from https://www.clearthought.co.uk/getting-started-with-pnpm/:

curl -fsSL https://get.pnpm.io/install.sh > pnpm-install.sh
# view the file to make sure you're happy running it on your computer
sh ./pnpm-install.sh

Update config.fish:

# vim ~/.config/fish/config.fish
set -gx PNPM_HOME "/home/patrick/.local/share/pnpm"
set -gx PATH "$PNPM_HOME" $PATH

Tip

Change patrick to your own user name.

To install command line completion:

pnpm install-completion

To use node 16:

pnpm env use --global 16

To use the current LTS version of node:

pnpm env use --global lts

Installing ember-cli

pnpm install -g ember-cli

Creating a project

Run the following commands to create a project e.g. ember-first:

# ember new ember-first --lang en
# to create an embroider project
ember new ember-first --lang en --embroider --skip-npm --skip-git
cd ember-first
pnpm install
pnpm start
# or...
#ember serve
# or...
npm start

Cloning an existing project

To clone an existing project e.g. ember-first:

git clone git@gitlab.com:proj-owner/ember-first.git
cd ember-first
npm install
bower install
ember server

Components

Input

The following input attributes must be passed as arguments (i.e. do prepend @) to the <Input> component:

@checked
@type
@value

From https://guides.emberjs.com/release/components/built-in-components/

Tip

Do not use on "change", use on "input" e.g. {{on "input" this.updateText}}.

Error Handling

Configuration

Django REST framework exception handler (from the api app):

REST_FRAMEWORK = {"EXCEPTION_HANDLER": "api.models.custom_exception_handler"}

Exceptions and Responses

For Ember to understand and handle an exception, we need to be using the custom_exception_handler (see above).

e.g. if a user does not have permission to data, then raise PermissionDenied (from rest_framework.exceptions import PermissionDenied)

Warning

Do not return an HttpResponseForbidden response as Ember will have no idea what happened.

Tip

For an example, search for PermissionDenied in work/api.py

To catch the forbidden error code in Ember:

try {
  let process = yield this.store.findRecord("process", params.workflow_id, {
    reload: true
  })
  return yield process
} catch (e) {
  if (e.errors.firstObject.status === "403") {
    return yield undefined
  } else {
    this.kbMessages.addError("Cannot load workflow processes", e)
  }
}

Learn

Tip

We have two projects which can be used together to explore Ember data:

  1. https://gitlab.com/kb/contact/ (on the 2292-dramatiq branch)

  2. https://github.com/pkimber/ember-data-error

Background

From Force Ember Data to reload data from backend API

Ember Data’s default strategy for requesting data records (either findRecord or findAll):

  • If it is not loaded, load it

  • If it is already loaded, don’t reload it. Instead, backgroundReload it

What does this mean?

  • reload queries for new data pre-emptively, that is, it waits until the promise with new data resolves

  • backgroundReload returns the local (cached) record, and then queries for new data

This has a big impact on error handling because returning the local (cached) copy of a record will probably succeed (so no exception thrown). If the backgroundReload query fails, then this is happening at a later date, away from your error handling code and the exception will not be caught.

There is still an open issue for this: https://github.com/emberjs/data/issues/3809 For more information, search Ember Discord for backgroundReload.

Solution

To solve this issue, add the reload option to findRecord and findAll e.g:

let contact = yield this.store.findRecord("contact", 22, { reload: true })

Then we can catch any errors …

Ember Concurrency

@task *doStuff() {
  try {
    let contact = yield this.store.findRecord("contact", 22, { reload: true })
    this.manager = contact
  } catch(e) {
    console.log("catch, doStuff .........................................")
    console.log(e)
  }
}

Ember (without Concurrency)

If you are not using Ember concurrency, then the error handler in a Route, should catch any errors e.g:

@action
error(error, transition) {
  console.log("Before, contacts.js ...................................")
  console.log(error)
  console.log(transition)
  console.log("After, contacts.js ....................................")
  return false
}

Ember Data

Our adapter (extends the DRFAdapter) can be found in app/adapters/application.js for our projects.

Note

I tried moving the adapter to @kb/ember-addon, but the project doesn’t seem to find it.

Packages

Peer Dependencies

Note

I had so many issues with this one on ticket https://www.kbsoftware.co.uk/crm/ticket/6312/

Some things to check…

Check auto-install-peers=false and fix any issues arising:

pnpm config list                                                                                                                                                                                                     6312-peer-dependencies   ◼
auto-install-peers=false

To fix V1 ember addons are resolving as incorrect peer dependencies:

I moved dependencies in package.json from dependencies to devDependencies and peerDependencies.

I used the exact version e.g. 4.12.3 rather than the ^4.12.3.

Check all dependencies have the exact same version in addons and the project.

Update Packages

To update one package (e.g kb-base-ember-addons):

npm i @kbsoftware/kb-base-ember-addons@latest

Use ncu (npm-check-updates) to finalise versions before releasing for deployment. Run all the tests and check it by running on a local server.

https://www.npmjs.com/package/npm-check-updates:

npm i -g npm-check-updates

Then type:

ncu

… inside a folder with a package.json.

This shows you what is out of date. And typing:

ncu -u

… will update all the versions in the package.json file.

So you then run:

npm i

… which will upgrade as per the new package.json

Testing

Note

We don’t need to define Mirage models, Auto-discovery of Ember Data models