diff --git a/addon/validations/factory.js b/addon/validations/factory.js
index f5f5b464..7f9f21c8 100644
--- a/addon/validations/factory.js
+++ b/addon/validations/factory.js
@@ -384,6 +384,7 @@ function createCPValidationFor(attribute, validations, owner) {
*/
function createTopLevelPropsMixin(validatableAttrs) {
return Ember.Mixin.create({
+ isWarning: and(...validatableAttrs.map(attr => `attrs.${attr}.isWarning`)).readOnly(),
isValid: and(...validatableAttrs.map(attr => `attrs.${attr}.isValid`)).readOnly(),
isValidating: or(...validatableAttrs.map(attr => `attrs.${attr}.isValidating`)).readOnly(),
isDirty: or(...validatableAttrs.map(attr => `attrs.${attr}.isDirty`)).readOnly(),
diff --git a/addon/validations/result-collection.js b/addon/validations/result-collection.js
index 732699cb..4c090128 100644
--- a/addon/validations/result-collection.js
+++ b/addon/validations/result-collection.js
@@ -54,6 +54,22 @@ export default Ember.Object.extend({
set(this, 'content', emberArray(get(this, 'content')));
},
+ /**
+ * ```javascript
+ * // Examples
+ * get(user, 'validations.isWarning')
+ * get(user, 'validations.attrs.username.isWarning')
+ * ```
+ *
+ * @property isWarning
+ * @default false
+ * @readOnly
+ * @type {Boolean}
+ */
+ isWarning: computed('content.@each.isWarning', cycleBreaker(function () {
+ return get(this, 'content').isEvery('isWarning', true);
+ }, false)).readOnly(),
+
/**
* ```javascript
* // Examples
diff --git a/bower.json b/bower.json
index 65a70986..120c4ad0 100644
--- a/bower.json
+++ b/bower.json
@@ -5,7 +5,8 @@
"ember-cli-shims": "0.1.1",
"ember-cli-test-loader": "0.2.2",
"moment": ">= 2.8.0",
- "moment-timezone": ">= 0.1.0"
+ "moment-timezone": ">= 0.1.0",
+ "font-awesome": "~4.5.0"
},
"devDependencies": {
"blanket": "5e94fc30f2e694bb5c3718ddcbf60d467f4b4d26",
diff --git a/ember-cli-build.js b/ember-cli-build.js
index 4ac39137..185ff557 100644
--- a/ember-cli-build.js
+++ b/ember-cli-build.js
@@ -4,7 +4,8 @@ var EmberAddon = require('ember-cli/lib/broccoli/ember-addon');
module.exports = function(defaults) {
var app = new EmberAddon(defaults, {
- // Add options here
+ snippetSearchPaths: ['addon','tests/dummy/app'],
+ snippetPaths: ['snippets','tests/dummy/snippets']
});
/*
diff --git a/package.json b/package.json
index 8708cabd..ceb811ba 100644
--- a/package.json
+++ b/package.json
@@ -41,17 +41,20 @@
"ember-cli-app-version": "^1.0.0",
"ember-cli-blanket": "0.9.5",
"ember-cli-dependency-checker": "^1.2.0",
+ "ember-cli-font-awesome": "1.5.2",
"ember-cli-github-pages": "^0.1.0",
"ember-cli-htmlbars": "^1.0.3",
"ember-cli-htmlbars-inline-precompile": "^0.3.1",
"ember-cli-inject-live-reload": "^1.4.0",
"ember-cli-jshint": "^1.0.0",
+ "ember-cli-less": "1.5.3",
"ember-cli-moment-shim": "2.0.0",
"ember-cli-qunit": "^2.0.2",
"ember-cli-release": "^1.0.0-beta.1",
"ember-cli-sri": "^2.1.0",
"ember-cli-uglify": "^1.2.0",
"ember-cli-yuidoc": "0.8.4",
+ "ember-code-snippet": "1.3.0",
"ember-data": "^2.6.0",
"ember-disable-prototype-extensions": "^1.1.0",
"ember-disable-proxy-controllers": "^1.0.1",
@@ -59,7 +62,7 @@
"ember-load-initializers": "^0.5.1",
"ember-moment": "6.1.0",
"ember-resolver": "^2.0.3",
- "ember-try": "0.2.4",
+ "ember-truth-helpers": "1.2.0",
"loader.js": "^4.0.1",
"moment": "2.13.0",
"moment-timezone": "0.5.4",
diff --git a/tests/acceptance/dummy-index-test.js b/tests/acceptance/dummy-index-test.js
index 021f887c..aa40a234 100644
--- a/tests/acceptance/dummy-index-test.js
+++ b/tests/acceptance/dummy-index-test.js
@@ -29,8 +29,8 @@ test("Page Loads", function(assert) {
assert.expect(2);
visit('/');
andThen(function() {
- assert.equal(find('.demo .info h1').text(), "CP Validations");
- assert.equal(find('.demo .form .register h2').text(), "Create an Account");
+ assert.equal(find('a.navbar-brand').text().trim(), "CP Validations");
+ assert.equal(find('.form .register h2').text(), "Create an Account");
});
});
@@ -43,11 +43,22 @@ test("Helper tooltips", function(assert) {
});
});
+test("Invalid form submit", function(assert) {
+ visit('/');
+ andThen(function() {
+ click('#signup');
+ });
+
+ andThen(function() {
+ assert.equal(find('.form .alert').text().trim(), 'Please fix all the errors below before continuing.');
+ });
+});
+
test("Valid form submit", function(assert) {
visit('/');
andThen(function() {
Object.keys(validInputValues).forEach((input) => {
- let $input = find(`.demo .validated-input input[name="${input}"]`);
+ let $input = find(`.validated-input input[name="${input}"]`);
assert.ok($input, `${input} found`);
fillIn($input, validInputValues[input]);
assert.ok($input.parent('.validated-input.has-success'), `${input} success`);
@@ -66,7 +77,7 @@ test("Invalid to valid email", function(assert) {
visit('/');
var $input;
andThen(function() {
- $input = find('.demo .validated-input input[name="email"]');
+ $input = find('.validated-input input[name="email"]');
assert.ok($input);
fillIn($input, 'invalid-email');
});
@@ -79,4 +90,3 @@ test("Invalid to valid email", function(assert) {
assert.ok($input.parent('.validated-input.has-success'));
});
});
-
diff --git a/tests/dummy/app/components/validated-input.js b/tests/dummy/app/components/validated-input.js
index 7f9b0e96..c66059bb 100644
--- a/tests/dummy/app/components/validated-input.js
+++ b/tests/dummy/app/components/validated-input.js
@@ -3,6 +3,7 @@
* Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
+// BEGIN-SNIPPET validated-input
import Ember from 'ember';
const {
@@ -43,3 +44,4 @@ export default Ember.Component.extend({
return (this.get('validation.isDirty') || this.get('didValidate')) && this.get('isValid') && !isEmpty(this.get('validation.warnings'));
})
});
+// END-SNIPPET
diff --git a/tests/dummy/app/controllers/index.js b/tests/dummy/app/controllers/index.js
index aa36f6f5..0004479f 100644
--- a/tests/dummy/app/controllers/index.js
+++ b/tests/dummy/app/controllers/index.js
@@ -13,31 +13,41 @@ export default Ember.Controller.extend({
actions: {
showCode() {
- this.toggleProperty('showCode');
- },
+ this.toggleProperty('showCode');
+ },
- submit() {
- var model = this.get('model');
- model.validate().then(({
- model, validations
- }) => {
- if (validations.get('isValid')) {
- this.setProperties({
- showAlert: false,
- isRegistered: true,
- showCode: false
- });
- } else {
- this.set('showAlert', true);
- }
- this.set('didValidate', true);
- }, (errors) => {
+ submit() {
+ var model = this.get('model');
+ model.validate().then(({
+ model,
+ validations
+ }) => {
+ if (validations.get('isValid')) {
+ this.setProperties({
+ showAlert: false,
+ isRegistered: true,
+ showCode: false
+ });
+ } else {
+ this.set('showAlert', true);
+ }
+ this.set('didValidate', true);
+ }, (errors) => {
- });
- },
+ });
+ },
- dismissAlert() {
- this.set('showAlert', false);
- }
+ dismissAlert() {
+ this.set('showAlert', false);
+ },
+
+ reset() {
+ this.setProperties({
+ showAlert: false,
+ isRegistered: false,
+ showCode: false,
+ didValidate: false
+ });
+ }
}
});
diff --git a/tests/dummy/app/index.html b/tests/dummy/app/index.html
index cc86fad1..e14ae6ba 100644
--- a/tests/dummy/app/index.html
+++ b/tests/dummy/app/index.html
@@ -3,16 +3,14 @@
- Ember CP Validations Demo
+ Ember CP Validations
{{content-for 'head'}}
-
-
-
+
@@ -22,8 +20,7 @@
{{content-for 'body'}}
-
-
+
{{content-for 'body-footer'}}
diff --git a/tests/dummy/app/models/user-detail.js b/tests/dummy/app/models/user-detail.js
index 194f10a2..3432caed 100644
--- a/tests/dummy/app/models/user-detail.js
+++ b/tests/dummy/app/models/user-detail.js
@@ -3,19 +3,14 @@
* Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
+ // BEGIN-SNIPPET user-detail-model
import Ember from 'ember';
import DS from 'ember-data';
import moment from 'moment';
-import {
- validator, buildValidations
-}
-from 'ember-cp-validations';
+import { validator, buildValidations } from 'ember-cp-validations';
-const {
- computed
-} = Ember;
-
-var attr = DS.attr;
+const { computed } = Ember;
+const { attr } = DS;
var Validations = buildValidations({
firstName: validator('presence', true),
@@ -64,3 +59,4 @@ export default DS.Model.extend(Validations, {
"phone": attr('string'),
"url": attr('string')
});
+// END-SNIPPET
diff --git a/tests/dummy/app/models/user.js b/tests/dummy/app/models/user.js
index 7b88280f..2719c47d 100644
--- a/tests/dummy/app/models/user.js
+++ b/tests/dummy/app/models/user.js
@@ -3,15 +3,13 @@
* Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
+ // BEGIN-SNIPPET user-model
import Ember from 'ember';
import DS from 'ember-data';
import { validator, buildValidations } from 'ember-cp-validations';
-const {
- computed
-} = Ember;
-
-var attr = DS.attr;
+const { computed } = Ember;
+const { attr } = DS;
var Validations = buildValidations({
username: {
@@ -67,3 +65,4 @@ export default DS.Model.extend(Validations, {
minLength: 5
});
+// END-SNIPPET
diff --git a/tests/dummy/app/styles/app.less b/tests/dummy/app/styles/app.less
new file mode 100644
index 00000000..8edc4f20
--- /dev/null
+++ b/tests/dummy/app/styles/app.less
@@ -0,0 +1,29 @@
+@accent-color: #f23818;
+
+@import "./navbar.less";
+@import "./form.less";
+@import "./code-snippet.less";
+
+body,
+html {
+ min-height: 100%;
+ min-width: 100%;
+ background-color: #F3F3F3;
+ height: 100%;
+ font-family: 'Open Sans', sans-serif;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+
+ > div {
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ }
+}
+
+.content {
+ display: flex;
+ justify-content: center;
+ padding: 25px;
+ flex: 1 0 auto;
+}
diff --git a/tests/dummy/app/styles/code-snippet.less b/tests/dummy/app/styles/code-snippet.less
new file mode 100644
index 00000000..9d2d4303
--- /dev/null
+++ b/tests/dummy/app/styles/code-snippet.less
@@ -0,0 +1,51 @@
+@background-color: #fdfdfd;
+
+.snippet-container {
+ background: @background-color;
+ align-self: flex-start;
+ overflow: auto;
+ width: 0;
+ height: 670px;
+ margin: auto 0;
+ -webkit-transition: width 1s ease;
+ -moz-transition: width 1s ease;
+ -o-transition: width 1s ease;
+ transition: width 1s ease;
+ border-radius: 3px;
+ padding: 15px 10px;
+ margin-left: -20px;
+ z-index: 0;
+
+ &.show {
+ width: 600px;
+ margin-left: -2px;
+ box-shadow: 3px 3px 10px 1px rgba(0, 0, 0, 0.15);
+ }
+
+ .nav-tabs {
+ li > a {
+ color: #8A8A8A;
+ border-radius: 2px 2px 0 0;
+ font-size: 12px;
+ }
+ li.active > a {
+ background-color: @background-color;
+ color: #696969;
+ }
+ }
+ .tab-content {
+ background-color: @background-color;
+ max-height: 600px;
+ overflow: auto;
+
+ > .active {
+ padding: 15px 15px 0;
+ }
+ }
+ pre {
+ border: none;
+ margin: 0;
+ padding: 0;
+ background-color: @background-color;
+ }
+}
diff --git a/tests/dummy/app/styles/app.css b/tests/dummy/app/styles/form.less
similarity index 73%
rename from tests/dummy/app/styles/app.css
rename to tests/dummy/app/styles/form.less
index 49a7086b..9789e1be 100644
--- a/tests/dummy/app/styles/app.css
+++ b/tests/dummy/app/styles/form.less
@@ -1,53 +1,18 @@
-/**
- * Copyright 2016, Yahoo! Inc.
- * Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
- */
-
-html {
- width: 100%;
- height: 100%;
-}
-
-body {
- margin: 0;
- padding: 0;
- font-family: 'Open Sans', sans-serif;
- background: #e9e9e9;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
-
-.demo {
- margin-bottom: 50px;
+.form {
text-align: center;
-}
-
-.demo .info {
- width: 500px;
- margin: 25px auto;
- text-align: center;
-}
-
-.demo .info h1 {
- margin: 0;
- padding: 0;
- font-size: 24px;
- font-weight: 400;
- color: #333333;
-}
-
-.demo .form {
position: relative;
background: #ffffff;
width: 485px;
- margin: 25px auto 0;
padding: 40px;
- border-top: 5px solid #f23818;
+ border-top: 5px solid @accent-color;
border-radius: 3px;
- box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.15);
+ box-shadow: 5px 5px 10px 1px rgba(0, 0, 0, 0.15);
+ flex: 0;
+ z-index: 5;
+ align-self: center;
}
-.demo .form input {
+.form input {
outline: none;
display: block;
width: 100%;
@@ -66,7 +31,7 @@ body {
box-shadow: none;
}
-.demo .form .form-group {
+.form .form-group {
margin: 0 0 20px;
}
@@ -83,27 +48,34 @@ body {
border-color: rgb(31, 187, 20);
}
-.demo .form input:focus {
- outline: none;
+.has-success .form-control {
+ border-color: #d9d9d9;
+}
+
+input.form-control:focus {
color: #333333;
+ border-color: #b9b9b9;
+ outline: none;
+ box-shadow: none;
+ -webkit-box-shadow: none;
}
-.demo .form h2 {
+.form h2 {
margin: -15px 0 25px 0;
line-height: 1;
- color: #f23818;
+ color: @accent-color;
font-size: 18px;
font-weight: 400;
}
-.demo .form form h4 {
+.form form h4 {
margin-bottom: 20px;
color: rgb(107, 106, 106);
font-weight: 400;
font-size: 16px;
}
-.demo .form .alert {
+.form .alert {
position: relative;
background: #f3f3f3;
color: #666666;
@@ -113,7 +85,7 @@ body {
text-align: left;
}
-.demo .form .alert .icon-remove {
+.form .alert .icon-remove {
cursor: pointer;
position: absolute;
top: 50%;
@@ -126,10 +98,10 @@ body {
float: right;
}
-.demo .form button {
+.form button {
cursor: pointer;
outline: none;
- background: #f23818;
+ background: @accent-color;
width: 100%;
padding: 10px 15px;
margin-bottom: 25px;
@@ -144,7 +116,7 @@ body {
transition: all 0.3s linear 0s;
}
-.demo .form .section {
+.form .section {
position: relative;
}
@@ -173,7 +145,7 @@ body {
border-bottom: 10px solid transparent;
}
-.demo .form .section-info.left {
+.form .section-info.left {
left: -325px;
}
@@ -206,8 +178,8 @@ body {
top: -50%;
}
-.demo .form footer {
- background: #f2f2f2;
+.form footer {
+ background: #eae9e9;
width: 485px;
padding: 15px 40px;
margin: 0 0 -40px -40px;
@@ -217,18 +189,18 @@ body {
text-align: center;
}
-.demo .form footer a {
+.form footer a {
color: #333333;
text-decoration: none;
}
-.demo .form h2.success {
+.form h2.success {
font-size: 40px;
margin-bottom: 40px;
padding-top: 20px;
}
-.demo .form .tomster {
+.form .tomster {
position: absolute;
top: 0;
z-index: -1;
@@ -242,7 +214,7 @@ body {
animation-fill-mode: forwards;
}
-.demo .form .registered .icon-success {
+.form .registered .icon-success {
font-size: 160px;
color: #A5A5A5;
margin-bottom: 15px;
@@ -278,32 +250,10 @@ body {
color: rgb(255, 165, 31);
}
-.demo a.show-code {
+a.show-code {
cursor: pointer;
}
-.code {
- display: none;
- position: relative;
- width: 600px;
- margin: -10px auto 25px auto;
- background: rgba(0, 0, 0, 0.8);
- padding: 0 25px;
-}
-
-.code:before {
- left: 295px;
-}
-
-.code .prettyprint {
- background-color: transparent;
- border: none;
-}
-
-.code.show {
- display: block;
-}
-
@-webkit-keyframes peek {
from {
top: 0;
diff --git a/tests/dummy/app/styles/navbar.less b/tests/dummy/app/styles/navbar.less
new file mode 100644
index 00000000..4bd6ce8f
--- /dev/null
+++ b/tests/dummy/app/styles/navbar.less
@@ -0,0 +1,41 @@
+.navbar.navbar-default {
+ background-color: white;
+ margin: 0;
+ border-radius: 0;
+ border-width: 0;
+ border-bottom-width: 1px;
+
+ .navbar-brand {
+ color: #797979;
+ font-size: 16px;
+ font-weight: 400;
+ img {
+ height: 32px;
+ display: inline-block;
+ margin-top: -15px;
+ }
+ span {
+ font-size: 12px;
+ vertical-align: super;
+ text-transform: uppercase;
+ color: #444444;
+ }
+ }
+ .navbar-nav > li > a {
+ font-size: 14px;
+ font-weight: 200;
+ &.github {
+ font-size: 24px;
+ }
+ }
+ .navbar-nav > li > a:focus,
+ .navbar-nav > li > a:hover {
+ color: @accent-color;
+ }
+ .navbar-nav > .active > a,
+ .navbar-nav > .active > a:focus,
+ .navbar-nav > .active > a:hover {
+ color: @accent-color;
+ background-color: transparent;
+ }
+}
diff --git a/tests/dummy/app/templates/application.hbs b/tests/dummy/app/templates/application.hbs
index c24cd689..18eedccf 100644
--- a/tests/dummy/app/templates/application.hbs
+++ b/tests/dummy/app/templates/application.hbs
@@ -1 +1,32 @@
-{{outlet}}
+
+
+
+ {{outlet}}
+
diff --git a/tests/dummy/app/templates/components/validated-input.hbs b/tests/dummy/app/templates/components/validated-input.hbs
index de32bc9e..8dbcfa96 100644
--- a/tests/dummy/app/templates/components/validated-input.hbs
+++ b/tests/dummy/app/templates/components/validated-input.hbs
@@ -1,3 +1,4 @@
+{{!-- BEGIN-SNIPPET validated-input --}}
{{input type=type value=value placeholder=placeholder class="form-control" name=valuePath}}
{{#if isValid}}
@@ -18,3 +19,4 @@
{{/if}}
+{{!-- END-SNIPPET --}}
diff --git a/tests/dummy/app/templates/index.hbs b/tests/dummy/app/templates/index.hbs
index 433cbf7c..70a705ac 100644
--- a/tests/dummy/app/templates/index.hbs
+++ b/tests/dummy/app/templates/index.hbs
@@ -1,71 +1,77 @@
-
+