chore: 🤖 add initial scope service
This commit is contained in:
7 files changed
+193
-3
No files matched your search
@@ -0,0 +1,111 @@
|
||||
import Service from '@ember/service';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
import { computed } from '@ember/object';
|
||||
|
||||
/**
|
||||
* This module includes two parts:
|
||||
*
|
||||
* - `Scope` class: a data structure representing an org/project tuple
|
||||
* - `ScopeService`: manages the scope and exposes it to the application
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents a _scope_, which is defined as an organization/project tuple.
|
||||
* This class is intended as a simple data structure and is used by the
|
||||
* scope service (see below).
|
||||
* Immutable.
|
||||
*/
|
||||
class Scope {
|
||||
/**
|
||||
* @type {?object}
|
||||
* @private
|
||||
*/
|
||||
#org = null;
|
||||
|
||||
/**
|
||||
* @type {?object}
|
||||
* @private
|
||||
*/
|
||||
#project = null;
|
||||
|
||||
/**
|
||||
* Initializes an instance of `Scope` with optional org and/or project.
|
||||
* @param {?object} org
|
||||
* @param {?object} project
|
||||
*/
|
||||
constructor(org = null, project = null) {
|
||||
if (org) this.#org = org;
|
||||
if (project) this.#project = project;
|
||||
}
|
||||
|
||||
/**
|
||||
* Org for this scope. Immutable.
|
||||
* @type {?object}
|
||||
*/
|
||||
get org() {
|
||||
return this.#org;
|
||||
}
|
||||
|
||||
/**
|
||||
* Project for this scope. If org is null, so is project.
|
||||
* @type {?object}
|
||||
*/
|
||||
get project() {
|
||||
return this.org ? this.#project : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the JSON serialization of this scope.
|
||||
* @return {?object}
|
||||
*/
|
||||
toJSON() {
|
||||
const { org, project } = this;
|
||||
return JSON.stringify({ org, project });
|
||||
}
|
||||
}
|
||||
|
||||
export { Scope };
|
||||
|
||||
/**
|
||||
* The scope service manages and persists the current scope. 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.
|
||||
*
|
||||
* For now, should an invalid scope arise, it is left to the user to refresh,
|
||||
* since they are likely to encounter 404s. This is an acceptable tradeoff for
|
||||
* an initial release because invalid scopes are considered uncommon.
|
||||
*/
|
||||
export default class ScopeService extends Service {
|
||||
/**
|
||||
* The currently selected scope.
|
||||
* @type {?Scope}
|
||||
*/
|
||||
@tracked scope = null;
|
||||
|
||||
/**
|
||||
* When setting org, `service.org = {...}`, a new scope is instantiated,
|
||||
* since scopes are immutable.
|
||||
* @type {?object}
|
||||
*/
|
||||
@computed('scope.org')
|
||||
get org() {
|
||||
return this.scope ? this.scope.org : null;
|
||||
}
|
||||
set org(org) {
|
||||
this.scope = new Scope(org, this.project);
|
||||
}
|
||||
|
||||
/**
|
||||
* When setting project, `service.project = {...}`, a new scope is
|
||||
* instantiated, since scopes are immutable.
|
||||
* @type {?object}
|
||||
*/
|
||||
@computed('scope.project')
|
||||
get project() {
|
||||
return this.scope ? this.scope.project : null;
|
||||
}
|
||||
set project(project) {
|
||||
this.scope = new Scope(this.org, project);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { default, Scope } from 'api/services/scope';
|
||||
@@ -0,0 +1,10 @@
|
||||
import Route from '@ember/routing/route';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
export default class ApplicationRoute extends Route {
|
||||
@service scope;
|
||||
|
||||
afterModel() {
|
||||
//console.log(this.scope);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
<h2 id="title">Welcome to Ember</h2>
|
||||
|
||||
{{outlet}}
|
||||
{{outlet}}
|
||||
@@ -0,0 +1 @@
|
||||
index
|
||||
@@ -0,0 +1,67 @@
|
||||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
import { Scope } from '../../../services/scope';
|
||||
|
||||
module('Unit | Service | scope class', function (hooks) {
|
||||
setupTest(hooks);
|
||||
|
||||
test('it provides a scope class', function (assert) {
|
||||
assert.expect(1);
|
||||
assert.ok(Scope);
|
||||
});
|
||||
|
||||
test('it has initializable org and project members', function (assert) {
|
||||
assert.expect(2);
|
||||
const org = { id: 1 };
|
||||
const project = { id: 2 };
|
||||
const scope = new Scope(org, project);
|
||||
assert.equal(scope.org.id, 1);
|
||||
assert.equal(scope.project.id, 2);
|
||||
});
|
||||
|
||||
test('it has a null project if org is null, even if project was initialized to non-null', function (assert) {
|
||||
assert.expect(2);
|
||||
const org = null;
|
||||
const project = { id: 2 };
|
||||
const scope = new Scope(org, project);
|
||||
assert.notOk(scope.org);
|
||||
assert.notOk(scope.project);
|
||||
});
|
||||
|
||||
test('it serializes to JSON', function (assert) {
|
||||
assert.expect(2);
|
||||
let scope = new Scope({ id: 1 });
|
||||
assert.deepEqual(JSON.parse(scope.toJSON()), {
|
||||
org: { id: 1 },
|
||||
project: null,
|
||||
});
|
||||
scope = new Scope({ id: 1 }, { id: 2 });
|
||||
assert.deepEqual(JSON.parse(scope.toJSON()), {
|
||||
org: { id: 1 },
|
||||
project: { id: 2 },
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
module('Unit | Service | scope', function (hooks) {
|
||||
setupTest(hooks);
|
||||
|
||||
test('it returns nulls when scope is not set', function (assert) {
|
||||
assert.expect(3);
|
||||
const service = this.owner.lookup('service:scope');
|
||||
assert.equal(service.scope, null);
|
||||
assert.equal(service.org, null);
|
||||
assert.equal(service.project, null);
|
||||
});
|
||||
|
||||
test('it aliases org and project to a scope instance', 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.org, service.scope.org);
|
||||
assert.equal(service.project, service.scope.project);
|
||||
});
|
||||
});
|
||||
@@ -3,8 +3,8 @@ import { action } from '@ember/object';
|
||||
|
||||
export default class IndexController extends Controller {
|
||||
@action
|
||||
selectChange(value) {
|
||||
selectChange(/*value*/) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(value);
|
||||
//console.log(value);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user