mirror of
https://github.com/flarum/framework.git
synced 2024-11-25 17:57:04 +08:00
Upgrade ember-cli to 0.1.4 and fix related breakage. closes #18
This commit is contained in:
parent
9365205ac4
commit
238bb40360
|
@ -1,3 +1,4 @@
|
|||
{
|
||||
"directory": "vendor"
|
||||
"directory": "bower_components",
|
||||
"analytics": false
|
||||
}
|
||||
|
|
33
ember/.editorconfig
Normal file
33
ember/.editorconfig
Normal file
|
@ -0,0 +1,33 @@
|
|||
# EditorConfig helps developers define and maintain consistent
|
||||
# coding styles between different editors and IDEs
|
||||
# editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.js]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.hbs]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.css]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.html]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
9
ember/.ember-cli
Normal file
9
ember/.ember-cli
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
/**
|
||||
Ember CLI sends analytics information by default. The data is completely
|
||||
anonymous, but there are times when you might want to disable this behavior.
|
||||
|
||||
Setting `disableAnalytics` to true will prevent any data from being sent.
|
||||
*/
|
||||
"disableAnalytics": false
|
||||
}
|
3
ember/.gitignore
vendored
3
ember/.gitignore
vendored
|
@ -6,8 +6,7 @@
|
|||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/vendor/*
|
||||
!/vendor/json-api.js
|
||||
/bower_components
|
||||
|
||||
# misc
|
||||
/.sass-cache
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"predef": {
|
||||
"document": true,
|
||||
"window": true,
|
||||
"FlarumENV": true
|
||||
},
|
||||
"browser" : true,
|
||||
"boss" : true,
|
||||
"predef": [
|
||||
"document",
|
||||
"window",
|
||||
"-Promise"
|
||||
],
|
||||
"browser": true,
|
||||
"boss": true,
|
||||
"curly": true,
|
||||
"debug": false,
|
||||
"devel": true,
|
||||
|
|
20
ember/.travis.yml
Normal file
20
ember/.travis.yml
Normal file
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
language: node_js
|
||||
|
||||
sudo: false
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
||||
|
||||
before_install:
|
||||
- "npm config set spin false"
|
||||
- "npm install -g npm@^2"
|
||||
|
||||
install:
|
||||
- npm install -g bower
|
||||
- npm install
|
||||
- bower install
|
||||
|
||||
script:
|
||||
- npm test
|
|
@ -4,16 +4,15 @@ var EmberApp = require('ember-cli/lib/broccoli/ember-app');
|
|||
|
||||
var app = new EmberApp();
|
||||
|
||||
app.import('vendor/bootstrap/dist/js/bootstrap.js');
|
||||
app.import('vendor/spin.js/spin.js');
|
||||
app.import('vendor/spin.js/jquery.spin.js');
|
||||
app.import('vendor/moment/moment.js');
|
||||
app.import('vendor/json-api.js');
|
||||
app.import('bower_components/bootstrap/dist/js/bootstrap.js');
|
||||
app.import('bower_components/spin.js/spin.js');
|
||||
app.import('bower_components/spin.js/jquery.spin.js');
|
||||
app.import('bower_components/moment/moment.js');
|
||||
|
||||
app.import('vendor/font-awesome/fonts/fontawesome-webfont.eot');
|
||||
app.import('vendor/font-awesome/fonts/fontawesome-webfont.svg');
|
||||
app.import('vendor/font-awesome/fonts/fontawesome-webfont.ttf');
|
||||
app.import('vendor/font-awesome/fonts/fontawesome-webfont.woff');
|
||||
app.import('vendor/font-awesome/fonts/FontAwesome.otf');
|
||||
app.import('bower_components/font-awesome/fonts/fontawesome-webfont.eot');
|
||||
app.import('bower_components/font-awesome/fonts/fontawesome-webfont.svg');
|
||||
app.import('bower_components/font-awesome/fonts/fontawesome-webfont.ttf');
|
||||
app.import('bower_components/font-awesome/fonts/fontawesome-webfont.woff');
|
||||
app.import('bower_components/font-awesome/fonts/FontAwesome.otf');
|
||||
|
||||
module.exports = app.toTree();
|
||||
|
|
|
@ -1,26 +1,37 @@
|
|||
import Ember from 'ember';
|
||||
import DS from 'ember-data';
|
||||
|
||||
export default DS.JsonApiAdapter.extend({
|
||||
import JsonApiAdapter from 'ember-json-api/json-api-adapter';
|
||||
export default JsonApiAdapter.extend({
|
||||
host: '/api',
|
||||
|
||||
xhr: [],
|
||||
|
||||
ajax: function(url, type, hash) {
|
||||
var adapter = this;
|
||||
|
||||
return new Ember.RSVP.Promise(function(resolve, reject) {
|
||||
hash = adapter.ajaxOptions(url, type, hash);
|
||||
|
||||
hash.success = function(json) {
|
||||
Ember.run(null, resolve, json);
|
||||
};
|
||||
|
||||
hash.error = function(jqXHR, textStatus, errorThrown) {
|
||||
Ember.run(null, reject, adapter.ajaxError(jqXHR));
|
||||
};
|
||||
|
||||
adapter.xhr.push(Ember.$.ajax(hash));
|
||||
}, "DS: RestAdapter#ajax " + type + " to " + url);
|
||||
},
|
||||
findQuery: function(store, type, query) {
|
||||
var ids = null;
|
||||
if (query.ids) {
|
||||
ids = query.ids.join(',');
|
||||
delete query.ids;
|
||||
}
|
||||
return this.ajax(this.buildURL(type.typeKey, ids), 'GET', {data: query});
|
||||
},
|
||||
});
|
||||
|
||||
// export default DS.JsonApiAdapter.extend({
|
||||
// host: '/api',
|
||||
|
||||
// // xhr: [],
|
||||
|
||||
// // ajax: function(url, type, hash) {
|
||||
// // var adapter = this;
|
||||
|
||||
// // return new Ember.RSVP.Promise(function(resolve, reject) {
|
||||
// // hash = adapter.ajaxOptions(url, type, hash);
|
||||
|
||||
// // hash.success = function(json) {
|
||||
// // Ember.run(null, resolve, json);
|
||||
// // };
|
||||
|
||||
// // hash.error = function(jqXHR, textStatus, errorThrown) {
|
||||
// // Ember.run(null, reject, adapter.ajaxError(jqXHR));
|
||||
// // };
|
||||
|
||||
// // adapter.xhr.push(Ember.$.ajax(hash));
|
||||
// // }, "DS: RestAdapter#ajax " + type + " to " + url);
|
||||
// // },
|
||||
// });
|
||||
|
|
|
@ -1,21 +1,17 @@
|
|||
import Ember from 'ember';
|
||||
import Resolver from 'ember/resolver';
|
||||
import loadInitializers from 'ember/load-initializers';
|
||||
import config from './config/environment';
|
||||
|
||||
Ember.MODEL_FACTORY_INJECTIONS = true;
|
||||
|
||||
var App = Ember.Application.extend({
|
||||
modulePrefix: 'flarum', // TODO: loaded via config
|
||||
Resolver: Resolver,
|
||||
|
||||
registerPlugin: function(plugin) {
|
||||
console.log('Plugin loaded: '+plugin.name);
|
||||
plugin.boot();
|
||||
}
|
||||
modulePrefix: config.modulePrefix,
|
||||
podModulePrefix: config.podModulePrefix,
|
||||
Resolver: Resolver
|
||||
});
|
||||
|
||||
loadInitializers(App, 'flarum');
|
||||
|
||||
loadInitializers(App, config.modulePrefix);
|
||||
|
||||
//-----------------------------------------
|
||||
// TODO: Move all this to an initializer
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Handlebars.makeBoundHelper(function(number, options) {
|
||||
return new Handlebars.SafeString(number);
|
||||
return new Ember.Handlebars.SafeString(''+number);
|
||||
});
|
||||
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
import Ember from 'ember';
|
||||
|
||||
// This helper takes a post as its argument and renders a certain component
|
||||
// corresponding to the post's type. The naming convention is 'post-type-[type]'
|
||||
// (for example, post-type-comment for a comment.) Other arguments added to the
|
||||
// helper are passed through to the component.
|
||||
|
||||
export default Ember.Handlebars.makeBoundHelper(function(post, options) {
|
||||
options.hash.post = post;
|
||||
var component = 'post-type-'+post.get('type');
|
||||
var helper = Ember.Handlebars.resolveHelper(options.data.view.container, component);
|
||||
|
||||
helper.call(this, options);
|
||||
});
|
|
@ -7,20 +7,19 @@
|
|||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
{{BASE_TAG}}
|
||||
{{content-for 'head'}}
|
||||
|
||||
<link rel="stylesheet" href="assets/vendor.css">
|
||||
<link rel="stylesheet" href="assets/flarum.css">
|
||||
|
||||
{{content-for 'head-footer'}}
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
window.FlarumENV = {{ENV}};
|
||||
window.EmberENV = window.FlarumENV.EmberENV;
|
||||
</script>
|
||||
{{content-for 'body'}}
|
||||
|
||||
<script src="assets/vendor.js"></script>
|
||||
<script src="assets/flarum.js"></script>
|
||||
<script>
|
||||
window.Flarum = require('flarum/app')['default'].create(FlarumENV.APP);
|
||||
</script>
|
||||
|
||||
{{content-for 'body-footer'}}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
import Ember from 'ember';
|
||||
import config from './config/environment';
|
||||
|
||||
console.log(config.locationType);
|
||||
var Router = Ember.Router.extend({
|
||||
location: FlarumENV.locationType
|
||||
location: config.locationType
|
||||
});
|
||||
|
||||
Router.map(function() {
|
||||
|
||||
this.resource('categories', { path: '/categories' });
|
||||
this.resource('categories', { path: '/categories' });
|
||||
|
||||
this.resource('discussions', { path: '/' }, function() {
|
||||
this.resource('discussion', { path: '/:id/:slug' });
|
||||
|
@ -18,7 +19,6 @@ Router.map(function() {
|
|||
this.route('discussions');
|
||||
this.route('preferences');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
export default Router;
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
import Ember from 'ember';
|
||||
import DS from 'ember-data';
|
||||
import JsonApiSerializer from 'ember-json-api/json-api-serializer';
|
||||
export default JsonApiSerializer.extend({
|
||||
normalize: function(type, hash, property) {
|
||||
var json = {};
|
||||
|
||||
export default DS.JsonApiSerializer.extend({
|
||||
normalize: function(type, hash, property) {
|
||||
var json = {};
|
||||
for (var prop in hash) {
|
||||
json[prop.camelize()] = hash[prop];
|
||||
}
|
||||
|
||||
for (var prop in hash) {
|
||||
json[prop.camelize()] = hash[prop];
|
||||
}
|
||||
|
||||
return this._super(type, json, property);
|
||||
}
|
||||
});
|
||||
return this._super(type, json, property);
|
||||
}
|
||||
});
|
|
@ -10,4 +10,4 @@
|
|||
{{!-- #{{view.post.number}} (ID: {{view.post.id}}) --}}
|
||||
{{/link-to}}
|
||||
|
||||
{{post-content view.post}}
|
||||
{{dynamic-component type=view.contentComponent post=view.post}}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<div class="controls btn-group">
|
||||
{{!-- <div class="controls btn-group">
|
||||
<button data-toggle="dropdown" class="dropdown-toggle btn btn-default btn-xs btn-icon">{{fa-icon "caret-down"}}</button>
|
||||
{{menu-list items=view.controls class="dropdown-menu pull-right"}}
|
||||
</div>
|
||||
</div> --}}
|
||||
|
||||
<div class="discussion">
|
||||
|
||||
|
@ -40,7 +40,7 @@
|
|||
{{#link-to "user" discussion.lastUser}}{{user-avatar discussion.lastUser class="avatar-thumb"}}{{/link-to}}
|
||||
{{#link-to "discussion" discussion.content (query-params start="last")}}{{abbreviate-time discussion.lastTime}}{{/link-to}}
|
||||
{{/if}}
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<span class="replies">{{abbreviate-number discussion.repliesCount}}</span>
|
||||
|
||||
|
|
|
@ -9,6 +9,10 @@ export default Ember.View.extend({
|
|||
|
||||
controls: null,
|
||||
|
||||
contentComponent: function() {
|
||||
return 'post-type-'+this.get('post.type');
|
||||
}.property('post.type'),
|
||||
|
||||
classNames: ['post'],
|
||||
classNameBindings: ['post.deleted', 'post.edited'],
|
||||
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
{
|
||||
"name": "flarum",
|
||||
"dependencies": {
|
||||
"handlebars": "~1.3.0",
|
||||
"handlebars": "2.0.0",
|
||||
"jquery": "^1.11.1",
|
||||
"qunit": "~1.12.0",
|
||||
"ember-qunit": "~0.1.8",
|
||||
"ember": "~1.7.0",
|
||||
"ember-resolver": "~0.1.5",
|
||||
"loader": "stefanpenner/loader.js#1.0.0",
|
||||
"ember-cli-shims": "stefanpenner/ember-cli-shims#0.0.2",
|
||||
"ember": "1.9.0",
|
||||
"ember-data": "1.0.0-beta.12",
|
||||
"ember-resolver": "~0.1.10",
|
||||
"loader.js": "stefanpenner/loader.js#1.0.1",
|
||||
"ember-cli-shims": "stefanpenner/ember-cli-shims#0.0.3",
|
||||
"ember-cli-test-loader": "rwjblue/ember-cli-test-loader#0.0.4",
|
||||
"ember-load-initializers": "stefanpenner/ember-load-initializers#0.0.2",
|
||||
"ember-qunit-notifications": "^0.0.3",
|
||||
"ember-cli-test-loader": "rjackson/ember-cli-test-loader#0.0.2",
|
||||
"ember-qunit": "0.1.8",
|
||||
"ember-qunit-notifications": "0.0.4",
|
||||
"qunit": "~1.15.0",
|
||||
"bootstrap": "~3.2.0",
|
||||
"font-awesome": "~4",
|
||||
"spin.js": "~1.3.3",
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
|
||||
module.exports = function(environment) {
|
||||
var ENV = {
|
||||
modulePrefix: 'flarum',
|
||||
environment: environment,
|
||||
baseURL: '/',
|
||||
locationType: 'auto',
|
||||
locationType: 'hash',
|
||||
EmberENV: {
|
||||
FEATURES: {
|
||||
// Here you can enable experimental features on an ember canary build
|
||||
|
@ -27,7 +28,15 @@ module.exports = function(environment) {
|
|||
}
|
||||
|
||||
if (environment === 'test') {
|
||||
// Testem prefers this...
|
||||
ENV.baseURL = '/';
|
||||
ENV.locationType = 'none';
|
||||
|
||||
// keep test console output quieter
|
||||
ENV.APP.LOG_ACTIVE_GENERATION = false;
|
||||
ENV.APP.LOG_VIEW_LOOKUPS = false;
|
||||
|
||||
ENV.APP.rootElement = '#ember-testing';
|
||||
}
|
||||
|
||||
if (environment === 'production') {
|
||||
|
|
|
@ -4,31 +4,35 @@
|
|||
"private": true,
|
||||
"directories": {
|
||||
"doc": "doc",
|
||||
"test": "test"
|
||||
"test": "tests"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "ember server",
|
||||
"build": "ember build",
|
||||
"test": "ember test"
|
||||
},
|
||||
"repository": "https://github.com/stefanpenner/ember-cli",
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"node": ">= 0.10.0"
|
||||
},
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"body-parser": "^1.2.0",
|
||||
"broccoli-asset-rev": "0.0.17",
|
||||
"broccoli-ember-hbs-template-compiler": "^1.5.0",
|
||||
"broccoli-less-single": "^0.1.4",
|
||||
"ember-cli": "0.0.40",
|
||||
"ember-cli-autoprefixer": "^0.1.0",
|
||||
"ember-cli-ember-data": "0.1.0",
|
||||
"broccoli-asset-rev": "^1.0.0",
|
||||
"ember-cli": "0.1.4",
|
||||
"ember-cli-content-security-policy": "0.3.0",
|
||||
"ember-cli-dependency-checker": "0.0.6",
|
||||
"ember-cli-esnext": "0.1.1",
|
||||
"ember-cli-htmlbars": "^0.5.4",
|
||||
"ember-cli-ic-ajax": "0.1.1",
|
||||
"express": "^4.1.1",
|
||||
"glob": "^3.2.9",
|
||||
"liquid-fire": "^0.9.2",
|
||||
"originate": "0.1.5"
|
||||
"ember-cli-inject-live-reload": "^1.3.0",
|
||||
"ember-cli-qunit": "0.1.2",
|
||||
"ember-data": "1.0.0-beta.12",
|
||||
"ember-dynamic-component": "0.0.4",
|
||||
"ember-export-application-global": "^1.0.0",
|
||||
"ember-json-api": "^0.2.3",
|
||||
"express": "^4.8.5",
|
||||
"glob": "^4.0.5",
|
||||
"liquid-fire": "^0.9.2"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
{
|
||||
"framework": "qunit",
|
||||
"test_page": "tests/index.html",
|
||||
"launch_in_ci": ["PhantomJS"],
|
||||
"launch_in_dev": ["PhantomJS", "Chrome"]
|
||||
"launch_in_ci": [
|
||||
"PhantomJS"
|
||||
],
|
||||
"launch_in_dev": [
|
||||
"PhantomJS",
|
||||
"Chrome"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
"location",
|
||||
"setTimeout",
|
||||
"$",
|
||||
"-Promise",
|
||||
"QUnit",
|
||||
"define",
|
||||
"console",
|
||||
|
@ -33,11 +34,11 @@
|
|||
"fillIn",
|
||||
"click",
|
||||
"keyEvent",
|
||||
"triggerEvent",
|
||||
"find",
|
||||
"findWithAssert",
|
||||
"wait",
|
||||
"DS",
|
||||
"keyEvent",
|
||||
"isolatedContainer",
|
||||
"startApp",
|
||||
"andThen",
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import Resolver from 'ember/resolver';
|
||||
import config from '../../config/environment';
|
||||
|
||||
var resolver = Resolver.create();
|
||||
|
||||
resolver.namespace = {
|
||||
modulePrefix: 'flarum'
|
||||
modulePrefix: config.modulePrefix,
|
||||
podModulePrefix: config.podModulePrefix
|
||||
};
|
||||
|
||||
export default resolver;
|
||||
|
|
|
@ -1,30 +1,19 @@
|
|||
/* global require */
|
||||
|
||||
var Application = require('flarum/app')['default'];
|
||||
var Router = require('flarum/router')['default'];
|
||||
import Ember from 'ember';
|
||||
import Application from '../../app';
|
||||
import Router from '../../router';
|
||||
import config from '../../config/environment';
|
||||
|
||||
export default function startApp(attrs) {
|
||||
var App;
|
||||
|
||||
var attributes = Ember.merge({
|
||||
// useful Test defaults
|
||||
rootElement: '#ember-testing',
|
||||
LOG_ACTIVE_GENERATION:false,
|
||||
LOG_VIEW_LOOKUPS: false
|
||||
}, attrs); // but you can override;
|
||||
var attributes = Ember.merge({}, config.APP);
|
||||
attributes = Ember.merge(attributes, attrs); // use defaults, but you can override;
|
||||
|
||||
Router.reopen({
|
||||
location: 'none'
|
||||
});
|
||||
|
||||
Ember.run(function(){
|
||||
Ember.run(function() {
|
||||
App = Application.create(attributes);
|
||||
App.setupForTesting();
|
||||
App.injectTestHelpers();
|
||||
});
|
||||
|
||||
App.reset(); // this shouldn't be needed, i want to be able to "start an app at a specific URL"
|
||||
|
||||
return App;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
{{BASE_TAG}}
|
||||
{{content-for 'head'}}
|
||||
{{content-for 'test-head'}}
|
||||
|
||||
<link rel="stylesheet" href="assets/vendor.css">
|
||||
<link rel="stylesheet" href="assets/flarum.css">
|
||||
|
@ -28,22 +29,21 @@
|
|||
zoom: 50%;
|
||||
}
|
||||
</style>
|
||||
|
||||
{{content-for 'head-footer'}}
|
||||
{{content-for 'test-head-footer'}}
|
||||
</head>
|
||||
<body>
|
||||
<div id="qunit"></div>
|
||||
<div id="qunit-fixture"></div>
|
||||
|
||||
<script>
|
||||
window.FlarumENV = {{ENV}};
|
||||
window.EmberENV = window.FlarumENV.EmberENV;
|
||||
</script>
|
||||
<script src="assets/test-support.js"></script>
|
||||
{{content-for 'body'}}
|
||||
{{content-for 'test-body'}}
|
||||
<script src="assets/vendor.js"></script>
|
||||
<script src="assets/test-support.js"></script>
|
||||
<script src="assets/flarum.js"></script>
|
||||
<script src="testem.js"></script>
|
||||
<script>
|
||||
require('flarum/tests/test-helper');
|
||||
</script>
|
||||
<script src="assets/test-loader.js"></script>
|
||||
|
||||
{{content-for 'body-footer'}}
|
||||
{{content-for 'test-body-footer'}}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
import resolver from './helpers/resolver';
|
||||
import { setResolver } from 'ember-qunit';
|
||||
import {
|
||||
setResolver
|
||||
} from 'ember-qunit';
|
||||
|
||||
setResolver(resolver);
|
||||
|
||||
document.write('<div id="ember-testing-container"><div id="ember-testing"></div></div>');
|
||||
|
||||
QUnit.config.urlConfig.push({ id: 'nocontainer', label: 'Hide container'});
|
||||
var containerVisibility = QUnit.urlParams.nocontainer ? 'hidden' : 'visible';
|
||||
document.getElementById('ember-testing-container').style.visibility = containerVisibility;
|
||||
|
|
353
ember/vendor/json-api.js
vendored
353
ember/vendor/json-api.js
vendored
|
@ -1,353 +0,0 @@
|
|||
/*!
|
||||
* ember-json-api
|
||||
* Built on 2014-07-03
|
||||
* http://github.com/daliwali/ember-json-api
|
||||
* Copyright (c) 2014 Dali Zheng
|
||||
*/
|
||||
(function() {
|
||||
"use strict";
|
||||
var get = Ember.get;
|
||||
var isNone = Ember.isNone;
|
||||
|
||||
DS.JsonApiSerializer = DS.RESTSerializer.extend({
|
||||
/**
|
||||
* Patch the extractSingle method, since there are no singular records
|
||||
*/
|
||||
extractSingle: function(store, primaryType, payload, recordId) {
|
||||
var primaryTypeName;
|
||||
if (this.keyForAttribute) {
|
||||
primaryTypeName = this.keyForAttribute(primaryType.typeKey);
|
||||
} else {
|
||||
primaryTypeName = primaryType.typeKey;
|
||||
}
|
||||
|
||||
var json = {};
|
||||
|
||||
for (var key in payload) {
|
||||
var typeName = Ember.String.singularize(key);
|
||||
if (typeName === primaryTypeName &&
|
||||
Ember.isArray(payload[key])) {
|
||||
json[typeName] = payload[key][0];
|
||||
} else {
|
||||
json[key] = payload[key];
|
||||
}
|
||||
}
|
||||
return this._super(store, primaryType, json, recordId);
|
||||
},
|
||||
|
||||
extractArray: function(store, primaryType, payload) {
|
||||
var primaryTypeName;
|
||||
if (this.keyForAttribute) {
|
||||
primaryTypeName = this.keyForAttribute(primaryType.typeKey);
|
||||
} else {
|
||||
primaryTypeName = primaryType.typeKey;
|
||||
}
|
||||
|
||||
for (var key in payload) {
|
||||
var typeName = Ember.String.singularize(key);
|
||||
if (typeName === primaryTypeName &&
|
||||
! Ember.isArray(payload[key])) {
|
||||
payload[key] = [payload[key]];
|
||||
}
|
||||
}
|
||||
|
||||
return this._super(store, primaryType, payload);
|
||||
},
|
||||
|
||||
/**
|
||||
* Flatten links
|
||||
*/
|
||||
normalize: function(type, hash, prop) {
|
||||
var json = {};
|
||||
for (var key in hash) {
|
||||
if (key !== 'links') {
|
||||
json[key] = hash[key];
|
||||
} else if (typeof hash[key] === 'object') {
|
||||
for (var link in hash[key]) {
|
||||
json[link] = hash[key][link];
|
||||
}
|
||||
}
|
||||
}
|
||||
return this._super(type, json, prop);
|
||||
},
|
||||
|
||||
/**
|
||||
* Extract top-level "meta" & "links" before normalizing.
|
||||
*/
|
||||
normalizePayload: function(payload) {
|
||||
// if (payload.meta) {
|
||||
// this.extractMeta(payload.meta);
|
||||
// delete payload.meta;
|
||||
// }
|
||||
if (payload.links) {
|
||||
this.extractLinks(payload.links);
|
||||
delete payload.links;
|
||||
}
|
||||
if (payload.linked) {
|
||||
this.extractLinked(payload.linked);
|
||||
delete payload.linked;
|
||||
}
|
||||
return payload;
|
||||
},
|
||||
|
||||
/**
|
||||
* Extract top-level "linked" containing associated objects
|
||||
*/
|
||||
extractLinked: function(linked) {
|
||||
var link, values, value, relation;
|
||||
var store = get(this, 'store');
|
||||
|
||||
for (link in linked) {
|
||||
values = linked[link];
|
||||
for (var i = values.length - 1; i >= 0; i--) {
|
||||
value = values[i];
|
||||
|
||||
if (value.links) {
|
||||
for (relation in value.links) {
|
||||
value[relation] = value.links[relation];
|
||||
}
|
||||
delete value.links;
|
||||
}
|
||||
}
|
||||
}
|
||||
store.pushPayload(linked);
|
||||
},
|
||||
|
||||
/**
|
||||
* Override this method to parse the top-level "meta" object per type.
|
||||
*/
|
||||
// extractMeta: function(meta) {
|
||||
// console.log(meta);
|
||||
// // store.metaForType(type, payload.meta);
|
||||
// },
|
||||
|
||||
/**
|
||||
* Parse the top-level "links" object.
|
||||
*/
|
||||
extractLinks: function(links) {
|
||||
var link, key, value, route;
|
||||
var extracted = [], linkEntry, linkKey;
|
||||
|
||||
for (link in links) {
|
||||
key = link.split('.').pop();
|
||||
value = links[link];
|
||||
if (typeof value === 'string') {
|
||||
route = value;
|
||||
} else {
|
||||
key = value.type || key;
|
||||
route = value.href;
|
||||
}
|
||||
|
||||
// strip base url
|
||||
if (route.substr(0, 4).toLowerCase() === 'http') {
|
||||
route = route.split('//').pop().split('/').slice(1).join('/');
|
||||
}
|
||||
|
||||
// strip prefix slash
|
||||
if (route.charAt(0) === '/') {
|
||||
route = route.substr(1);
|
||||
}
|
||||
linkEntry = { };
|
||||
linkKey = Ember.String.singularize(key);
|
||||
linkEntry[linkKey] = route;
|
||||
extracted.push(linkEntry);
|
||||
DS._routes[linkKey] = route;
|
||||
}
|
||||
|
||||
return extracted;
|
||||
},
|
||||
|
||||
// SERIALIZATION
|
||||
|
||||
/**
|
||||
* Use "links" key, remove support for polymorphic type
|
||||
*/
|
||||
serializeBelongsTo: function(record, json, relationship) {
|
||||
var key = relationship.key;
|
||||
var belongsTo = get(record, key);
|
||||
|
||||
if (isNone(belongsTo)) return;
|
||||
|
||||
json.links = json.links || {};
|
||||
json.links[key] = get(belongsTo, 'id');
|
||||
},
|
||||
|
||||
/**
|
||||
* Use "links" key
|
||||
*/
|
||||
serializeHasMany: function(record, json, relationship) {
|
||||
var key = relationship.key;
|
||||
|
||||
var relationshipType = DS.RelationshipChange.determineRelationshipType(record.constructor, relationship);
|
||||
|
||||
if (relationshipType === 'manyToNone' ||
|
||||
relationshipType === 'manyToMany') {
|
||||
json.links = json.links || {};
|
||||
json.links[key] = get(record, key).mapBy('id');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}).call(this);
|
||||
|
||||
(function() {
|
||||
"use strict";
|
||||
var get = Ember.get;
|
||||
|
||||
/**
|
||||
* Keep a record of routes to resources by type.
|
||||
*/
|
||||
|
||||
// null prototype in es5 browsers wont allow collisions with things on the
|
||||
// global Object.prototype.
|
||||
DS._routes = Ember.create(null);
|
||||
|
||||
DS.JsonApiAdapter = DS.RESTAdapter.extend({
|
||||
defaultSerializer: 'DS/jsonApi',
|
||||
/**
|
||||
* Look up routes based on top-level links.
|
||||
*/
|
||||
buildURL: function(typeName, id) {
|
||||
// TODO: this basically only works in the simplest of scenarios
|
||||
var route = DS._routes[typeName];
|
||||
if (!!route) {
|
||||
var url = [];
|
||||
var host = get(this, 'host');
|
||||
var prefix = this.urlPrefix();
|
||||
var param = /\{(.*?)\}/g;
|
||||
|
||||
if (id) {
|
||||
if (param.test(route)) {
|
||||
url.push(route.replace(param, id));
|
||||
} else {
|
||||
url.push(route, id);
|
||||
}
|
||||
} else {
|
||||
url.push(route.replace(param, ''));
|
||||
}
|
||||
|
||||
if (prefix) { url.unshift(prefix); }
|
||||
|
||||
url = url.join('/');
|
||||
if (!host && url) { url = '/' + url; }
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
return this._super(typeName, id);
|
||||
},
|
||||
|
||||
/**
|
||||
* Fix query URL.
|
||||
*/
|
||||
findMany: function(store, type, ids, owner) {
|
||||
return this.ajax(this.buildURL(type.typeKey, ids.join(',')), 'GET');
|
||||
},
|
||||
|
||||
findQuery: function(store, type, query) {
|
||||
var ids = null;
|
||||
if (query.ids) {
|
||||
ids = query.ids.join(',');
|
||||
delete query.ids;
|
||||
}
|
||||
return this.ajax(this.buildURL(type.typeKey, ids), 'GET', {data: query});
|
||||
},
|
||||
|
||||
/**
|
||||
* Cast individual record to array,
|
||||
* and match the root key to the route
|
||||
*/
|
||||
createRecord: function(store, type, record) {
|
||||
var data = {};
|
||||
|
||||
data[this.pathForType(type.typeKey)] = [
|
||||
store.serializerFor(type.typeKey).serialize(record, {
|
||||
includeId: true
|
||||
})
|
||||
];
|
||||
|
||||
return this.ajax(this.buildURL(type.typeKey), 'POST', {
|
||||
data: data
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Cast individual record to array,
|
||||
* and match the root key to the route
|
||||
*/
|
||||
updateRecord: function(store, type, record) {
|
||||
var data = {};
|
||||
data[this.pathForType(type.typeKey)] = [
|
||||
store.serializerFor(type.typeKey).serialize(record)
|
||||
];
|
||||
|
||||
var id = get(record, 'id');
|
||||
|
||||
return this.ajax(this.buildURL(type.typeKey, id), 'PUT', {
|
||||
data: data
|
||||
});
|
||||
},
|
||||
|
||||
_tryParseErrorResponse: function(responseText) {
|
||||
try {
|
||||
return Ember.$.parseJSON(responseText);
|
||||
} catch(e) {
|
||||
return "Something went wrong";
|
||||
}
|
||||
},
|
||||
|
||||
ajaxError: function(jqXHR) {
|
||||
var error = this._super(jqXHR);
|
||||
var response;
|
||||
|
||||
if (jqXHR && typeof jqXHR === 'object') {
|
||||
response = this._tryParseErrorResponse(jqXHR.responseText);
|
||||
var errors = {};
|
||||
|
||||
if (response &&
|
||||
typeof response === 'object' &&
|
||||
response.errors !== undefined) {
|
||||
|
||||
Ember.A(Ember.keys(response.errors)).forEach(function(key) {
|
||||
errors[Ember.String.camelize(key)] = response.errors[key];
|
||||
});
|
||||
}
|
||||
|
||||
if (jqXHR.status === 422) {
|
||||
return new DS.InvalidError(errors);
|
||||
} else{
|
||||
return new ServerError(jqXHR.status, response, jqXHR);
|
||||
}
|
||||
} else {
|
||||
return error;
|
||||
}
|
||||
},
|
||||
/**
|
||||
Underscores the JSON root keys when serializing.
|
||||
|
||||
@method serializeIntoHash
|
||||
@param {Object} hash
|
||||
@param {subclass of DS.Model} type
|
||||
@param {DS.Model} record
|
||||
@param {Object} options
|
||||
*/
|
||||
serializeIntoHash: function(data, type, record, options) {
|
||||
var root = underscore(decamelize(type.typeKey));
|
||||
data[root] = this.serialize(record, options);
|
||||
}
|
||||
});
|
||||
|
||||
function ServerError(status, message, xhr) {
|
||||
this.status = status;
|
||||
this.message = message;
|
||||
this.xhr = xhr;
|
||||
|
||||
this.stack = new Error().stack;
|
||||
}
|
||||
|
||||
ServerError.prototype = Ember.create(Error.prototype);
|
||||
ServerError.constructor = ServerError;
|
||||
|
||||
DS.JsonApiAdapter.ServerError = ServerError;
|
||||
|
||||
}).call(this);
|
|
@ -9,19 +9,16 @@
|
|||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
|
||||
<meta name="flarum/config/environment" content="%7B%22modulePrefix%22%3A%22flarum%22%2C%22environment%22%3A%22development%22%2C%22baseURL%22%3A%22/%22%2C%22locationType%22%3A%22hash%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%7D%2C%22APP%22%3A%7B%22LOG_ACTIVE_GENERATION%22%3Atrue%2C%22LOG_VIEW_LOOKUPS%22%3Atrue%7D%2C%22contentSecurityPolicyHeader%22%3A%22Content-Security-Policy-Report-Only%22%2C%22contentSecurityPolicy%22%3A%7B%22default-src%22%3A%22%27none%27%22%2C%22script-src%22%3A%22%27self%27%20%27unsafe-eval%27%22%2C%22font-src%22%3A%22%27self%27%22%2C%22connect-src%22%3A%22%27self%27%22%2C%22img-src%22%3A%22%27self%27%22%2C%22style-src%22%3A%22%27self%27%22%2C%22media-src%22%3A%22%27self%27%22%7D%2C%22exportApplicationGlobal%22%3Atrue%7D" />
|
||||
|
||||
<base href="/">
|
||||
|
||||
{{ app('flarum.web.assetManager')->styles() }}
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
window.FlarumENV = {"environment":"development","baseURL":"/","EmberENV":{"FEATURES":{"query-params-new":true}},"APP":{"LOG_MODULE_RESOLVER":true,"LOG_TRANSITIONS":true,"LOG_TRANSITIONS_INTERNAL":true},"LOG_MODULE_RESOLVER":true};
|
||||
window.EmberENV = window.FlarumENV.EmberENV;
|
||||
</script>
|
||||
{{ app('flarum.web.assetManager')->scripts() }}
|
||||
<script>
|
||||
window.Flarum = require('flarum/app')['default'].create(FlarumENV.APP);
|
||||
// window.Flarum.registerPlugin(require('flarum/categories')['default']); // todo: make dynamic
|
||||
</script>
|
||||
</body>
|
||||
|
|
Loading…
Reference in New Issue
Block a user