chore: 🤖 add persistence to scope service
This commit is contained in:
4 files changed
+84
-15
No files matched your search
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user