first steps to ember-cli

This commit is contained in:
jelhan 2014-10-30 21:44:22 +01:00
parent 5243b6c046
commit 7a241bd311
94 changed files with 444 additions and 1547 deletions

View file

@ -1,3 +1,4 @@
{
"directory": "vendor"
"directory": "bower_components",
"analytics": false
}

33
.editorconfig Normal file
View 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-cli Normal file
View 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
}

11
.gitignore vendored
View file

@ -3,18 +3,15 @@
# compiled output
/dist
/tmp
/docs
# dependencies
/node_modules
/vendor/*
!/vendor/ember-shim.js
!/vendor/qunit-shim.js
/bower_components
# misc
/.sass-cache
/connect.lock
/libpeerconnection.log
.DS_Store
Thumbs.db
/coverage/*
/libpeerconnection.log
npm-debug.log
testem.log

View file

@ -1,22 +1,14 @@
{
"predef": {
"document": true,
"window": true,
"location": true,
"setTimeout": true,
"Ember": true,
"Em": true,
"DS": true,
"$": true,
"moment": true,
"sjcl": true
},
"node" : false,
"browser" : false,
"predef": [
"document",
"window",
"-Promise"
],
"browser" : true,
"boss" : true,
"curly": false,
"curly": true,
"debug": false,
"devel": false,
"devel": true,
"eqeqeq": true,
"evil": true,
"forin": false,
@ -35,5 +27,6 @@
"strict": false,
"white": false,
"eqnull": true,
"esnext": true
"esnext": true,
"unused": true
}

View file

@ -1,7 +1,16 @@
---
language: node_js
node_js:
- 0.10
before_script:
- npm install -g grunt-cli
sudo: false
cache:
directories:
- node_modules
install:
- npm install -g bower
- npm install
- bower install
script:
- npm test

56
Brocfile.js Normal file
View file

@ -0,0 +1,56 @@
/* global require, module */
var EmberApp = require('ember-cli/lib/broccoli/ember-app');
var app = new EmberApp();
// Use `app.import` to add additional libraries to the generated
// output files.
//
// If you need to use different assets in different
// environments, specify an object as the first parameter. That
// object's keys should be the environment name and the values
// should be the asset to use in that environment.
//
// If the library that you are including contains AMD or ES6
// modules that you would like to import into your application
// please specify an object with the list of modules as keys
// along with the exports of each module as its value.
app.import({
development: 'bower_components/moment/min/moment-with-locales.js',
production: 'bower_components/momemt/min/moment-with-locales.min.js'
});
app.import({
development: 'bower_components/bootstrap/dist/js/bootstrap.js',
production: 'bower_components/bootstrap/dist/js/bootstrap.min.js'
});
app.import('bower_components/bootstrap-datepicker/js/bootstrap-datepicker.js');
app.import('bower_components/ember-easyForm/index.js');
app.import('bower_components/cldr/plurals.js');
app.import('bower_components/ember-i18n/lib/i18n.js');
app.import('bower_components/ember-i18n/lib/i18n-plurals.js');
app.import({
development: 'bower_components/floatThead/dist/jquery.floatThead.js',
production: 'bower_components/floatThead/dist/jquery.floatThead.min.js'
});
app.import({
development: 'bower_components/webshim/js-webshim/dev/polyfiller.js',
production: 'bower_components/webshim/js-webshim/minified/polyfiller.js'
});
app.import('bower_components/ember-validations/index.js');
app.import('bower_components/sjcl/sjcl.js');
app.import('bower_components/modernizr/modernizr.js');
module.exports = app.toTree();

View file

@ -1,256 +0,0 @@
// jshint node:true
module.exports = function(grunt) {
// To support Coffeescript, SASS, LESS and others, just install
// the appropriate grunt package and it will be automatically included
// in the build process:
//
// * for Coffeescript, run `npm install --save-dev grunt-contrib-coffee`
//
// * for SCSS (without SASS), run `npm install --save-dev grunt-sass`
// * for SCSS/SASS support (may be slower), run
// `npm install --save-dev grunt-contrib-sass`
// This depends on the ruby sass gem, which can be installed with
// `gem install sass`
// * for Compass, run `npm install --save-dev grunt-contrib-compass`
// This depends on the ruby compass gem, which can be installed with
// `gem install compass`
// You should not install SASS if you have installed Compass.
//
// * for LESS, run `npm install --save-dev grunt-contrib-less`
//
// * for Stylus/Nib, `npm install --save-dev grunt-contrib-stylus`
//
// * for Emblem, run the following commands:
// `npm uninstall --save-dev grunt-ember-templates`
// `npm install --save-dev grunt-emblem`
// `bower install emblem.js --save`
//
// * For EmberScript, run `npm install --save-dev grunt-ember-script`
//
// * for LiveReload, `npm install --save-dev connect-livereload`
//
// * for YUIDoc support, `npm install --save-dev grunt-contrib-yuidoc`
// It is also nice to use a theme other than default. For example,
// simply do: `npm install yuidoc-theme-blue`
// Currently, only the `app` directory is used for generating docs.
// When installed, visit: http[s]://[host:port]/docs
//
// * for displaying the execution time of the grunt tasks,
// `npm install --save-dev time-grunt`
//
// * for minimizing the index.html at the end of the dist task
// `npm install --save-dev grunt-contrib-htmlmin`
//
// * for minimizing images in the dist task
// `npm install --save-dev grunt-contrib-imagemin`
//
// * for using images based CSS sprites (http://youtu.be/xD8DW6IQ6r0)
// `npm install --save-dev grunt-fancy-sprites`
// `bower install --save fancy-sprites-scss`
//
// * for automatically adding CSS vendor prefixes (autoprefixer)
// `npm install --save-dev grunt-autoprefixer`
//
// * for package import validations
// `npm install --save-dev grunt-es6-import-validate`
//
var Helpers = require('./tasks/helpers'),
filterAvailable = Helpers.filterAvailableTasks,
_ = grunt.util._,
path = require('path');
Helpers.pkg = require("./package.json");
if (Helpers.isPackageAvailable("time-grunt")) {
require("time-grunt")(grunt);
}
// Loads task options from `tasks/options/` and `tasks/custom-options`
// and loads tasks defined in `package.json`
var config = _.extend({},
require('load-grunt-config')(grunt, {
configPath: path.join(__dirname, 'tasks/options'),
loadGruntTasks: false,
init: false
}),
require('load-grunt-config')(grunt, { // Custom options have precedence
configPath: path.join(__dirname, 'tasks/custom-options'),
init: false
})
);
grunt.loadTasks('tasks'); // Loads tasks in `tasks/` folder
config.env = process.env;
// App Kit's Main Tasks
// ====================
// Generate the production version
// ------------------
grunt.registerTask('dist', "Build a minified & production-ready version of your app.", [
'clean:dist',
'build:dist',
'copy:assemble',
'createDistVersion'
]);
// Default Task
// ------------------
grunt.registerTask('default', "Build (in debug mode) & test your application.", ['test']);
// Servers
// -------------------
grunt.registerTask('server', "Run your server in development mode, auto-rebuilding when files change.", function(proxyMethod) {
var expressServerTask = 'expressServer:debug';
if (proxyMethod) {
expressServerTask += ':' + proxyMethod;
}
grunt.task.run(['clean:debug',
'build:debug',
expressServerTask,
'watch'
]);
});
grunt.registerTask('server:dist', "Build and preview a minified & production-ready version of your app.", [
'dist',
'expressServer:dist:keepalive'
]);
// Testing
// -------
grunt.registerTask('test', "Run your apps's tests once. Uses Google Chrome by default.", [
'clean:debug', 'build:debug', 'testem:ci:basic' ]);
grunt.registerTask('test:ci', "Run your app's tests in PhantomJS. For use in continuous integration (i.e. Travis CI).", [
'clean:debug', 'build:debug', 'testem:ci:basic' ]);
grunt.registerTask('test:browsers', "Run your app's tests in multiple browsers (see tasks/options/testem.js for configuration).", [
'clean:debug', 'build:debug', 'testem:ci:browsers' ]);
grunt.registerTask('test:server', "Alias to `testem:run:basic`. Be sure to install testem first using `npm install -g testem`", [
'testem:run:basic' ]);
// Worker tasks
// =================================
grunt.registerTask('build:dist', filterAvailable([
'createResultDirectory', // Create directoy beforehand, fixes race condition
'fancySprites:create',
'concurrent:buildDist', // Executed in parallel, see config below
]));
grunt.registerTask('build:debug', filterAvailable([
'jshint:tooling',
'createResultDirectory', // Create directoy beforehand, fixes race condition
'fancySprites:create',
'concurrent:buildDebug', // Executed in parallel, see config below
]));
grunt.registerTask('createDistVersion', filterAvailable([
'useminPrepare', // Configures concat, cssmin and uglify
'concat', // Combines css and javascript files
'cssmin', // Minifies css
'uglify', // Minifies javascript
'imagemin', // Optimizes image compression
// 'svgmin',
'copy:dist', // Copies files not covered by concat and imagemin
'rev', // Appends 8 char hash value to filenames
'usemin', // Replaces file references
'htmlmin:dist' // Removes comments and whitespace
]));
// Documentation
// -------
grunt.registerTask('docs', "Build YUIDoc documentation.", [
'buildDocs',
'server:debug'
]);
// Parallelize most of the build process
_.merge(config, {
concurrent: {
buildDist: [
"buildTemplates:dist",
"buildScripts",
"buildStyles",
"buildIndexHTML:dist"
],
buildDebug: [
"buildTemplates:debug",
"buildScripts",
"buildStyles",
"buildIndexHTML:debug"
]
}
});
// Templates
grunt.registerTask('buildTemplates:dist', filterAvailable([
'emblem:compile',
'emberTemplates:dist'
]));
grunt.registerTask('buildTemplates:debug', filterAvailable([
'emblem:compile',
'emberTemplates:debug'
]));
// Scripts
grunt.registerTask('buildScripts', filterAvailable([
'jshint:app',
'jshint:tests',
'validate-imports:app',
'validate-imports:tests',
'coffee',
'emberscript',
'copy:javascriptToTmp',
'transpile',
'buildDocs',
'concat_sourcemap'
]));
// Styles
grunt.registerTask('buildStyles', filterAvailable([
'compass:compile',
'sass:compile',
'less:compile',
'stylus:compile',
'copy:cssToResult',
'autoprefixer:app'
]));
// Documentation
grunt.registerTask('buildDocs', filterAvailable([
'yuidoc:debug',
]));
// Index HTML
grunt.registerTask('buildIndexHTML:dist', [
'preprocess:indexHTMLDistApp',
'preprocess:indexHTMLDistTests'
]);
grunt.registerTask('buildIndexHTML:debug', [
'preprocess:indexHTMLDebugApp',
'preprocess:indexHTMLDebugTests'
]);
grunt.registerTask('createResultDirectory', function() {
grunt.file.mkdir('tmp/result');
});
grunt.initConfig(config);
};

