diff --git a/app/assets/javascripts/admin/routes/admin-plugins.js.es6 b/app/assets/javascripts/admin/routes/admin-plugins.js.es6 index 3e8246ccc..ae7f961fd 100644 --- a/app/assets/javascripts/admin/routes/admin-plugins.js.es6 +++ b/app/assets/javascripts/admin/routes/admin-plugins.js.es6 @@ -1,6 +1,6 @@ export default Ember.Route.extend({ model() { - return Discourse.ajax("/admin/plugins.json").then(res => res.plugins); + return this.store.findAll('plugin'); }, actions: { diff --git a/app/assets/javascripts/discourse/adapters/rest.js.es6 b/app/assets/javascripts/discourse/adapters/rest.js.es6 new file mode 100644 index 000000000..a01491da9 --- /dev/null +++ b/app/assets/javascripts/discourse/adapters/rest.js.es6 @@ -0,0 +1,46 @@ +const ADMIN_MODELS = ['plugin']; + +function plural(type) { + return type + 's'; +} + +function pathFor(type) { + const path = "/" + plural(type); + + if (ADMIN_MODELS.indexOf(type) !== -1) { + return "/admin/" + path; + } + + return path; +} + +const _identityMap = {}; + +export default Ember.Object.extend({ + findAll(type) { + var self = this; + return Discourse.ajax(pathFor(type)).then(function(result) { + return result[plural(type)].map(obj => self._hydrate(type, obj)); + }); + }, + + _hydrate(type, obj) { + if (!obj) { throw "Can't hydrate " + type + " of `null`"; } + if (!obj.id) { throw "Can't hydrate " + type + " without an `id`"; } + + _identityMap[type] = _identityMap[type] || {}; + + const existing = _identityMap[type][obj.id]; + if (existing) { + delete obj.id; + existing.setProperties(obj); + return existing; + } + + const klass = this.container.lookupFactory('model:' + type) || Ember.Object; + const model = klass.create(obj); + _identityMap[type][obj.id] = model; + return model; + } + +}); diff --git a/app/assets/javascripts/discourse/ember/resolver.js.es6 b/app/assets/javascripts/discourse/ember/resolver.js.es6 index 896baca33..d6ce2e212 100644 --- a/app/assets/javascripts/discourse/ember/resolver.js.es6 +++ b/app/assets/javascripts/discourse/ember/resolver.js.es6 @@ -24,7 +24,7 @@ function loadingResolver(cb) { function parseName(fullName) { /*jshint validthis:true */ - var nameParts = fullName.split(":"), + const nameParts = fullName.split(":"), type = nameParts[0], fullNameWithoutType = nameParts[1], name = fullNameWithoutType, namespace = get(this, 'namespace'), @@ -85,6 +85,10 @@ export default Ember.DefaultResolver.extend({ return module; }, + resolveAdapter(parsedName) { + return this.customResolve(parsedName) || this._super(parsedName); + }, + resolveView(parsedName) { return this.findLoadingView(parsedName) || this.customResolve(parsedName) || this._super(parsedName); }, diff --git a/app/assets/javascripts/discourse/initializers/inject-objects.js.es6 b/app/assets/javascripts/discourse/initializers/inject-objects.js.es6 index 885a3edd1..fc37aad17 100644 --- a/app/assets/javascripts/discourse/initializers/inject-objects.js.es6 +++ b/app/assets/javascripts/discourse/initializers/inject-objects.js.es6 @@ -1,48 +1,53 @@ import Session from 'discourse/models/session'; import AppEvents from 'discourse/lib/app-events'; +import Store from 'discourse/models/store'; export default { name: "inject-objects", - initialize: function(container, application) { + initialize(container, app) { // Inject appEvents everywhere - var appEvents = AppEvents.create(); - application.register('app-events:main', appEvents, { instantiate: false }); + const appEvents = AppEvents.create(); + app.register('app-events:main', appEvents, { instantiate: false }); - application.inject('controller', 'appEvents', 'app-events:main'); - application.inject('component', 'appEvents', 'app-events:main'); - application.inject('route', 'appEvents', 'app-events:main'); - application.inject('view', 'appEvents', 'app-events:main'); - application.inject('model', 'appEvents', 'app-events:main'); + app.inject('controller', 'appEvents', 'app-events:main'); + app.inject('component', 'appEvents', 'app-events:main'); + app.inject('route', 'appEvents', 'app-events:main'); + app.inject('view', 'appEvents', 'app-events:main'); + app.inject('model', 'appEvents', 'app-events:main'); Discourse.URL.appEvents = appEvents; // Inject Discourse.Site to avoid using Discourse.Site.current() - var site = Discourse.Site.current(); - application.register('site:main', site, { instantiate: false }); - application.inject('controller', 'site', 'site:main'); - application.inject('component', 'site', 'site:main'); - application.inject('route', 'site', 'site:main'); - application.inject('view', 'site', 'site:main'); - application.inject('model', 'site', 'site:main'); + const site = Discourse.Site.current(); + app.register('site:main', site, { instantiate: false }); + app.inject('controller', 'site', 'site:main'); + app.inject('component', 'site', 'site:main'); + app.inject('route', 'site', 'site:main'); + app.inject('view', 'site', 'site:main'); + app.inject('model', 'site', 'site:main'); // Inject Discourse.SiteSettings to avoid using Discourse.SiteSettings globals - application.register('site-settings:main', Discourse.SiteSettings, { instantiate: false }); - application.inject('controller', 'siteSettings', 'site-settings:main'); - application.inject('component', 'siteSettings', 'site-settings:main'); - application.inject('route', 'siteSettings', 'site-settings:main'); - application.inject('view', 'siteSettings', 'site-settings:main'); - application.inject('model', 'siteSettings', 'site-settings:main'); + app.register('site-settings:main', Discourse.SiteSettings, { instantiate: false }); + app.inject('controller', 'siteSettings', 'site-settings:main'); + app.inject('component', 'siteSettings', 'site-settings:main'); + app.inject('route', 'siteSettings', 'site-settings:main'); + app.inject('view', 'siteSettings', 'site-settings:main'); + app.inject('model', 'siteSettings', 'site-settings:main'); // Inject Session for transient data - application.register('session:main', Session.current(), { instantiate: false }); - application.inject('controller', 'session', 'session:main'); - application.inject('component', 'session', 'session:main'); - application.inject('route', 'session', 'session:main'); - application.inject('view', 'session', 'session:main'); - application.inject('model', 'session', 'session:main'); + app.register('session:main', Session.current(), { instantiate: false }); + app.inject('controller', 'session', 'session:main'); + app.inject('component', 'session', 'session:main'); + app.inject('route', 'session', 'session:main'); + app.inject('view', 'session', 'session:main'); + app.inject('model', 'session', 'session:main'); // Inject currentUser. Components only for now to prevent any breakage - application.register('current-user:main', Discourse.User.current(), { instantiate: false }); - application.inject('component', 'currentUser', 'current-user:main'); + app.register('current-user:main', Discourse.User.current(), { instantiate: false }); + app.inject('component', 'currentUser', 'current-user:main'); + + app.register('store:main', Store); + app.inject('route', 'store', 'store:main'); + app.inject('controller', 'store', 'store:main'); } }; diff --git a/app/assets/javascripts/discourse/models/store.js.es6 b/app/assets/javascripts/discourse/models/store.js.es6 new file mode 100644 index 000000000..fed39da1d --- /dev/null +++ b/app/assets/javascripts/discourse/models/store.js.es6 @@ -0,0 +1,6 @@ +export default Ember.Object.extend({ + findAll(type) { + const adapter = this.container.lookup('adapter:' + type) || this.container.lookup('adapter:rest'); + return adapter.findAll(type); + } +}); diff --git a/app/assets/javascripts/main_include.js b/app/assets/javascripts/main_include.js index 2e7e7f43b..3e6caae85 100644 --- a/app/assets/javascripts/main_include.js +++ b/app/assets/javascripts/main_include.js @@ -24,6 +24,7 @@ //= require ./discourse/lib/autocomplete //= require ./discourse/lib/after-transition //= require ./discourse/lib/debounce +//= require_tree ./discourse/adapters //= require ./discourse/models/model //= require ./discourse/models/user_action //= require ./discourse/models/composer diff --git a/app/serializers/admin_plugin_serializer.rb b/app/serializers/admin_plugin_serializer.rb index 2c89c128b..09fdcc527 100644 --- a/app/serializers/admin_plugin_serializer.rb +++ b/app/serializers/admin_plugin_serializer.rb @@ -1,9 +1,14 @@ class AdminPluginSerializer < ApplicationSerializer - attributes :name, + attributes :id, + :name, :version, :url, :admin_route + def id + object.metadata.name + end + def name object.metadata.name end