chore: 🤖 add persistence to scope service

This commit is contained in:
Randall Morey committed 2020-05-13 16:41:50 -04:00
1 parent 7f2e195fd8
commit 3eb2abe4a5
4 files changed
+84 -15

No files matched your search

+47 -7
View File
@@ -1,6 +1,7 @@
import Service from '@ember/service';
import { tracked } from '@glimmer/tracking';
import { computed } from '@ember/object';
import { inject as service } from '@ember/service';
/**
* This module includes two parts:
@@ -55,19 +56,25 @@ class Scope {
}
/**
* Returns the JSON serialization of this scope.
* Returns the JSON serialization of this scope. This is necessary because
* scopes may be persisted in storage with their JSON representation.
* @return {?object}
*/
toJSON() {
const { org, project } = this;
return JSON.stringify({ org, project });
return { org, project };
}
}
export { Scope };
/**
* The scope service manages and persists the current scope. Validating against
* The scope service manages and persists the current scope. To interact with
* this service, get and set `service.org` or `service.project` directly, rather
* than using the tracked `scope` member, which is internal.
*
* A scope is valid only if the user has access to the organization and project
* specified in the scope, and they exist. However, validating against
* available organizations and projects is outside the scope (tee hee) of this
* service because it is used by the adapter mixin to generate API paths, which
* could lead to problems were this service to attempt to fetch data.
@@ -78,14 +85,20 @@ export { Scope };
*/
export default class ScopeService extends Service {
/**
* The currently selected scope.
* The storage service is used to persist the current scope.
* @type {StorageService}
*/
@service storage;
/**
* The currently selected scope. This is an internal member only.
* @type {?Scope}
*/
@tracked scope = null;
@tracked scope = new Scope();
/**
* When setting org, `service.org = {...}`, a new scope is instantiated,
* since scopes are immutable.
* since scopes are immutable. Also persists scope on set.
* @type {?object}
*/
@computed('scope.org')
@@ -94,11 +107,12 @@ export default class ScopeService extends Service {
}
set org(org) {
this.scope = new Scope(org, this.project);
this.saveScope(this.scope);
}
/**
* When setting project, `service.project = {...}`, a new scope is
* instantiated, since scopes are immutable.
* instantiated, since scopes are immutable. Also persists scope on set.
* @type {?object}
*/
@computed('scope.project')
@@ -107,5 +121,31 @@ export default class ScopeService extends Service {
}
set project(project) {
this.scope = new Scope(this.org, project);
this.saveScope(this.scope);
}
/**
* Saves the current scope into storage.
*/
saveScope(scope) {
this.storage.setItem('scope', scope);
}
/**
* Retrieves a saved scope from storage, if any.
* @return {?Scope}
*/
fetchScope() {
const json = this.storage.getItem('scope');
if (json) return new Scope(json.org, json.project);
}
/**
* Initializes the service's current scope from storage, if any.
*/
init() {
const savedScope = this.fetchScope();
if (savedScope) this.scope = savedScope;
super.init(...arguments);
}
}
+3 -2
View File
@@ -108,7 +108,8 @@ export default class StorageService extends Service {
* @return {any}
*/
getItem(key) {
return this.storage.getItem(this.qualifiedKey(key));
const value = this.storage.getItem(this.qualifiedKey(key));
if (value) return JSON.parse(value);
}
/**
@@ -116,7 +117,7 @@ export default class StorageService extends Service {
* @param {string} key
*/
setItem(key, value) {
this.storage.setItem(this.qualifiedKey(key), value);
this.storage.setItem(this.qualifiedKey(key), JSON.stringify(value));
}
/**
@@ -3,9 +3,8 @@ import { inject as service } from '@ember/service';
export default class ApplicationRoute extends Route {
@service scope;
@service storage;
afterModel() {
//console.log(this.storage);
//console.log(this.scope);
}
}
+33 -4
View File
@@ -31,12 +31,12 @@ module('Unit | Service | scope class', function (hooks) {
test('it serializes to JSON', function (assert) {
assert.expect(2);
let scope = new Scope({ id: 1 });
assert.deepEqual(JSON.parse(scope.toJSON()), {
assert.deepEqual(scope.toJSON(), {
org: { id: 1 },
project: null,
});
scope = new Scope({ id: 1 }, { id: 2 });
assert.deepEqual(JSON.parse(scope.toJSON()), {
assert.deepEqual(scope.toJSON(), {
org: { id: 1 },
project: { id: 2 },
});
@@ -47,9 +47,8 @@ module('Unit | Service | scope', function (hooks) {
setupTest(hooks);
test('it returns nulls when scope is not set', function (assert) {
assert.expect(3);
assert.expect(2);
const service = this.owner.lookup('service:scope');
assert.equal(service.scope, null);
assert.equal(service.org, null);
assert.equal(service.project, null);
});
@@ -64,4 +63,34 @@ module('Unit | Service | scope', function (hooks) {
assert.equal(service.org, service.scope.org);
assert.equal(service.project, service.scope.project);
});
test('it persists changes to scope', function (assert) {
assert.expect(2);
const service = this.owner.lookup('service:scope');
const org = { id: 1 };
const project = { id: 2 };
service.org = org;
service.project = project;
assert.equal(service.fetchScope().org.id, 1);
assert.equal(service.fetchScope().project.id, 2);
});
test('it initializes to the persisted scope, if any', function (assert) {
assert.expect(4);
const service = this.owner.lookup('service:scope');
const org = { id: 1 };
const project = { id: 2 };
service.org = org;
service.project = project;
// first, persist a scope directly, without setting it on the service
const sneakyScope = new Scope({ id: 3 }, { id: 4 });
service.saveScope(sneakyScope);
// establish that the service scope wasn't changed...
assert.equal(service.scope.org.id, 1);
assert.equal(service.scope.project.id, 2);
// finally, call init and check that the scope changed
service.init();
assert.equal(service.scope.org.id, 3);
assert.equal(service.scope.project.id, 4);
});
});