View file

@ -1,3 +1,5 @@
import DS from "ember-data";
export default DS.RESTAdapter.extend({
// set namespace to api.php in same subdirectory
namespace:

View file

@ -1,5 +1,10 @@
import Ember from 'ember';
import Resolver from 'ember/resolver';
import loadInitializers from 'ember/load-initializers';
import config from './config/environment';
import sjcl from 'sjcl';
Ember.MODEL_FACTORY_INJECTIONS = true;
// decrypt / encrypt computed property helper
Ember.computed.encrypted = function(encryptedField, dataType) {
@ -46,10 +51,9 @@ Ember.computed.encrypted = function(encryptedField, dataType) {
case 'date':
// https://github.com/emberjs/data/blob/master/packages/ember-data/lib/transforms/date.js
var type = typeof decryptedValue;
if (type === "string") {
if (typeof decryptedValue === "string") {
return new Date(Ember.Date.parse(decryptedValue));
} else if (type === "number") {
} else if (typeof decryptedValue === "number") {
return new Date(decryptedValue);
} else if (decryptedValue === null || decryptedValue === undefined) {
// if the value is not present in the data,
@ -68,12 +72,11 @@ Ember.computed.encrypted = function(encryptedField, dataType) {
case 'boolean':
// https://github.com/emberjs/data/blob/master/packages/ember-data/lib/transforms/boolean.js
var type = typeof decryptedValue;
if (type === "boolean") {
if (typeof decryptedValue === "boolean") {
return decryptedValue;
} else if (type === "string") {
} else if (typeof decryptedValue === "string") {
return decryptedValue.match(/^true$|^t$|^1$/i) !== null;
} else if (type === "number") {
} else if (typeof decryptedValue === "number") {
return decryptedValue === 1;
} else {
return false;
@ -83,16 +86,14 @@ Ember.computed.encrypted = function(encryptedField, dataType) {
};
var App = Ember.Application.extend({
modulePrefix: 'croodle', // TODO: loaded via config
modulePrefix: config.modulePrefix,
podModulePrefix: config.podModulePrefix,
Resolver: Resolver
});
import extendTextField from 'croodle/ext/text-field';
extendTextField();
import formattedDateHelper from 'croodle/helpers/formatted-date';
Ember.Handlebars.registerBoundHelper('formattedDate', formattedDateHelper);
loadInitializers(App, 'croodle');
loadInitializers(App, config.modulePrefix);
export default App;

View file

@ -1,3 +1,5 @@
import Ember from "ember";
export default Ember.Component.extend({
classNames: ['pretty-color'],
attributeBindings: ['style'],

View file

@ -1,3 +1,5 @@
import Ember from "ember";
export default Ember.Component.extend({
classNames: ['look-ma-no-template'],
tagName: ['span']

View file

@ -1,3 +1,6 @@
import Ember from "ember";
import $ from "jquery";
export default Ember.ObjectController.extend(Ember.Validations.Mixin, {
actions: {
save: function() {
@ -22,11 +25,11 @@ export default Ember.ObjectController.extend(Ember.Validations.Mixin, {
pollTypes: function(){
return [
Em.Object.extend(Em.I18n.TranslateableProperties, {}).create({
Ember.Object.extend(Ember.I18n.TranslateableProperties, {}).create({
id : "FindADate",
labelTranslation : "pollTypes.findADate.label"
}),
Em.Object.extend(Em.I18n.TranslateableProperties, {}).create({
Ember.Object.extend(Ember.I18n.TranslateableProperties, {}).create({
id : "MakeAPoll",
labelTranslation : "pollTypes.makeAPoll.label"
})

View file

@ -1,3 +1,6 @@
import Ember from "ember";
import $ from "jquery";
export default Ember.ObjectController.extend(Ember.Validations.Mixin, {
actions: {
save: function() {

View file

@ -1,3 +1,6 @@
import Ember from "ember";
import $ from "jquery";
export default Ember.ObjectController.extend(Ember.Validations.Mixin, {
actions: {
/*
@ -50,8 +53,7 @@ export default Ember.ObjectController.extend(Ember.Validations.Mixin, {
datetimes.forEach(function(datetime){
datetime.contents.times.forEach(function(t){
var date = new Date(datetime.contents.title),
delimiter = '';
var date = new Date(datetime.contents.title);
// check if there is a value for time
if (Ember.isEmpty(t.value)) {
@ -104,7 +106,7 @@ export default Ember.ObjectController.extend(Ember.Validations.Mixin, {
/*
* only used on init, not on increasing number of input fields!
*/
datetimes: function(key, value, previousValue){
datetimes: function(){
var datetimes = Ember.A(),
dates = this.get('options'),
datetimesCount = this.get('datetimesInputFields'),

View file

@ -1,3 +1,6 @@
import Ember from "ember";
import $ from "jquery";
export default Ember.ObjectController.extend(Ember.Validations.Mixin, {
actions: {
save: function(){

View file

@ -1,3 +1,6 @@
import Ember from "ember";
import $ from "jquery";
export default Ember.ObjectController.extend(Ember.Validations.Mixin, {
actions: {
save: function(){
@ -35,44 +38,44 @@ export default Ember.ObjectController.extend(Ember.Validations.Mixin, {
answerTypes: function() {
return [
Em.Object.extend(Em.I18n.TranslateableProperties, {}).create({
Ember.Object.extend(Ember.I18n.TranslateableProperties, {}).create({
id : "YesNo",
labelTranslation : "answerTypes.yesNo.label",
answers : [
Em.Object.extend(Em.I18n.TranslateableProperties, {}).create({
Ember.Object.extend(Ember.I18n.TranslateableProperties, {}).create({
id: "yes",
labelTranslation: "answerTypes.yes.label",
icon: "glyphicon glyphicon-thumbs-up"
}),
Em.Object.extend(Em.I18n.TranslateableProperties, {}).create({
Ember.Object.extend(Ember.I18n.TranslateableProperties, {}).create({
id: "no",
labelTranslation: "answerTypes.no.label",
icon: "glyphicon glyphicon-thumbs-down"
})
]
}),
Em.Object.extend(Em.I18n.TranslateableProperties, {}).create({
Ember.Object.extend(Ember.I18n.TranslateableProperties, {}).create({
id : "YesNoMaybe",
labelTranslation : "answerTypes.yesNoMaybe.label",
answers : [
Em.Object.extend(Em.I18n.TranslateableProperties, {}).create({
Ember.Object.extend(Ember.I18n.TranslateableProperties, {}).create({
id: "yes",
labelTranslation: "answerTypes.yes.label",
icon: "glyphicon glyphicon-thumbs-up"
}),
Em.Object.extend(Em.I18n.TranslateableProperties, {}).create({
Ember.Object.extend(Ember.I18n.TranslateableProperties, {}).create({
id: "maybe",
labelTranslation: "answerTypes.maybe.label",
icon: "glyphicon glyphicon-hand-right"
}),
Em.Object.extend(Em.I18n.TranslateableProperties, {}).create({
Ember.Object.extend(Ember.I18n.TranslateableProperties, {}).create({
id: "no",
labelTranslation: "answerTypes.no.label",
icon: "glyphicon glyphicon-thumbs-down"
})
]
}),
Em.Object.extend(Em.I18n.TranslateableProperties, {}).create({
Ember.Object.extend(Ember.I18n.TranslateableProperties, {}).create({
id : "FreeText",
labelTranslation : "answerTypes.freeText.label",
answers : []

View file

@ -1,3 +1,5 @@
import Ember from "ember";
export default Ember.ObjectController.extend({
is404: function(){
return this.get('status') === 404;

View file

@ -1,3 +1,6 @@
import Ember from "ember";
import $ from "jquery";
export default Ember.ObjectController.extend(Ember.Validations.Mixin, {
encryptionKey: '',
newUserName: '',
@ -72,12 +75,10 @@ export default Ember.ObjectController.extend(Ember.Validations.Mixin, {
}
var datetimes = this.get('dates'),
dates = [],
datesCount = {},
dateGroups = [];
var lastDate = null,
count = 0;
var count = 0,
lastDate = null;
datetimes.forEach(function(el){
var date;
date = new Date( el.title );
@ -133,12 +134,11 @@ export default Ember.ObjectController.extend(Ember.Validations.Mixin, {
}
else {
var timezoneDifference = new Date().getTimezoneOffset() - this.get('timezoneOffset'),
dates = [],
self = this;
dates = [];
this.get('options').forEach(function(option){
dates.pushObject({
title: new Date( option.title ).setMinutes(
new Date( option.title ).getMinutes() - self.get('timezoneOffset')
timezoneDifference
)
});
});
@ -226,7 +226,7 @@ export default Ember.ObjectController.extend(Ember.Validations.Mixin, {
return false;
}
newUserSelections.forEach(function(item, index, enumerable){
newUserSelections.forEach(function(item){
if (Ember.isEmpty(item.value)) {
allAnswered = false;
}
@ -313,7 +313,7 @@ export default Ember.ObjectController.extend(Ember.Validations.Mixin, {
* ToDo: Show validation errors
*/
acceptance: {
if: function(object, validator){
if: function(object){
return object.get('forceAnswer');
},
message: Ember.I18n.t('poll.error.newUser.everyOptionIsAnswered')
@ -326,7 +326,7 @@ export default Ember.ObjectController.extend(Ember.Validations.Mixin, {
* validate if a user name is given
* if it's forced by poll settings (anonymousUser === false)
*/
unless: function(object, validator){
unless: function(object){
/* have in mind that anonymousUser is undefined on init */
return object.get('anonymousUser');
}

View file

@ -1,3 +1,5 @@
import Ember from "ember";
export default function() {
Ember.TextField.reopen({
attributeBindings: ['data-option']

View file

@ -1,3 +1,5 @@
import moment from "moment";
export default function(date, options) {
var times = options.hash.times ? options.hash.times : false,
format = options.hash.format ? options.hash.format : 'LLLL';

View file

@ -1,3 +1,5 @@
import Ember from "ember";
/*
* radio button helper by FellowMD
* https://gist.github.com/FellowMD/84f5b113de2db762cb1d

View file

@ -1,3 +1,5 @@
import Ember from "ember";
// Please note that Handlebars helpers will only be found automatically by the
// resolver if their name contains a dash (reverse-word, translate-text, etc.)
// For more details: http://stefanpenner.github.io/ember-app-kit/guides/using-modules.html

View file

@ -1,140 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Croodle</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- build:css(tmp/result) assets/app.min.css -->
<link rel="stylesheet" href="/assets/app.css">
<!-- endbuild -->
{{content-for 'head'}}
<!-- for more details visit: https://github.com/yeoman/grunt-usemin -->
<link rel="stylesheet" href="assets/vendor.css">
<link rel="stylesheet" href="assets/croodle.css">
</head>
<body>
{{content-for 'body'}}
<!-- build:js(tmp/result) assets/config.min.js -->
<script src="/config/environment.js"></script>
<!-- @if tests=false -->
<!-- @if dist=false -->
<script src="/config/environments/development.js"></script>
<!-- @endif -->
<!-- @if dist=true -->
<script src="/config/environments/production.js"></script>
<!-- @endif -->
<!-- @endif --><!-- @if tests=true -->
<script src="/config/environments/test.js"></script>
<!-- @endif -->
<!-- endbuild -->
<!-- build:js(tmp/result) assets/vendor.min.js -->
<!-- @if dist=false -->
<script src="/vendor/jquery/dist/jquery.js"></script>
<script src="/vendor/handlebars/handlebars.js"></script>
<script src="/vendor/ember/ember.js"></script>
<script src="/vendor/ember-data/ember-data.js"></script>
<script src="/vendor/floatThead/dist/jquery.floatThead.js"></script>
<script src="/vendor/moment/min/moment-with-locales.js"></script>
<script src="/vendor/webshim/js-webshim/dev/polyfiller.js"></script>
<script src="/vendor/bootstrap/dist/js/bootstrap.js"></script>
<!-- @endif -->
<!-- @if dist=true -->
<script src="/vendor/jquery/dist/jquery.min.js"></script>
<script src="/vendor/handlebars/handlebars.runtime.js"></script>
<script src="/vendor/ember/ember.prod.js"></script>
<script src="/vendor/ember-data/ember-data.prod.js"></script>
<script src="/vendor/floatThead/dist/jquery.floatThead.min.js"></script>
<script src="/vendor/moment/min/moment-with-locales.min.js"></script>
<script src="/vendor/webshim/js-webshim/minified/polyfiller.js"></script>
<script src="/vendor/bootstrap/dist/js/bootstrap.min.js"></script>
<!-- @endif -->
<script src="/vendor/loader.js/loader.js"></script>
<script src="/vendor/ember-resolver/dist/ember-resolver.js"></script>
<script src="/vendor/ember-shim.js"></script>
<script src="/vendor/ic-ajax/dist/named-amd/main.js"></script>
<script src="/vendor/ember-load-initializers/ember-load-initializers.js"></script>
<script src="/vendor/ember-validations/index.js"></script>
<script src="/vendor/ember-easyForm/index.js"></script>
<script src="/vendor/cldr/plurals.js"></script>
<script src="/vendor/ember-i18n/lib/i18n.js"></script>
<script src="/vendor/ember-i18n/lib/i18n-plurals.js"></script>
<script src="/vendor/sjcl/sjcl.js"></script>
<script src="/vendor/bootstrap-datepicker/js/bootstrap-datepicker.js"></script>
<script src="/vendor/modernizr/modernizr.js"></script>
<!-- endbuild -->
<!-- build:js(tmp/result) assets/app.min.js -->
<script src="/assets/app.js"></script>
<script src="/assets/templates.js"></script>
<!-- endbuild -->
<!-- @if dist=false -->
<style>
@keyframes domChanged { from { background: yellow; } }
@-webkit-keyframes domChanged { from { background: yellow; } }
.ember-view { animation: domChanged 1s; -webkit-animation: domChanged 1s; }
</style>
<!-- @endif -->
<!-- @if tests=true -->
<script src="/vendor/ember-shim.js"></script>
<link rel="stylesheet" href="/vendor/qunit/qunit/qunit.css">
<script src="/vendor/qunit/qunit/qunit.js"></script>
<script src="/vendor/qunit-shim.js"></script>
<script src="/vendor/ember-qunit/dist/named-amd/main.js"></script>
<style>
#ember-testing-container {
position: absolute;
background: white;
bottom: 0;
right: 0;
width: 640px;
height: 384px;
overflow: auto;
z-index: 9999;
border: 1px solid #ccc;
}
#ember-testing {
zoom: 50%;
}
</style>
<!-- @endif -->
</head>
<body>
<!--[if lt IE 8]>
<p class="browsehappy">
You are using an <strong>outdated</strong> browser. Please
<a href="http://browsehappy.com/">upgrade your browser</a>
to improve your experience.
</p>
<![endif]-->
<!-- @if tests=true -->
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script src="/tests/tests.js"></script>
<script src="/tests/test-helper.js"></script>
<script src="/tests/test-loader.js"></script>
<script src="/testem.js"></script>
<!-- @endif -->
<!-- @if tests=false -->
<script>
window.App = require('croodle/app')['default'].create(ENV.APP);
webshim.polyfill('forms forms-ext');
</script>
<!-- @endif -->
</body>
<script src="assets/vendor.js"></script>
<script src="assets/croodle.js"></script>
</body>
</html>

View file

@ -1,3 +1,5 @@
import Ember from "ember";
/*
* make ember-easyForm support Bootstrap 3
* https://github.com/dockyard/ember-easyForm/wiki/Bootstrap-3-and-Ember-Data-With-Server-Side-Validations

View file

@ -1,4 +1,6 @@
import Ember from "ember";
import translations from "croodle/lang/translations";
import moment from "moment";
export default {
name: 'i18n',

View file

@ -1,3 +1,5 @@
import Ember from "ember";
export default Ember.Object.extend({
key : '',
isSet: false

View file

@ -1,3 +1,6 @@
import DS from "ember-data";
import Ember from "ember";
export default DS.Model.extend({
// relationship
users : DS.hasMany('user'),

View file

@ -1,3 +1,6 @@
import DS from "ember-data";
import Ember from "ember";
export default DS.Model.extend({
// relationship
poll : DS.belongsTo('poll'),

View file

@ -1,4 +1,9 @@
var Router = Ember.Router.extend(); // ensure we don't share routes between all Router instances
import Ember from 'ember';
import config from './config/environment';
var Router = Ember.Router.extend({
location: config.locationType
});
Router.map(function(){
this.route('poll', { path: '/poll/:poll_id' });

View file

@ -1,3 +1,5 @@
import Ember from "ember";
export default Ember.Route.extend({
beforeModel: function(){
// generate encryptionKey

View file

@ -1,3 +1,5 @@
import Ember from "ember";
export default Ember.Route.extend({
model: function(){
return this.modelFor('create');

View file

@ -1,3 +1,5 @@
import Ember from "ember";
export default Ember.Route.extend({
model: function(){
return this.modelFor('create');

View file

@ -1,3 +1,5 @@
import Ember from "ember";
export default Ember.Route.extend({
model: function(){
return this.modelFor('create');

View file

@ -1,3 +1,5 @@
import Ember from "ember";
export default Ember.Route.extend({
model: function(){
return this.modelFor('create');

View file

@ -1,3 +1,5 @@
import Ember from "ember";
export default Ember.Route.extend({
model: function(){
return this.modelFor('create');

View file

@ -1,6 +1,8 @@
import Ember from "ember";
export default Ember.Route.extend({
actions: {
error: function(error, transition) {
error: function(error) {
if (error && error.status === 404) {
return this.transitionTo('404');
}

View file

@ -1 +1,3 @@
import DS from "ember-data";
export default DS.RESTSerializer.extend();

View file

@ -1,3 +1,5 @@
import DS from "ember-data";
export default DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
users: {embedded: 'always'}

3
app/styles/app.css Normal file
View file

@ -0,0 +1,3 @@
html, body {
margin: 20px;
}

View file

@ -1,4 +1,7 @@
export default Em.View.extend({
import Ember from "ember";
import webshim from "webshim";
export default Ember.View.extend({
didInsertElement: function(){
this._super();

View file

@ -1,3 +1,5 @@
import Ember from "ember";
export default Ember.View.extend({
title: '',

View file

@ -1,4 +1,7 @@
export default Em.View.extend({
import Ember from "ember";
import $ from "jquery";
export default Ember.View.extend({
classNames: ['datepicker'],
didInsertElement: function() {

View file

@ -1,3 +1,4 @@
import Ember from "ember";
import translations from "croodle/lang/translations";
export default Ember.View.extend({

View file

@ -1,4 +1,8 @@
export default Ember.View.extend(Em.I18n.TranslateableProperties, {
import Ember from "ember";
import moment from "moment";
import $ from "jquery";
export default Ember.View.extend(Ember.I18n.TranslateableProperties, {
showEvaluation: false,
actions: {

View file

@ -1,3 +1,5 @@
import Ember from "ember";
/*
* ember-radio by FellowMD
* https://github.com/FellowMD/ember-radio/blob/master/app/views/radio.js

View file

@ -2,26 +2,27 @@
"name": "croodle",
"dependencies": {
"handlebars": "~1.3.0",
"jquery": "~1.11",
"qunit": "~1.12.0",
"jquery": "^1.11.1",
"ember": "1.7.0",
"ember-data": "1.0.0-beta.10",
"ember-resolver": "~0.1.7",
"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": "0.1.8",
"ember": "~1.7.0",
"ember-data": "~1.0.0",
"ember-resolver": "~0.1",
"ic-ajax": "~1.0.4",
"ember-testing-httpRespond": "~0.1.1",
"loader.js": "git://github.com/stefanpenner/loader.js",
"ember-load-initializers": "git://github.com/stefanpenner/ember-load-initializers.git#0.0.1",
"moment": "~2.8.3",
"sjcl": "~1.0.0",
"ember-qunit-notifications": "0.0.4",
"qunit": "~1.15.0",
"ember-validations": "http://builds.dockyard.com.s3.amazonaws.com/ember-validations/tags/v1.0.0/ember-validations.js",
"ember-easyForm": "http://builds.dockyard.com/ember-easyForm/latest/ember-easyForm.js",
"cldr": "~1.0.2",
"ember-i18n": "~2.9.0",
"sjcl": "~1.0.0",
"bootstrap": "~3.2.0",
"bootstrap-datepicker": "~1.3.0",
"ember-easyForm": "http://builds.dockyard.com/ember-easyForm/latest/ember-easyForm.js",
"moment": "~2.8.3",
"floatThead": "~1.2.9",
"webshim": "~1.15.3",
"modernizr": "~2.8.3",
"ember-i18n": "~2.9.0",
"cldr": "~1.0.2"
"modernizr": "~2.8.3"
}
}

View file

@ -1,16 +1,46 @@
// Put general configuration here. This file is included
// in both production and development BEFORE Ember is
// loaded.
//
// For example to enable a feature on a canary build you
// might do:
//
// window.ENV = {FEATURES: {'with-controller': true}};
/* jshint node: true */
window.ENV = {
module.exports = function(environment) {
var ENV = {
modulePrefix: 'croodle',
environment: environment,
baseURL: '/',
locationType: 'auto',
EmberENV: {
FEATURES: {
'query-params-new': true
}
};
},
window.ENV.MODEL_FACTORY_INJECTIONS = true;
APP: {
// Here you can pass flags/options to your application instance
// when it is created
}
};
if (environment === 'development') {
// ENV.APP.LOG_RESOLVER = true;
ENV.APP.LOG_ACTIVE_GENERATION = true;
// ENV.APP.LOG_TRANSITIONS = true;
// ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
ENV.APP.LOG_VIEW_LOOKUPS = true;
}
if (environment === 'test') {
// Testem prefers this...
ENV.baseURL = '/';
ENV.locationType = 'auto';
// 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') {
}
return ENV;
};

View file

@ -1,14 +0,0 @@
// Put your development configuration here.
//
// This is useful when using a separate API
// endpoint in development than in production.
//
// window.ENV.public_key = '123456'
window.ENV.APP = {
LOG_ACTIVE_GENERATION: true,
LOG_MODULE_RESOLVER: true,
LOG_TRANSITIONS: true,
LOG_TRANSITIONS_INTERNAL: true,
LOG_VIEW_LOOKUPS: true
};

View file

@ -1,6 +0,0 @@
// Put your production configuration here.
//
// This is useful when using a separate API
// endpoint in development than in production.
//
// window.ENV.public_key = '123456'

View file

@ -1,6 +0,0 @@
// Put your test configuration here.
//
// This is useful when using a separate API
// endpoint in test than in production.
//
// window.ENV.public_key = '123456'

View file

@ -1,57 +1,37 @@
{
"name": "croodle",
"namespace": "croodle",
"APIMethod": "proxy",
"proxyURL": "http://localhost:80/croodle",
"proxyPath": "/api.php",
"docURL": "http://localhost:8000/docs/index.html",
"version": "0.2.0",
"private": true,
"directories": {
"doc": "doc",
"test": "test"
"test": "tests"
},
"scripts": {
"start": "grunt server",
"build": "grunt build:debug",
"test": "grunt test:ci",
"postinstall": "bower install"
"start": "ember server",
"build": "ember build",
"test": "ember test"
},
"repository": {
"type": "git",
"url": "git://github.com/stefanpenner/ember-app-kit.git"
"repository": "https://github.com/stefanpenner/ember-cli",
"engines": {
"node": ">= 0.10.0"
},
"author": "",
"license": "MIT",
"devDependencies": {
"express": "~3.4.8",
"lockfile": "~0.4.2",
"bower": "~1.3.2",
"grunt": "~0.4.2",
"grunt-cli": "~0.1.9",
"load-grunt-config": "~0.7.0",
"grunt-contrib-watch": "~0.5.3",
"grunt-contrib-copy": "~0.4.1",
"grunt-contrib-concat": "~0.3.0",
"grunt-contrib-clean": "~0.5.0",
"grunt-contrib-jshint": "~0.8.0",
"grunt-contrib-uglify": "~0.2.7",
"grunt-contrib-cssmin": "~0.6.2",
"grunt-preprocess": "~3.0.1",
"grunt-es6-module-transpiler": "~0.6.0",
"grunt-concat-sourcemap": "~0.4.0",
"grunt-concurrent": "~0.4.3",
"grunt-usemin": "~0.1.13",
"grunt-rev": "~0.1.0",
"grunt-ember-templates": "~0.4.18",
"grunt-contrib-testem": "~0.5.16",
"express-namespace": "~0.1.1",
"request": "~2.33.0",
"loom-generators-ember-appkit": "~1.0.5",
"originate": "~0.1.5",
"loom": "~3.1.2",
"connect-livereload": "~0.3.1",
"grunt-es6-import-validate": "0.0.6",
"grunt-contrib-less": "~0.11.4"
"body-parser": "^1.2.0",
"broccoli-asset-rev": "0.3.1",
"broccoli-ember-hbs-template-compiler": "^1.6.1",
"ember-cli": "0.1.2",
"ember-cli-content-security-policy": "0.3.0",
"ember-export-application-global": "^1.0.0",
"ember-cli-ic-ajax": "0.1.1",
"ember-cli-inject-live-reload": "^1.3.0",
"ember-cli-qunit": "0.1.0",
"ember-data": "1.0.0-beta.10",
"express": "^4.8.5",
"glob": "^4.0.5"
}
}

View file

@ -1,27 +0,0 @@
{
"node" : true,
"browser" : false,
"boss" : true,
"curly": false,
"debug": false,
"devel": false,
"eqeqeq": true,
"evil": true,
"forin": false,
"immed": false,
"laxbreak": false,
"newcap": true,
"noarg": true,
"noempty": false,
"nonew": false,
"nomen": false,
"onevar": false,
"plusplus": false,
"regexp": false,
"undef": true,
"sub": true,
"strict": false,
"white": false,
"eqnull": true,
"esnext": true
}

View file

@ -1,78 +0,0 @@
module.exports = {
// Note: These tasks are listed in the order in which they will run.
javascriptToTmp: {
files: [{
expand: true,
cwd: 'app',
src: '**/*.js',
dest: 'tmp/javascript/app'
},
{
expand: true,
cwd: 'tests',
src: ['**/*.js', '!test-helper.js', '!test-loader.js'],
dest: 'tmp/javascript/tests/'
}]
},
cssToResult: {
expand: true,
cwd: 'app/styles',
src: ['**/*.css'],
dest: 'tmp/result/assets'
},
// Assembles everything in `tmp/result`.
// The sole purpose of this task is to keep things neat. Gathering everything in one
// place (tmp/dist) enables the subtasks of dist to only look there. Note: However,
// for normal development this is done on the fly by the development server.
assemble: {
files: [{
expand: true,
cwd: 'tests',
src: ['test-helper.js', 'test-loader.js'],
dest: 'tmp/result/tests/'
}, {
expand: true,
cwd: 'public',
src: ['**'],
dest: 'tmp/result/'
}, {
src: ['vendor/**/*.js', 'vendor/**/*.css'],
dest: 'tmp/result/'
}, {
src: ['config/environment.js', 'config/environments/production.js'],
dest: 'tmp/result/'
}
]
},
imageminFallback: {
files: '<%= imagemin.dist.files %>'
},
dist: {
files: [{
expand: true,
cwd: 'tmp/result',
src: [
'**',
'!**/*.{css,js}', // Already handled by concat
'!**/*.{png,gif,jpg,jpeg}', // Already handled by imagemin
'!tests/**/*', // No tests, please
'!**/*.map' // No source maps
],
filter: 'isFile',
dest: 'dist/'
},
{
expand: true,
cwd: 'vendor/webshim/js-webshim/minified/shims',
src: ['**'],
dest: 'dist/assets/shims'
}]
},
};

View file

@ -1,129 +0,0 @@
module.exports = function(grunt) {
var express = require('express'),
lockFile = require('lockfile'),
Helpers = require('./helpers'),
fs = require('fs'),
path = require('path'),
request = require('request');
/**
Task for serving the static files.
Note: The expressServer:debug task looks for files in multiple directories.
*/
grunt.registerTask('expressServer', function(target, proxyMethodToUse) {
// Load namespace module before creating the server
require('express-namespace');
var app = express(),
done = this.async(),
proxyMethod = proxyMethodToUse || grunt.config('express-server.options.APIMethod');
app.use(lock);
app.use(express.compress());
if (proxyMethod === 'stub') {
grunt.log.writeln('Using API Stub');
// Load API stub routes
app.use(express.json());
app.use(express.urlencoded());
require('../api-stub/routes')(app);
} else if (proxyMethod === 'proxy') {
var proxyURL = grunt.config('express-server.options.proxyURL'),
proxyPath = grunt.config('express-server.options.proxyPath') || '/api';
grunt.log.writeln('Proxying API requests matching ' + proxyPath + '/* to: ' + proxyURL);
// Use API proxy
app.all(proxyPath + '*', passThrough(proxyURL));
}
if (target === 'debug') {
// For `expressServer:debug`
// Add livereload middleware after lock middleware if enabled
if (Helpers.isPackageAvailable("connect-livereload")) {
var liveReloadPort = grunt.config('watch.options.livereload');
app.use(require("connect-livereload")({port: liveReloadPort}));
}
// YUIDoc serves static HTML, so just serve the index.html
app.all('/docs', function(req, res) { res.redirect(302, '/docs/index.html'); });
app.use(static({ urlRoot: '/docs', directory: 'docs' }));
// These three lines simulate what the `copy:assemble` task does
app.use(static({ urlRoot: '/config', directory: 'config' }));
app.use(static({ urlRoot: '/vendor', directory: 'vendor' }));
app.use(static({ directory: 'public' }));
app.use(static({ urlRoot: '/tests', directory: 'tests' })); // For test-helper.js and test-loader.js
app.use(static({ directory: 'tmp/result' }));
app.use(static({ file: 'tmp/result/index.html', ignoredFileExtensions: /\.\w{1,5}$/ })); // Gotta catch 'em all
} else {
// For `expressServer:dist`
app.use(lock);
app.use(static({ directory: 'dist' }));
app.use(static({ file: 'dist/index.html', ignoredFileExtensions: /\.\w{1,5}$/ })); // Gotta catch 'em all
}
var port = parseInt(process.env.PORT || 8000, 10);
if (isNaN(port) || port < 1 || port > 65535) {
grunt.fail.fatal('The PORT environment variable of ' + process.env.PORT + ' is not valid.');
}
app.listen(port);
grunt.log.ok('Started development server on port %d.', port);
if (!this.flags.keepalive) { done(); }
});
// Middleware
// ==========
function lock(req, res, next) { // Works with tasks/locking.js
(function retry() {
if (lockFile.checkSync('tmp/connect.lock')) {
setTimeout(retry, 30);
} else { next(); }
})();
}
function static(options) {
return function(req, res, next) { // Gotta catch 'em all (and serve index.html)
var filePath = "";
if (options.directory) {
var regex = new RegExp('^' + (options.urlRoot || ''));
// URL must begin with urlRoot's value
if (!req.path.match(regex)) { next(); return; }
filePath = options.directory + req.path.replace(regex, '');
} else if (options.file) {
filePath = options.file;
} else { throw new Error('static() isn\'t properly configured!'); }
fs.stat(filePath, function(err, stats) {
if (err) { next(); return; } // Not a file, not a folder => can't handle it
if (options.ignoredFileExtensions) {
if (options.ignoredFileExtensions.test(req.path)) {
res.send(404, {error: 'Resource not found'});
return; // Do not serve index.html
}
}
// Is it a directory? If so, search for an index.html in it.
if (stats.isDirectory()) { filePath = path.join(filePath, 'index.html'); }
// Serve the file
res.sendfile(filePath, function(err) {
if (err) { next(); return; }
grunt.verbose.ok('Served: ' + filePath);
});
});
};
}
function passThrough(target) {
return function(req, res) {
req.pipe(request(target+req.url)).pipe(res);
};
}
};

View file

@ -1,60 +0,0 @@
var grunt = require('grunt'),
_ = grunt.util._,
Helpers = {};
// List of package requisits for tasks
// Notated in conjunctive normal form (CNF)
// e.g. ['a', ['b', 'alternative-to-b']]
var taskRequirements = {
coffee: ['grunt-contrib-coffee'],
compass: ['grunt-contrib-compass'],
sass: [['grunt-sass', 'grunt-contrib-sass']],
less: ['grunt-contrib-less'],
stylus: ['grunt-contrib-stylus'],
emberTemplates: ['grunt-ember-templates'],
emblem: ['grunt-emblem'],
emberscript: ['grunt-ember-script'],
imagemin: ['grunt-contrib-imagemin'],
htmlmin: ['grunt-contrib-htmlmin'],
fancySprites: ['grunt-fancy-sprites'],
autoprefixer: ['grunt-autoprefixer'],
rev: ['grunt-rev'],
'validate-imports': ['grunt-es6-import-validate'],
yuidoc: ['grunt-contrib-yuidoc']
};
// Task fallbacks
// e.g. 'a': ['fallback-a-step-1', 'fallback-a-step-2']
var taskFallbacks = {
'imagemin': 'copy:imageminFallback'
};
Helpers.filterAvailableTasks = function(tasks){
tasks = tasks.map(function(taskName) {
// Maps to task name or fallback if task is unavailable
var baseName = taskName.split(':')[0]; // e.g. 'coffee' for 'coffee:compile'
var reqs = taskRequirements[baseName];
var isAvailable = Helpers.isPackageAvailable(reqs);
return isAvailable ? taskName : taskFallbacks[taskName];
});
return _.flatten(_.compact(tasks)); // Remove undefined's and flatten it
};
Helpers.isPackageAvailable = function(pkgNames) {
if (!pkgNames) return true; // packages are assumed to exist
if (!_.isArray(pkgNames)) { pkgNames = [pkgNames]; }
return _.every(pkgNames, function(pkgNames) {
if (!_.isArray(pkgNames)) { pkgNames = [pkgNames]; }
return _.any(pkgNames, function(pkgName) {
return !!Helpers.pkg.devDependencies[pkgName];
});
});
};
module.exports = Helpers;

View file

@ -1,14 +0,0 @@
var lockFile = require('lockfile');
module.exports = function(grunt) {
grunt.registerTask('lock', 'Set semaphore for connect server to wait on.', function() {
grunt.file.mkdir('tmp');
lockFile.lockSync('tmp/connect.lock');
grunt.log.writeln("Locked - Development server won't answer incoming requests until App Kit is done updating.");
});
grunt.registerTask('unlock', 'Release semaphore that connect server waits on.', function() {
lockFile.unlockSync('tmp/connect.lock');
grunt.log.writeln("Unlocked - Development server now handles requests.");
});
};

View file

@ -1,5 +0,0 @@
module.exports = {
app: {
src: 'tmp/result/assets/**/*.css'
}
};

View file

@ -1,4 +0,0 @@
module.exports = {
'debug': ['tmp'],
'dist': ['tmp', 'dist']
};

View file

@ -1,42 +0,0 @@
// CoffeeScript compilation. This must be enabled by modification
// of Gruntfile.js.
//
// The `bare` option is used since this file will be transpiled
// anyway. In CoffeeScript files, you need to escape out for
// some ES6 features like import and export. For example:
//
// `import User from 'appkit/models/user'`
//
// Post = Em.Object.extend
// init: (userId) ->
// @set 'user', User.findById(userId)
//
// `export default Post`
//
module.exports = {
"test": {
options: {
bare: true
},
files: [{
expand: true,
cwd: 'tests/',
src: '**/*.coffee',
dest: 'tmp/javascript/tests',
ext: '.js'
}]
},
"app": {
options: {
bare: true
},
files: [{
expand: true,
cwd: 'app/',
src: '**/*.coffee',
dest: 'tmp/javascript/app',
ext: '.js'
}]
}
};

View file

@ -1,17 +0,0 @@
module.exports = {
options: {
sassDir: "app/styles",
cssDir: "tmp/result/assets",
generatedImagesDir: "tmp/result/assets/images/generated",
imagesDir: "public/assets/images",
javascriptsDir: "app",
fontsDir: "public/assets/fonts",
importPath: ["vendor"],
httpImagesPath: "/assets/images",
httpGeneratedImagesPath: "/assets/images/generated",
httpFontsPath: "/assets/fonts",
relativeAssets: false,
debugInfo: true
},
compile: {}
};

View file

@ -1,25 +0,0 @@
module.exports = {
app: {
src: ['tmp/transpiled/app/**/*.js'],
dest: 'tmp/result/assets/app.js',
options: {
sourcesContent: true
},
},
config: {
src: ['tmp/result/config/**/*.js'],
dest: 'tmp/result/assets/config.js',
options: {
sourcesContent: true
},
},
test: {
src: 'tmp/transpiled/tests/**/*.js',
dest: 'tmp/result/tests/tests.js',
options: {
sourcesContent: true
}
}
};

View file

@ -1,6 +0,0 @@
module.exports = {
// Remaining configuration done in Gruntfile.js
options: {
logConcurrentOutput: true
}
};

View file

@ -1,72 +0,0 @@
module.exports = {
// Note: These tasks are listed in the order in which they will run.
javascriptToTmp: {
files: [{
expand: true,
cwd: 'app',
src: '**/*.js',
dest: 'tmp/javascript/app'
},
{
expand: true,
cwd: 'tests',
src: ['**/*.js', '!test-helper.js', '!test-loader.js'],
dest: 'tmp/javascript/tests/'
}]
},
cssToResult: {
expand: true,
cwd: 'app/styles',
src: ['**/*.css'],
dest: 'tmp/result/assets'
},
// Assembles everything in `tmp/result`.
// The sole purpose of this task is to keep things neat. Gathering everything in one
// place (tmp/dist) enables the subtasks of dist to only look there. Note: However,
// for normal development this is done on the fly by the development server.
assemble: {
files: [{
expand: true,
cwd: 'tests',
src: ['test-helper.js', 'test-loader.js'],
dest: 'tmp/result/tests/'
}, {
expand: true,
cwd: 'public',
src: ['**'],
dest: 'tmp/result/'
}, {
src: ['vendor/**/*.js', 'vendor/**/*.css'],
dest: 'tmp/result/'
}, {
src: ['config/environment.js', 'config/environments/production.js'],
dest: 'tmp/result/'
}
]
},
imageminFallback: {
files: '<%= imagemin.dist.files %>'
},
dist: {
files: [{
expand: true,
cwd: 'tmp/result',
src: [
'**',
'!**/*.{css,js}', // Already handled by concat
'!**/*.{png,gif,jpg,jpeg}', // Already handled by imagemin
'!tests/**/*', // No tests, please
'!**/*.map' // No source maps
],
filter: 'isFile',
dest: 'dist/'
}]
},
};

View file

@ -1,22 +0,0 @@
var grunt = require('grunt');
module.exports = {
options: {
templateBasePath: /app\//,
templateFileExtensions: /\.(hbs|hjs|handlebars)/,
templateRegistration: function(name, template) {
return grunt.config.process("define('<%= package.namespace %>/") + name + "', ['exports'], function(__exports__){ __exports__['default'] = " + template + "; });";
}
},
debug: {
options: {
precompile: false
},
src: "app/**/*.{hbs,hjs,handlebars}",
dest: "tmp/result/assets/templates.js"
},
dist: {
src: "<%= emberTemplates.debug.src %>",
dest: "<%= emberTemplates.debug.dest %>"
}
};

View file

@ -1,42 +0,0 @@
// EmberScript compilation. This must be enabled by modification
// of Gruntfile.js.
//
// The `bare` option is used since this file will be transpiled
// anyway. In EmberScript files, you need to escape out for
// some ES6 features like import and export. For example:
//
// `import User from 'appkit/models/user'`
//
// class Post
// init: (userId) ->
// @user = User.findById(userId)
//
// `export default Post`
//
module.exports = {
"test": {
options: {
bare: true
},
files: [{
expand: true,
cwd: 'tests/',
src: '**/*.em',
dest: 'tmp/javascript/tests',
ext: '.js'
}]
},
"app": {
options: {
bare: true
},
files: [{
expand: true,
cwd: 'app/',
src: '**/*.em',
dest: 'tmp/javascript/app',
ext: '.js'
}]
}
};

View file

@ -1,16 +0,0 @@
module.exports = {
compile: {
files: {
"tmp/result/assets/templates.js": ['app/templates/**/*.{emblem,hbs,hjs,handlebars}']
},
options: {
root: 'app/templates/',
dependencies: {
jquery: 'vendor/jquery/jquery.js',
ember: 'vendor/ember/ember.js',
handlebars: 'vendor/handlebars/handlebars.js',
emblem: 'vendor/emblem.js/emblem.js'
}
}
}
};

View file

@ -1,9 +0,0 @@
var grunt = require('grunt');
module.exports = {
options: {
APIMethod: "<%= package.APIMethod %>", // stub or proxy
proxyURL: "<%= package.proxyURL %>", // URL to the API server, if using APIMethod: 'proxy'
proxyPath: "<%= package.proxyPath %>" // path for the API endpoints, default is '/api', if using APIMethod: 'proxy'
}
};

View file

@ -1,22 +0,0 @@
var path = require('path');
module.exports = {
create: {
destStyles: 'tmp/sprites',
destSpriteSheets: 'tmp/result/assets/sprites',
files: [{
src: ['app/sprites/**/*.{png,jpg,jpeg}', '!app/sprites/**/*@2x.{png,jpg,jpeg}'],
spriteSheetName: '1x',
spriteName: function(name) {
return path.basename(name, path.extname(name));
}
}, {
src: 'app/sprites/**/*@2x.{png,jpg,jpeg}',
spriteSheetName: '2x',
spriteName: function(name) {
return path.basename(name, path.extname(name)).replace(/@2x/, '');
}
}
]
}
};

View file

@ -1,12 +0,0 @@
module.exports = {
dist: {
options: {
removeComments: true,
collapseWhitespace: true
},
files: [{
src: 'dist/index.html',
dest: 'dist/index.html'
}]
}
};

View file

@ -1,13 +0,0 @@
module.exports = {
dist: {
options: {
cache: false
},
files: [{
expand: true,
cwd: 'tmp/result',
src: '**/*.{png,gif,jpg,jpeg}',
dest: 'dist/'
}]
}
};

View file

@ -1,27 +0,0 @@
module.exports = {
app: {
src: [
'app/**/*.js'
],
options: { jshintrc: '.jshintrc' }
},
tooling: {
src: [
'Gruntfile.js',
'tasks/**/*.js'
],
options: { jshintrc: 'tasks/.jshintrc' }
},
tests: {
src: [
'tests/**/*.js',
],
options: { jshintrc: 'tests/.jshintrc' }
},
options: {
force: true
}
};

View file

@ -1,11 +0,0 @@
module.exports = {
compile: {
files: [{
expand: true,
cwd: 'app/styles',
src: ['**/*.less', '!**/_*.less'],
dest: 'tmp/result/assets/',
ext: '.css'
}]
}
};

View file

@ -1,18 +0,0 @@
module.exports = {
indexHTMLDebugApp: {
src : 'app/index.html', dest : 'tmp/result/index.html',
options: { context: { dist: false, tests: false } }
},
indexHTMLDebugTests: {
src : 'app/index.html', dest : 'tmp/result/tests/index.html',
options: { context: { dist: false, tests: true } }
},
indexHTMLDistApp: {
src : 'app/index.html', dest : 'tmp/result/index.html',
options: { context: { dist: true, tests: false } }
},
indexHTMLDistTests: {
src : 'app/index.html', dest : 'tmp/result/tests/index.html',
options: { context: { dist: true, tests: true } }
}
};

View file

@ -1,12 +0,0 @@
module.exports = {
dist: {
files: {
src: [
'dist/assets/config.min.js',
'dist/assets/app.min.js',
'dist/assets/vendor.min.js',
'dist/assets/app.min.css'
]
}
}
};

View file

@ -1,11 +0,0 @@
module.exports = {
compile: {
files: [{
expand: true,
cwd: 'app/styles',
src: ['**/*.{scss,sass}', '!**/_*.{scss,sass}'],
dest: 'tmp/result/assets/',
ext: '.css'
}]
}
};

View file

@ -1,11 +0,0 @@
module.exports = {
compile: {
files: [{
expand: true,
cwd: 'app/styles',
src: ['**/*.styl', '!**/_*.styl'],
dest: 'tmp/result/assets/',
ext: '.css'
}]
}
};

View file

@ -1,55 +0,0 @@
// See https://npmjs.org/package/grunt-contrib-testem for more config options
module.exports = {
basic: {
options: {
parallel: 2,
framework: 'qunit',
port: (parseInt(process.env.PORT || 7358, 10) + 1),
test_page: 'tmp/result/tests/index.html',
routes: {
'/tests/tests.js': 'tmp/result/tests/tests.js',
'/assets/app.js': 'tmp/result/assets/app.js',
'/assets/templates.js': 'tmp/result/assets/templates.js',
'/assets/app.css': 'tmp/result/assets/app.css'
},
src_files: [
'tmp/result/**/*.js'
],
launch_in_dev: ['PhantomJS', 'Chrome'],
launch_in_ci: ['PhantomJS', 'Chrome'],
}
},
browsers: {
options: {
parallel: 8,
framework: 'qunit',
port: (parseInt(process.env.PORT || 7358, 10) + 1),
test_page: 'tmp/result/tests/index.html',
routes: {
'/tests/tests.js': 'tmp/result/tests/tests.js',
'/assets/app.js': 'tmp/result/assets/app.js',
'/assets/templates.js': 'tmp/result/assets/templates.js',
'/assets/app.css': 'tmp/result/assets/app.css'
},
src_files: [
'tmp/result/**/*.js'
],
launch_in_dev: ['PhantomJS',
'Chrome',
'ChromeCanary',
'Firefox',
'Safari',
'IE7',
'IE8',
'IE9'],
launch_in_ci: ['PhantomJS',
'Chrome',
'ChromeCanary',
'Firefox',
'Safari',
'IE7',
'IE8',
'IE9'],
}
}
};

View file

@ -1,28 +0,0 @@
var grunt = require('grunt');
module.exports = {
"tests": {
type: 'amd',
moduleName: function(path) {
return grunt.config.process('<%= package.namespace %>/tests/') + path;
},
files: [{
expand: true,
cwd: 'tmp/javascript/tests/',
src: '**/*.js',
dest: 'tmp/transpiled/tests/'
}]
},
"app": {
type: 'amd',
moduleName: function(path) {
return grunt.config.process('<%= package.namespace %>/') + path;
},
files: [{
expand: true,
cwd: 'tmp/javascript/app/',
src: '**/*.js',
dest: 'tmp/transpiled/app/'
}]
}
};

View file

@ -1,3 +0,0 @@
module.exports = {
html: ['dist/index.html'],
};

View file

@ -1,6 +0,0 @@
module.exports = {
html: 'tmp/result/index.html',
options: {
dest: 'dist/'
}
};

View file

@ -1,47 +0,0 @@
var grunt = require('grunt');
module.exports = {
options: {
whitelist: {
'ember/resolver': ['default'],
'ember/load-initializers': ['default'],
'ember-qunit': ['moduleForComponent', 'moduleForModel', 'moduleFor', 'test', 'default'],
'ic-ajax': ['default', 'request', 'raw', 'defineFixture', 'lookupFixture'],
}
},
app: {
options: {
moduleName: function (name) {
return grunt.config.process('<%= package.namespace %>/') + name;
}
},
files: [{
expand: true,
cwd: 'app',
src: ['**/*.js']
}]
},
tests: {
options: {
moduleName: function (name) {
// Trim of the leading app/ from app modules
if (name.slice(0, 4) === 'app/') {
name = name.slice(4);
}
return grunt.config.process('<%= package.namespace %>/') + name;
}
},
// Test files reference app files so we have to make sure we pull in both sets
files: [{
expand: true,
cwd: '.',
src: ['tests/**/*.js']
}, {
expand: true,
cwd: '.',
src: ['app/**/*.js']
}]
}
};

View file

@ -1,53 +0,0 @@
var Helpers = require('../helpers'),
filterAvailable = Helpers.filterAvailableTasks,
LIVERELOAD_PORT = 35729,
liveReloadPort = (parseInt(process.env.PORT || 8000, 10) - 8000) + LIVERELOAD_PORT;
var docs = '{app}/**/*.{js,coffee,em}',
scripts = '{app,tests,config}/**/*.{js,coffee,em}',
templates = 'app/templates/**/*.{hbs,handlebars,hjs,emblem}',
sprites = 'app/sprites/**/*.{png,jpg,jpeg}',
styles = 'app/styles/**/*.{css,sass,scss,less,styl}',
indexHTML = 'app/index.html',
other = '{app,tests,public}/**/*',
bowerFile = 'bower.json',
npmFile = 'package.json';
module.exports = {
scripts: {
files: [scripts],
tasks: ['lock', 'buildScripts', 'unlock']
},
templates: {
files: [templates],
tasks: ['lock', 'buildTemplates:debug', 'unlock']
},
sprites: {
files: [sprites],
tasks: filterAvailable(['lock', 'fancySprites:create', 'unlock'])
},
styles: {
files: [styles],
tasks: ['lock', 'buildStyles', 'unlock']
},
indexHTML: {
files: [indexHTML],
tasks: ['lock', 'buildIndexHTML:debug', 'unlock']
},
docs: {
files: [docs],
tasks: ['lock', 'buildDocs', 'unlock']
},
other: {
files: [other, '!'+scripts, '!'+templates, '!'+styles, '!'+indexHTML, bowerFile, npmFile],
tasks: ['lock', 'build:debug', 'unlock']
},
options: {
// No need to debounce
debounceDelay: 0,
// When we don't have inotify
interval: 100,
livereload: liveReloadPort
}
};

View file

@ -1,16 +0,0 @@
var grunt = require('grunt');
module.exports = {
debug: {
name: '<%= package.name %>',
description: '<%= package.description %>',
version: '<%= package.version %>',
url: '<%= package.docURL %>/',
logo: 'http://emberjs.com/images/ember_logo.png',
options: {
paths: ['app/'],
outdir: './docs',
themedir: './node_modules/yuidoc-theme-blue'
}
}
};

View file

@ -1,14 +1,11 @@
{
"framework": "qunit",
"test_page": "tmp/result/tests/index.html",
"routes": {
"/tests/tests.js": "tmp/result/tests/tests.js",
"/assets/app.js": "tmp/result/assets/app.js",
"/assets/templates.js": "tmp/result/assets/templates.js",
"/assets/app.css": "tmp/result/assets/app.css"
},
"src_files": [
"tmp/result/**/*.js"
"test_page": "tests/index.html",
"launch_in_ci": [
"PhantomJS"
],
"launch_in_dev": ["PhantomJS", "Chrome"]
"launch_in_dev": [
"PhantomJS",
"Chrome"
]
}

View file

@ -4,14 +4,11 @@
"window",
"location",
"setTimeout",
"Ember",
"Em",
"$",
"-Promise",
"QUnit",
"define",
"console",
"require",
"requirejs",
"equal",
"notEqual",
"notStrictEqual",
@ -27,6 +24,9 @@
"ok",
"strictEqual",
"module",
"moduleFor",
"moduleForComponent",
"moduleForModel",
"process",
"expect",
"visit",
@ -34,16 +34,21 @@
"fillIn",
"click",
"keyEvent",
"triggerEvent",
"find",
"findWithAssert",
"wait",
"DS",
"keyEvent",
"isolatedContainer",
"startApp"
"startApp",
"andThen",
"currentURL",
"currentPath",
"currentRouteName"
],
"node" : false,
"browser" : false,
"boss" : true,
"node": false,
"browser": false,
"boss": true,
"curly": false,
"debug": false,
"devel": false,

View file

@ -1,9 +1,11 @@
import Resolver from 'ember/resolver';
import config from '../../config/environment';
var resolver = Resolver.create();
resolver.namespace = {
modulePrefix: 'croodle'
modulePrefix: config.modulePrefix,
podModulePrefix: config.podModulePrefix
};
export default resolver;

View file

@ -1,21 +1,19 @@
import Application from 'croodle/app';
import Router from 'croodle/router';
import Ember from 'ember';
import Application from '../../app';
import Router from '../../router';
import config from '../../config/environment';
function startApp(attrs) {
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();
@ -25,5 +23,3 @@ function startApp(attrs) {
return App;
}
export default startApp;

45
tests/index.html Normal file
View file

@ -0,0 +1,45 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Croodle Tests</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
{{content-for 'head'}}
{{content-for 'test-head'}}
<link rel="stylesheet" href="assets/vendor.css">
<link rel="stylesheet" href="assets/croodle.css">
<link rel="stylesheet" href="assets/test-support.css">
<style>
#ember-testing-container {
position: absolute;
background: white;
bottom: 0;
right: 0;
width: 640px;
height: 384px;
overflow: auto;
z-index: 9999;
border: 1px solid #ccc;
}
#ember-testing {
zoom: 50%;
}
</style>
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
{{content-for 'body'}}
{{content-for 'test-body'}}
<script src="assets/vendor.js"></script>
<script src="assets/test-support.js"></script>
<script src="assets/croodle.js"></script>
<script src="testem.js"></script>
<script src="assets/test-loader.js"></script>
</body>
</html>

View file

@ -1,30 +1,12 @@
import resolver from './helpers/resolver';
import {
setResolver
} from 'ember-qunit';
setResolver(resolver);
document.write('<div id="ember-testing-container"><div id="ember-testing"></div></div>');
var resolver = require('croodle/tests/helpers/resolver')['default'];
require('ember-qunit').setResolver(resolver);
window.startApp = require('croodle/tests/helpers/start-app')['default'];
window.isolatedContainer = require('ember-qunit/isolated-container')['default'];
function exists(selector, context) {
return !!find(selector, context).length;
}
function getAssertionMessage(actual, expected, message) {
return message || QUnit.jsDump.parse(expected) + " expected but was " + QUnit.jsDump.parse(actual);
}
function equal(actual, expected, message) {
message = getAssertionMessage(actual, expected, message);
QUnit.equal.call(this, actual, expected, message);
}
function strictEqual(actual, expected, message) {
message = getAssertionMessage(actual, expected, message);
QUnit.strictEqual.call(this, actual, expected, message);
}
window.exists = exists;
window.equal = equal;
window.strictEqual = strictEqual;
QUnit.config.urlConfig.push({ id: 'nocontainer', label: 'Hide container'});
var containerVisibility = QUnit.urlParams.nocontainer ? 'hidden' : 'visible';
document.getElementById('ember-testing-container').style.visibility = containerVisibility;

View file

@ -1,6 +0,0 @@
// TODO: load based on params
Ember.keys(requirejs.entries).forEach(function(entry) {
if ((/\-test/).test(entry)) {
require(entry, null, null, true);
}
});

View file

@ -1,3 +0,0 @@
define('ember', [ ], function(){
return Ember;
});

View file

@ -1,3 +0,0 @@
define('qunit', [ ], function(){
return QUnit;
});