”2016-03-29”

This commit is contained in:
Martin Donnelly 2016-03-29 12:15:56 +01:00
commit bf969ce01b
134 changed files with 3646 additions and 0 deletions

View File

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

View File

@ -0,0 +1,26 @@
# 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,json,hbs,html,css}]
indent_style = space
indent_size = 2
[*.hbs]
insert_final_newline = false
[*.{diff,md}]
indent_size = 2
trim_trailing_whitespace = false

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
}

View File

@ -0,0 +1,192 @@
### Archives template
# It's better to unpack these files and commit the raw source because
# git has its own built in compression methods.
*.7z
*.jar
*.rar
*.zip
*.gz
*.bzip
*.bz2
*.xz
*.lzma
*.cab
#packing-only formats
*.iso
*.tar
#package management formats
*.dmg
*.xpi
*.gem
*.egg
*.deb
*.rpm
*.msi
*.msm
*.msp
### Windows template
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# Windows shortcuts
*.lnk
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
*.iml
## Directory-based project format:
.idea/
# if you remove the above rule, at least ignore the following:
# User-specific stuff:
# .idea/workspace.xml
# .idea/tasks.xml
# .idea/dictionaries
# Sensitive or high-churn files:
# .idea/dataSources.ids
# .idea/dataSources.xml
# .idea/sqlDataSources.xml
# .idea/dynamic.xml
# .idea/uiDesigner.xml
# Gradle:
# .idea/gradle.xml
# .idea/libraries
# Mongo Explorer plugin:
# .idea/mongoSettings.xml
## File-based project format:
*.ipr
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
### Xcode template
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## Build generated
build/
DerivedData
## Various settings
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
## Other
*.xccheckout
*.moved-aside
*.xcuserstate
### OSX template
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### Node template
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directory
# https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git
node_modules
# See http://help.github.com/ignore-files/ for more about ignoring files.
# compiled output
/dist
/tmp
# dependencies
/node_modules
/bower_components
# misc
/.sass-cache
/connect.lock
/coverage/*
/libpeerconnection.log
npm-debug.log
testem.log
/.cache
/.gradle

View File

@ -0,0 +1,46 @@
{
"disallowKeywords": ["with"],
"disallowKeywordsOnNewLine": ["else"],
"disallowMixedSpacesAndTabs": true,
"disallowMultipleVarDecl": "exceptUndefined",
"disallowNewlineBeforeBlockStatements": true,
"disallowQuotedKeysInObjects": true,
"disallowSpaceAfterObjectKeys": true,
"disallowSpaceAfterPrefixUnaryOperators": true,
"disallowSpacesInFunction": {
"beforeOpeningRoundBrace": true
},
"disallowSpacesInsideParentheses": true,
"disallowTrailingWhitespace": true,
"maximumLineLength": 120,
"requireCamelCaseOrUpperCaseIdentifiers": false,
"requireCapitalizedComments": true,
"requireCapitalizedConstructors": true,
"requireCurlyBraces": true,
"requireSpaceAfterKeywords": [
"if",
"else",
"for",
"while",
"do",
"switch",
"case",
"return",
"try",
"catch",
"typeof"
],
"requireSpaceAfterLineComment": true,
"requireSpaceAfterBinaryOperators": true,
"requireSpaceBeforeBinaryOperators": true,
"requireSpaceBeforeBlockStatements": true,
"requireSpaceBeforeObjectValues": true,
"requireSpacesInFunction": {
"beforeOpeningCurlyBrace": true
},
"requireTrailingComma": false,
"requireEarlyReturn": true,
"validateIndentation": 2,
"validateLineBreaks": "LF",
"validateQuoteMarks": "'"
}

View File

@ -0,0 +1,33 @@
{
"predef": [
"server",
"document",
"window",
"-Promise"
],
"browser": true,
"boss": true,
"curly": true,
"debug": false,
"devel": true,
"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,
"unused": true
}

View File

@ -0,0 +1,23 @@
---
language: node_js
node_js:
- "0.12"
sudo: false
cache:
directories:
- node_modules
before_install:
- export PATH=/usr/local/phantomjs-2.0.0/bin:$PATH
- "npm config set spin false"
- "npm install -g npm@^2"
install:
- npm install -g bower
- npm install
- bower install
script:
- npm test

View File

@ -0,0 +1,3 @@
{
"ignore_dirs": ["tmp", "dist"]
}

View File

@ -0,0 +1,53 @@
# Obrand-admin
This README outlines the details of collaborating on this Ember application.
A short introduction of this app could easily go here.
## Prerequisites
You will need the following things properly installed on your computer.
* [Git](http://git-scm.com/)
* [Node.js](http://nodejs.org/) (with NPM)
* [Bower](http://bower.io/)
* [Ember CLI](http://www.ember-cli.com/)
* [PhantomJS](http://phantomjs.org/)
## Installation
* `git clone <repository-url>` this repository
* change into the new directory
* `npm install`
* `bower install`
## Running / Development
* `ember server`
* Visit your app at [http://localhost:4200](http://localhost:4200).
### Code Generators
Make use of the many generators for code, try `ember help generate` for more details
### Running Tests
* `ember test`
* `ember test --server`
### Building
* `ember build` (development)
* `ember build --environment production` (production)
### Deploying
Specify what it takes to deploy your app.
## Further Reading / Useful Links
* [ember.js](http://emberjs.com/)
* [ember-cli](http://www.ember-cli.com/)
* Development Browser Extensions
* [ember inspector for chrome](https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi)
* [ember inspector for firefox](https://addons.mozilla.org/en-US/firefox/addon/ember-inspector/)

View File

@ -0,0 +1,6 @@
import DS from 'ember-data';
import DataAdapterMixin from 'ember-simple-auth/mixins/data-adapter-mixin';
export default DS.JSONAPIAdapter.extend(DataAdapterMixin, {
authorizer: 'authorizer:application'
});

View File

@ -0,0 +1,5 @@
import ApplicationAdapter from './application';
export default ApplicationAdapter.extend({
namespace: 'api'
});

View File

@ -0,0 +1,5 @@
import ApplicationAdapter from './application';
export default ApplicationAdapter.extend({
namespace:'api'
});

View File

@ -0,0 +1,5 @@
import ApplicationAdapter from './application';
export default ApplicationAdapter.extend({
namespace:'api'
});

View File

@ -0,0 +1,20 @@
import Ember from 'ember';
import Resolver from './resolver';
import loadInitializers from 'ember-load-initializers';
import config from './config/environment';
let App;
Ember.MODEL_FACTORY_INJECTIONS = true;
Ember.LOG_TRANSITIONS = true;
Ember.LOG_TRANSITIONS_INTERNAL = true;
App = Ember.Application.extend({
modulePrefix: config.modulePrefix,
podModulePrefix: config.podModulePrefix,
Resolver
});
loadInitializers(App, config.modulePrefix);
export default App;

View File

@ -0,0 +1,10 @@
/**
*
* User: Martin Donnelly
* Date: 2016-03-04
* Time: 14:23
*
*/
import OAuth2PasswordGrant from 'ember-simple-auth/authenticators/oauth2-password-grant';
export default OAuth2PasswordGrant.extend();

View File

@ -0,0 +1,13 @@
/*
import Base from 'ember-simple-auth/authorizers/base';
export default Base.extend({
authorize(/!*data, block*!/) {
}
});
*/
import OAuth2Bearer from 'ember-simple-auth/authorizers/oauth2-bearer';
export default OAuth2Bearer.extend();

View File

@ -0,0 +1,19 @@
import Ember from 'ember';
const { service } = Ember.inject;
export default Ember.Component.extend({
session: service('session'), sessionAccount: service('session-account'),
actions: {
login() {
console.log('send onLogin?');
this.sendAction('onLogin');
},
logout() {
console.log('Invalidating session');
this.get('session').invalidate();
}
}
});

View File

@ -0,0 +1,7 @@
import Ember from 'ember';
const { service } = Ember.inject;
export default Ember.Component.extend({
session: service('session'), sessionAccount: service('session-account')
});

View File

@ -0,0 +1,4 @@
import Ember from 'ember';
export default Ember.Component.extend({
});

View File

@ -0,0 +1,9 @@
import Ember from 'ember';
export default Ember.Controller.extend({
actions: {
transitionToLoginRoute() {
this.transitionToRoute('login');
}
}
});

View File

@ -0,0 +1,35 @@
'use strict';
import Ember from 'ember';
const {service} = Ember.inject;
export default Ember.Controller.extend({
session: service('session'),
sessionAccount: service('session-account'),
actions: {
editCompany: function() {
this.set('isEditing', true);
}, saveCompany: function() {
this.set('isEditing', false);
console.log(this.get('isEditing'));
var model = this.get('model');
this.model.save()
.then(function(d) {
console.log(d);
})
.catch(function(err) {
console.log(err);
});
}, cancelEdit: function() {
var model = this.get('model');
model.rollbackAttributes();
this.set('isEditing', false);
}
}
});

View File

@ -0,0 +1,25 @@
import Ember from 'ember';
const { service } = Ember.inject;
export default Ember.Controller.extend({
session: service('session'),
actions: {
authenticate() {
'use strict';
console.log('Lets login');
let {identification, password } = this.getProperties('identification', 'password');
this.get('session').authenticate('authenticator:oauth2', identification, password)
.then(function(d) {
console.log('logged in');
console.log(d);
})
.catch((reason) => {
this.set('errorMessage', reason.error);
});
}
}
});

View File

@ -0,0 +1,34 @@
'use strict';
import Ember from 'ember';
const { service } = Ember.inject;
export default Ember.Controller.extend({
session: service('session'),
sessionAccount: service('session-account'),
actions: {
saveCompany: function() {
console.log('save company');
var model = this.get('model');
var account = this.get('sessionAccount.account');
console.log(model.get('company_name'));
model.set('uid', this.get('sessionAccount.account.uid'));
model.save()
.then(function(d) {
console.log(d);
account.set('memberof', model.get('cid'));
})
.catch(function(err) {
console.log(err);
});
// This.set('isEditing', false);
//this.transitionTo('company');
}
}
});

View File

@ -0,0 +1,4 @@
import Ember from 'ember';
export default Ember.Controller.extend({
});

View File

@ -0,0 +1,31 @@
'use strict';
import Ember from 'ember';
const { service } = Ember.inject;
export default Ember.Controller.extend({
session: service('session'),
sessionAccount: service('session-account'),
genders: [{g: 'Male', id: 0}, {g: 'Female', id: 1}],
actions: {
editProfile: function() {
this.set('isEditing', true);
}, saveProfile: function() {
var model = this.get('model');
this.set('sessionAccount.account.forename', model.get('forename'));
// this.profile.save();
console.log(model.get('dob'));
this.model.save()
.then(function(d) {
console.log(d);
})
.catch(function(err) {
console.log(err);
});
this.set('isEditing', false);
}
}
});

View File

@ -0,0 +1,9 @@
import Ember from 'ember';
/*export function eq(params/!*, hash*!/) {
return params;
}*/
const eq = (params) => params[0] === params[1];
export default Ember.Helper.helper(eq);

View File

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>ObrandAdmin</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
{{content-for "head"}}
<link rel="stylesheet" href="assets/vendor.css">
<link rel="stylesheet" href="assets/obrand-admin.css">
{{content-for "head-footer"}}
</head>
<body>
{{content-for "body"}}
<script src="assets/vendor.js"></script>
<script src="assets/obrand-admin.js"></script>
{{content-for "body-footer"}}
</body>
</html>

View File

@ -0,0 +1,16 @@
import DS from 'ember-data';
const { attr } = DS;
export default DS.Model.extend({
uid: DS.attr('string'),
login: DS.attr('string'),
/*name: DS.attr('string'),*/
forename: DS.attr('string'),
surname: DS.attr('string'),
memberof: DS.attr('string'),
fullName: function() {
return '%@ %@'.fmt(this.get('forename'), this.get('surname'));
}.property('forename', 'surname')
});

View File

@ -0,0 +1,5 @@
import DS from 'ember-data';
export default DS.Model.extend({
});

View File

@ -0,0 +1,27 @@
import DS from 'ember-data';
const { attr } = DS;
export default DS.Model.extend({
cid: DS.attr('string'),
company_name: DS.attr('string'),
address1: DS.attr('string'),
address2: DS.attr('string'),
address3: DS.attr('string'),
town: DS.attr('string'),
county: DS.attr('string'),
postcode: DS.attr('string'),
country: DS.attr('string'),
pcontact: DS.attr('string'),
ocontact: DS.attr('string'),
mobile: DS.attr('string'),
email: DS.attr('string'),
needCompany: function() {
console.log('NeedCompany');
if (typeof this.get('cid') !== 'undefined') {
return true;
} else {
return false;
}
}.property('cid')
});

View File

@ -0,0 +1,20 @@
import DS from 'ember-data';
const { attr } = DS;
export default DS.Model.extend({
uid: attr(),
cid: attr(),
company_name: attr('string'),
address1: attr(),
address2: attr(),
address3: attr(),
town: attr(),
county: attr(),
postcode: attr(),
country: attr(),
pcontact: attr(),
ocontact: attr(),
mobile: attr(),
email: attr()
});

View File

@ -0,0 +1,14 @@
import DS from 'ember-data';
export default DS.Model.extend({
title: DS.attr('string'),
imageUrl: DS.attr('string'),
link1Text: DS.attr('string'),
link1Url: DS.attr('string'),
link2Text: DS.attr('string'),
link2Url: DS.attr('string'),
link3Text: DS.attr('string'),
link3Url: DS.attr('string'),
link4Text: DS.attr('string'),
link4Url: DS.attr('string')
});

View File

@ -0,0 +1,9 @@
import DS from 'ember-data';
export default DS.Model.extend({
cid: DS.attr('string'),
pid: DS.attr('string'),
category: DS.attr(),
title: DS.attr('string'),
content: DS.belongsTo('page-content')
});

View File

@ -0,0 +1,22 @@
import DS from 'ember-data';
const { attr } = DS;
export default DS.Model.extend({
uid: attr('string'),
forename: attr('string'),
surname: attr('string'),
gender: attr('number'),
dob: attr(),
bio: attr('string'),
fullName: function() {
return '%@ %@'.fmt(this.get('forename'), this.get('surname'));
}.property('forename', 'surname'),
qualifiedGender: function() {
let genderArray = ['Male', 'Female'];
return genderArray[this.get('gender')];
}.property('gender')
});

View File

@ -0,0 +1,3 @@
import Resolver from 'ember-resolver';
export default Resolver;

View File

@ -0,0 +1,21 @@
import Ember from 'ember';
import config from './config/environment';
const Router = Ember.Router.extend({
location: config.locationType
});
Router.map(function() {
this.route('index', {path:'/'});
this.route('login');
this.route('auth-error');
this.route('about');
this.route('signup');
this.route('profile');
this.route('company');
this.route('newcompany');
this.route('venue');
this.route('pages');
});
export default Router;

View File

@ -0,0 +1,4 @@
import Ember from 'ember';
export default Ember.Route.extend({
});

View File

@ -0,0 +1,18 @@
import Ember from 'ember';
import ApplicationRouteMixin from 'ember-simple-auth/mixins/application-route-mixin';
const { service } = Ember.inject;
export default Ember.Route.extend(ApplicationRouteMixin, {
sessionAccount: service('session-account'),
_loadCurrentUser() {
return this.get('sessionAccount').loadCurrentUser();
},
beforeModel() {
return this._loadCurrentUser();
},
sessionAuthenticated() {
this._super(...arguments);
this._loadCurrentUser().catch(() => this.get('session').invalidate());
}
});

View File

@ -0,0 +1,8 @@
import Ember from 'ember';
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';
export default Ember.Route.extend(AuthenticatedRouteMixin, {
model() {
return this.get('store').find('post', 3);
}
});

View File

@ -0,0 +1,38 @@
import Ember from 'ember';
const { inject: { service }, RSVP } = Ember;
export default Ember.Route.extend({
sessionAccount: service('session-account'),
beforeModel() {
const cid = this.get('sessionAccount.account.memberof');
console.log(this.get('sessionAccount.account'));
console.log('cid:' + cid);
if (typeof cid === 'undefined' || cid === null) {
console.log('Going to new company');
this.transitionTo('newcompany');
}
},
model: function(params) {
'use strict';
const cid = this.get('sessionAccount.account.memberof');
console.log(cid);
if (typeof cid !== 'undefined' && cid !== null) {
return new RSVP.Promise((resolve, reject) => {
return this.get('store').find('company', cid)
.then(resolve, reject);
});
} else {
return {
needNewCompany: true
};
}
}
});

View File

@ -0,0 +1,4 @@
import Ember from 'ember';
export default Ember.Route.extend({
});

View File

@ -0,0 +1,6 @@
import Ember from 'ember';
import UnauthenticatedRouteMixin from 'ember-simple-auth/mixins/unauthenticated-route-mixin';
export default Ember.Route.extend(UnauthenticatedRouteMixin);

View File

@ -0,0 +1,30 @@
import Ember from 'ember';
const { inject: { service }, RSVP } = Ember;
export default Ember.Route.extend({
sessionAccount: service('session-account'),
model: function(params) {
'use strict';
const cid = this.get('sessionAccount.account.memberOf');
console.log(cid);
if (typeof cid !== 'undefined') {
return new RSVP.Promise((resolve, reject) => {
return this.get('store').find('company', cid)
.then(resolve, reject);
});
} else {
console.log('Neeed new company');
var newPage = this.store.createRecord('newcompany',{});
newPage.set('cid', cid);
return newPage;
};
},
});

View File

@ -0,0 +1,18 @@
import Ember from 'ember';
const { inject: { service }, RSVP } = Ember;
export default Ember.Route.extend({
sessionAccount: service('session-account'),
model: function(params) {
'use strict';
const cid = this.get('sessionAccount.account.memberOf');
var newPageContent = this.store.createRecord('page-content',{});
var newPage = this.store.createRecord('page',{});
newPage.set('cid', cid);
newPage.set('content',newPageContent);
return newPage;
}
});

View File

@ -0,0 +1,26 @@
import Ember from 'ember';
const { inject: { service }, RSVP } = Ember;
export default Ember.Route.extend({
sessionAccount: service('session-account'),
model: function(params) {
'use strict';
const accountId = this.get('sessionAccount.account.id');
/*return new RSVP.Promise((resolve,reject) => {
return this.get('store').find('profile',accountId)
.then(function(p) {
resolve(p);
},reject);
});*/
return new RSVP.Promise((resolve,reject) => {
console.log('***HERE***');
return this.get('store').find('profile',accountId)
.then(resolve,reject);
});
}
});

View File

@ -0,0 +1,4 @@
import Ember from 'ember';
export default Ember.Route.extend({
});

View File

@ -0,0 +1,15 @@
import Ember from 'ember';
const { inject: { service }, RSVP } = Ember;
export default Ember.Route.extend({
sessionAccount: service('session-account'),
beforeModel() {
const cid = this.get('sessionAccount.account.memberof');
console.log(this.get('sessionAccount.account'));
console.log('cid:' + cid);
if (typeof cid === 'undefined') {
console.log('Going to new company');
this.transitionTo('newcompany');
}
}
});

View File

@ -0,0 +1,30 @@
import Ember from 'ember';
const { inject: { service }, RSVP } = Ember;
export default Ember.Service.extend({
session: service('session'),
store: service(),
loadCurrentUser() {
console.log('+ loadCurrentUser');
return new RSVP.Promise((resolve, reject) => {
const accountId = this.get('session.data.authenticated.account_id');
if (!Ember.isEmpty(accountId)) {
return this.get('store').find('account', accountId).then((account) => {
console.log('+++');
console.log(account.get('id'));
console.log(account.get('forename'));
console.log(account.get('memberof'));
this.set('account', account);
console.log('---');
return resolve();
}, reject);
} else {
return resolve();
}
});
}
});

View File

@ -0,0 +1,54 @@
@import 'bootstrap';
/*@import 'signin';*/
/*@import 'profile';*/
@import 'side-bar';
$input-border-focus: #ff0000 !default;
body {
padding-top:5em;
}
.app-top {
padding: 3rem 1.5rem;
}
.colour-bg {
color: #fff;
/*background: linear-gradient(-226deg, rgba(142, 130, 236, 0.8) 0%, rgba(8, 81, 152, 0.92) 100%);*/
position: relative;
display: block;
padding: 200px 40px;
height: 500px;
width: 100%;
}
.blue-tint {
background: linear-gradient(-226deg, rgba(142, 130, 236, 0.8) 0%, rgba(8, 81, 152, 0.92) 100%);
}
.user-icon-nav {
margin-right:10px;
}
.dropdown-menu{
padding:5px 0;
margin:2px 0 0;
}
.fakeDevice{
width: 375px;
height: 667px;
border:1px solid grey;
-webkit-box-shadow: 0px 4px 5px 0px rgba(0,0,0,0.43);
-moz-box-shadow: 0px 4px 5px 0px rgba(0,0,0,0.43);
box-shadow: 0px 4px 5px 0px rgba(0,0,0,0.43);
border-radius: 0.25rem;
}

View File

@ -0,0 +1,22 @@
/* CSS used here will be applied after bootstrap.css */
body {
/*background-color: #eaeaea;*/
}
img.avatar {
border: 1px solid #eee;
}
.only-bottom-margin {
margin-top: 0px;
}
.activity-mini {
padding-right: 15px;
float: left;
}
.profileCard {
box-shadow:0 1px 2px #aaa;
}

View File

@ -0,0 +1,341 @@
h1.page-header {
margin-top: -5px;
}
.sidebar {
padding-left: 0;
}
.main-container {
background: #FFF;
padding-top: 15px;
margin-top: -20px;
}
.footer {
width: 100%;
}
:focus {
outline: none;
}
.side-menu {
position: relative;
width: 100%;
height: 100%;
background-color: #f8f8f8;
border-right: 1px solid #e7e7e7;
}
.side-menu .navbar {
border: none;
}
.side-menu .navbar-header {
width: 100%;
border-bottom: 1px solid #e7e7e7;
}
.side-menu .navbar-nav .active a {
background-color: transparent;
margin-right: -1px;
border-right: 5px solid #e7e7e7;
}
.side-menu .navbar-nav li {
display: block;
width: 100%;
border-bottom: 1px solid #e7e7e7;
}
.side-menu .navbar-nav li a {
padding: 15px;
}
.side-menu .navbar-nav li a .glyphicon {
padding-right: 10px;
}
.side-menu #dropdown {
border: 0;
margin-bottom: 0;
border-radius: 0;
background-color: transparent;
box-shadow: none;
}
.side-menu #dropdown .caret {
float: right;
margin: 9px 5px 0;
}
.side-menu #dropdown .indicator {
float: right;
}
.side-menu #dropdown > a {
border-bottom: 1px solid #e7e7e7;
}
.side-menu #dropdown .panel-body {
padding: 0;
background-color: #f3f3f3;
}
.side-menu #dropdown .panel-body .navbar-nav {
width: 100%;
}
.side-menu #dropdown .panel-body .navbar-nav li {
padding-left: 15px;
border-bottom: 1px solid #e7e7e7;
}
.side-menu #dropdown .panel-body .navbar-nav li:last-child {
border-bottom: none;
}
.side-menu #dropdown .panel-body .panel > a {
margin-left: -20px;
padding-left: 35px;
}
.side-menu #dropdown .panel-body .panel-body {
margin-left: -15px;
}
.side-menu #dropdown .panel-body .panel-body li {
padding-left: 30px;
}
.side-menu #dropdown .panel-body .panel-body li:last-child {
border-bottom: 1px solid #e7e7e7;
}
.side-menu #search-trigger {
background-color: #f3f3f3;
border: 0;
border-radius: 0;
position: absolute;
top: 0;
right: 0;
padding: 15px 18px;
}
.side-menu .brand-name-wrapper {
min-height: 50px;
}
.side-menu .brand-name-wrapper .navbar-brand {
display: block;
}
.side-menu #search {
position: relative;
z-index: 1000;
}
.side-menu #search .panel-body {
padding: 0;
}
.side-menu #search .panel-body .navbar-form {
padding: 0;
padding-right: 50px;
width: 100%;
margin: 0;
position: relative;
border-top: 1px solid #e7e7e7;
}
.side-menu #search .panel-body .navbar-form .form-group {
width: 100%;
position: relative;
}
.side-menu #search .panel-body .navbar-form input {
border: 0;
border-radius: 0;
box-shadow: none;
width: 100%;
height: 50px;
}
.side-menu #search .panel-body .navbar-form .btn {
position: absolute;
right: 0;
top: 0;
border: 0;
border-radius: 0;
background-color: #f3f3f3;
padding: 15px 18px;
}
/* Main body section */
.side-body {
margin-left: 310px;
}
/* small screen */
@media (max-width: 768px) {
.side-menu {
position: relative;
width: 100%;
height: 0;
border-right: 0;
}
.side-menu .navbar {
z-index: 999;
position: relative;
height: 0;
min-height: 0;
background-color:none !important;
border-color: none !important;
}
.side-menu .brand-name-wrapper .navbar-brand {
display: inline-block;
}
/* Slide in animation */
@-moz-keyframes slidein {
0% {
left: -300px;
}
100% {
left: 10px;
}
}
@-webkit-keyframes slidein {
0% {
left: -300px;
}
100% {
left: 10px;
}
}
@keyframes slidein {
0% {
left: -300px;
}
100% {
left: 10px;
}
}
@-moz-keyframes slideout {
0% {
left: 0;
}
100% {
left: -300px;
}
}
@-webkit-keyframes slideout {
0% {
left: 0;
}
100% {
left: -300px;
}
}
@keyframes slideout {
0% {
left: 0;
}
100% {
left: -300px;
}
}
/* Slide side menu*/
/* Add .absolute-wrapper.slide-in for scrollable menu -> see top comment */
.side-menu-container > .navbar-nav.slide-in {
-moz-animation: slidein 300ms forwards;
-o-animation: slidein 300ms forwards;
-webkit-animation: slidein 300ms forwards;
animation: slidein 300ms forwards;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
}
.side-menu-container > .navbar-nav {
/* Add position:absolute for scrollable menu -> see top comment */
position: fixed;
left: -300px;
width: 300px;
top: 43px;
height: 100%;
border-right: 1px solid #e7e7e7;
background-color: #f8f8f8;
overflow: auto;
-moz-animation: slideout 300ms forwards;
-o-animation: slideout 300ms forwards;
-webkit-animation: slideout 300ms forwards;
animation: slideout 300ms forwards;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
}
@-moz-keyframes bodyslidein {
0% {
left: 0;
}
100% {
left: 300px;
}
}
@-webkit-keyframes bodyslidein {
0% {
left: 0;
}
100% {
left: 300px;
}
}
@keyframes bodyslidein {
0% {
left: 0;
}
100% {
left: 300px;
}
}
@-moz-keyframes bodyslideout {
0% {
left: 300px;
}
100% {
left: 0;
}
}
@-webkit-keyframes bodyslideout {
0% {
left: 300px;
}
100% {
left: 0;
}
}
@keyframes bodyslideout {
0% {
left: 300px;
}
100% {
left: 0;
}
}
/* Slide side body*/
.side-body {
margin-left: 5px;
margin-top: 70px;
position: relative;
-moz-animation: bodyslideout 300ms forwards;
-o-animation: bodyslideout 300ms forwards;
-webkit-animation: bodyslideout 300ms forwards;
animation: bodyslideout 300ms forwards;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
}
.body-slide-in {
-moz-animation: bodyslidein 300ms forwards;
-o-animation: bodyslidein 300ms forwards;
-webkit-animation: bodyslidein 300ms forwards;
animation: bodyslidein 300ms forwards;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
}
/* Hamburger */
.navbar-toggle-sidebar {
border: 0;
float: left;
padding: 18px;
margin: 0;
border-radius: 0;
background-color: #f3f3f3;
}
/* Search */
#search .panel-body .navbar-form {
border-bottom: 0;
}
#search .panel-body .navbar-form .form-group {
margin: 0;
}
.side-menu .navbar-header {
/* this is probably redundant */
position: fixed;
z-index: 3;
background-color: #f8f8f8;
}
/* Dropdown tweek */
#dropdown .panel-body .navbar-nav {
margin: 0;
}
}

View File

@ -0,0 +1,42 @@
.form-signin {
max-width:330px;
padding:15px;
margin:0 auto;
box-shadow:0 1px 2px #aaa;
border-radius:3px;
user-select:none;
}
.form-signin .form-signin-heading, .form-signin .checkbox {
margin-bottom:10px;
}
.form-signin .checkbox {
font-weight:normal;
}
.form-signin .form-control {
position:relative;
height:auto;
-webkit-box-sizing:border-box;
box-sizing: border-box;
padding:10px;
font-size:16px;
}
.form-signin .form-control:focus{
z-index: 2;
}
.form-signin input[type="email"] {
margin-bottom:-1px;
border-bottom-right-radius:0;
border-bottom-left-radius:0;
}
.form-signin input[type='password'] {
margin-bottom:10px;
border-top-left-radius: 0;
border-top-right-radius: 0;
}

View File

@ -0,0 +1,6 @@
<div class="jumbotron">
<div class="container">
<h1>Welcome to OBrand</h1>
<p>Det är ett välkänt faktum att läsare distraheras av läsbar text på en sida när man skall studera layouten. Poängen med Lorem Ipsum är att det ger ett normalt ordflöde, till skillnad från "Text här, Text här", och ger intryck av att vara läsbar text. Många publiseringprogram och webbutvecklare använder Lorem Ipsum som test-text, och en sökning efter "Lorem Ipsum" avslöjar många webbsidor under uteckling. Olika versioner har dykt upp under åren, ibland av olyckshändelse, ibland med flit (mer eller mindre humoristiska).</p>
</div>
</div>

View File

@ -0,0 +1,14 @@
{{nav-bar currentControllerBindings="controller"}}
<div class="container-fluid main-container" class="app-body">
{{outlet}}
<footer class="pull-left footer">
<p class="col-md-12">
<hr class="divider">
Copyright &COPY; 2016 <a
href="http://www.obrand.info">Obrand Communications</a> </p>
</footer>
</div>

View File

@ -0,0 +1 @@
{{outlet}}

View File

@ -0,0 +1,156 @@
<!--<div class="container profileCard">-->
<div class="container profileCard">
{{#if isEditing}}
<form {{action "saveCompany" on='submit'}} class="form-horizontal">
<div class="form-group">
<label for="company_name"
class="col-sm-2 control-label">Company name:</label>
<div class="col-sm-10">
{{input id='company_name' placeholder='Company name' valueBinding=model.company_name class="form-control" required="required"}}
</div>
</div>
<br/>
<div class="form-group">
<label for="address1" class="col-sm-2 control-label">Address:</label>
<div class="col-sm-10">
{{input id='address1' placeholder='Address' valueBinding=model.address1 class="form-control" required="required"}}
{{input id='address2' placeholder='Address' valueBinding=model.address2 class="form-control" }}
{{input id='address3' placeholder='Address' valueBinding=model.address3 class="form-control" }}
</div>
</div>
<br/>
<!-- -->
<div class="form-group">
<label for="town" class="col-sm-2 control-label">Town:</label>
<div class="col-sm-10">
{{input id='town' placeholder='Town' valueBinding=model.town class="form-control" required="required"}}
</div>
<!-- -->
<label for="county" class="col-sm-2 control-label">County:</label>
<div class="col-sm-10">
{{input id='county' placeholder='County' valueBinding=model.county class="form-control" }}
</div>
<!-- -->
<label for="postcode" class="col-sm-2 control-label">Postcode:</label>
<div class="col-sm-10">
{{input id='postcode' placeholder='Postcode' valueBinding=model.postcode class="form-control" required="required"}}
</div>
</div>
<br/>
<div class="form-group">
<label for="pcontact"
class="col-sm-2 control-label">Primary Contact:</label>
<div class="col-sm-10">
{{input id='pcontact' placeholder='Primary contact number' valueBinding=model.pcontact class="form-control" required="required"}}
</div>
<label for="ocontact"
class="col-sm-2 control-label">Other Contact:</label>
<div class="col-sm-10">
{{input id='ocontact' placeholder='Other contact phone number' valueBinding=model.ocontact class="form-control" }}
</div>
<label for="mobile" class="col-sm-2 control-label">Mobile:</label>
<div class="col-sm-10">
{{input id='mobile' placeholder='Mobile phone' valueBinding=model.mobile class="form-control" }}
</div>
</div>
<br/>
<div class="form-group">
<label for="email" class="col-sm-2 control-label">Email:</label>
<div class="col-sm-10">
{{input id='email' placeholder='Contact email address' valueBinding=model.email class="form-control" required="required"}}
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-md-8">&nbsp;</div>
<div class="col-md-4">
{{#if isEditing}}
<button class="btn btn-primary pull-right" type="submit">
<i class="glyphicon glyphicon-pencil"></i> Save
</button>
&nbsp;
<button class="btn btn-warning-outline pull-right" {{action "cancelEdit"}}>
Cancel
</button>
{{/if}}
</div>
</div>
</div>
</form>
{{else}}
<h1 class="only-bottom-margin">{{model.company_name}}</h1>
<div class="row">
<div class="col-sm-2">Address</div>
<div class="col-sm-10">
<div>{{model.address1}}</div>
<div>{{model.address2}}</div>
<div>{{model.address3}}</div>
</div>
</div>
<div class="row">
<div class="col-sm-2">Town</div>
<div class="col-sm-10">
<div>{{model.town}}</div>
</div>
</div>
<div class="row">
<div class="col-sm-2">County</div>
<div class="col-sm-10">
<div>{{model.county}}</div>
</div>
</div>
<div class="row">
<div class="col-sm-2">Postcode</div>
<div class="col-sm-10">
<div>{{model.postcode}}</div>
</div>
</div>
<div class="row">
<div class="col-sm-2">Primary contact</div>
<div class="col-sm-10">
<div>{{model.pcontact}}</div>
</div>
</div>
<div class="row">
<div class="col-sm-2">Secondary contact</div>
<div class="col-sm-10">
<div>{{model.ocontact}}</div>
</div>
</div>
<div class="row">
<div class="col-sm-2">Mobile</div>
<div class="col-sm-10">
<div>{{model.mobile}}</div>
</div>
</div>
<div class="row">
<div class="col-sm-2">Email</div>
<div class="col-sm-10">
<div>{{model.email}}</div>
</div>
</div>
{{/if}}
<div class="form-group">
<div class="row">
<div class="col-md-12">
{{#if isEditing}}
{{else}}
<button class="btn btn-default pull-right" {{action "editCompany"}}>
<i class="glyphicon glyphicon-pencil"></i> Edit
</button>
&nbsp;
{{/if}}
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,52 @@
<!--<nav class="navbar navbar-fixed-top navbar-dark bg-inverse">-->
<nav class="navbar navbar-light bg-faded navbar-fixed-top">
<div class="collapse navbar-toggleable-xs">
<a class="navbar-brand" href="#">OBrand Admin</a>
<ul class="nav navbar-nav">
<li class="nav-item">
{{#link-to 'index' class='nav-link'}}Home{{/link-to}}
</li>
<li class="nav-item">
{{#link-to 'about' class='nav-link'}}About{{/link-to}}
</li>
<li class="nav-item">
<a class="nav-link" href="#">Contact</a>
</li>
{{#if session.isAuthenticated}}
<li class="nav-item">
{{#link-to 'profile' class='nav-link'}}Profile{{/link-to}}
</li>
<li class="nav-item">
{{#link-to 'company' class='nav-link'}}Company{{/link-to}}
</li>
<li class="nav-item">
{{#link-to 'venue' class='nav-link'}}Venues{{/link-to}}
</li>
<li class="nav-item">
<a class="nav-link" href="#">Beacons</a>
</li>
<li class="nav-item">
{{#link-to 'pages' class='nav-link'}}Pages{{/link-to}}
</li>
{{/if}}
</ul>
<div class="pull-xs-right">
{{#if sessionAccount.account}}
<span
class="nav-item">{{gravatar-image email=sessionAccount.account.login size=25 class="img-circle avatar avatar-original pull-right user-icon-nav" defaultImage='identicon'}}
<span class="text-primary">{{sessionAccount.account.forename}}</span></span>
<span class="navbar-divider"></span>
{{/if}}
<span class="nav-item">
{{#if session.isAuthenticated}}
<a {{action 'logout'}} class="btn btn-danger-outline">Logout</a>
{{else}}
{{#link-to 'login' class='btn btn-primary-outline'}}Login{{/link-to}}
{{/if}}
</span>
</div>
</div>
</nav>

View File

@ -0,0 +1,29 @@
<div class="container-fluid main-container">
<div class="col-md-12 content">
<div class="card">
<div class="card-header">
New Page
</div>
<div class="card-block">
<div class="row">
<div class="col-md-4 content">
Entered content
</div>
<div class="col-md-8 content">
<div id="fakeDevice" class="fakeDevice">
<h1 class="text-xs-center">OBrand Test</h1>
<img src="http://placehold.it/300x300" class="center-block"/>
<ul class="list-group">
<li class="list-group-item">List item 1</li>
<li class="list-group-item">List item 2</li>
<li class="list-group-item">List item 3</li>
<li class="list-group-item">List item 4</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,65 @@
<!-- trying to implement the menu from
http://bootsnipp.com/snippets/featured/simple-admin
-->
<div class="col-md-2 sidebar">
<div class="row">
<div class="absolute-wrapper"></div>
<div class="side-menu">
<nav class="navbar navbar-default" role="navigation">
<!-- Main Menu -->
<div class="side-menu-container">
<ul class="nav navbar-nav">
<li class="active"><a href="#"><span
class="glyphicon glyphicon-dashboard"></span> Dashboard</a></li>
<li><a href="#"><span
class="glyphicon glyphicon-plane"></span> Active Link</a></li>
<li><a href="#"><span
class="glyphicon glyphicon-cloud"></span> Link</a></li>
<!-- Dropdown-->
<li class="panel panel-default" id="dropdown">
<a data-toggle="collapse" href="#dropdown-lvl1"> <span
class="glyphicon glyphicon-user"></span> Sub Level <span
class="caret"></span> </a>
<!-- Dropdown level 1 -->
<div id="dropdown-lvl1" class="panel-collapse collapse">
<div class="panel-body">
<ul class="nav navbar-nav">
<li><a href="#">Link</a></li>
<li><a href="#">Link</a></li>
<li><a href="#">Link</a></li>
<!-- Dropdown level 2 -->
<li class="panel panel-default" id="dropdown">
<a data-toggle="collapse" href="#dropdown-lvl2"> <span
class="glyphicon glyphicon-off"></span> Sub Level
<span class="caret"></span> </a>
<div id="dropdown-lvl2" class="panel-collapse collapse">
<div class="panel-body">
<ul class="nav navbar-nav">
<li><a href="#">Link</a></li>
<li><a href="#">Link</a></li>
<li><a href="#">Link</a></li>
</ul>
</div>
</div>
</li>
</ul>
</div>
</div>
</li>
<li><a href="#"><span
class="glyphicon glyphicon-signal"></span> Link</a></li>
</ul>
</div><!-- /.navbar-collapse -->
</nav>
</div>
</div>
</div>

View File

@ -0,0 +1,15 @@
{{#unless session.isAuthenticated}}
<div class="alert alert-info">
You can {{#link-to 'login' classNames='alert-link'}}log in{{/link-to}} with login <code>m@g.com</code> and password <code>password</code>.
</div>
{{/unless}}
<div class="jumbotron">
<div class="container" style="background: linear-gradient(-226deg, rgba(142, 130, 236, 0.8) 0%, rgba(8, 81, 152, 0.92) 100%),url('images/skyview.jpg');background-size:100%;">
<span class="colour-bg">
<h1>Welcome to OBrand</h1>
<p>Det är ett välkänt faktum att läsare distraheras av läsbar text på en sida när man skall studera layouten. Poängen med Lorem Ipsum är att det ger ett normalt ordflöde, till skillnad från "Text här, Text här", och ger intryck av att vara läsbar text. Många publiseringprogram och webbutvecklare använder Lorem Ipsum som test-text, och en sökning efter "Lorem Ipsum" avslöjar många webbsidor under uteckling. Olika versioner har dykt upp under åren, ibland av olyckshändelse, ibland med flit (mer eller mindre humoristiska).</p>
</span>
</div>
</div>

View File

@ -0,0 +1,40 @@
<form class="form-signin" {{action 'authenticate' on='submit'}}>
<div>
<h2 class="form-signin-heading">Please login</h2>
<label for="inputEmail" class="sr-only">Email address</label>
{{input type='email' required="required" autofocus="autofocus" id='inputEmail' placeholder='Email address' value=identification class="form-control" }}
<label for="inputPassword" class="sr-only">Password</label>
{{input id='inputPassword' placeholder='Password' type='password' value=password class="form-control" required="required"}}
<div class="checkbox">
<label>
<input type="checkbox" value="remember-me"> Remember me
</label>
</div>
<button type='submit' class="btn btn-lg btn-primary btn-block">Login</button>
</div>
{{#if errorMessage}}
<div class="alert alert-danger" role="alert">{{errorMessage}}</div>
<div class="alert alert-info">
If you don't have an account, click <strong>SIGN UP</strong> and create one now.
</div>
{{/if}}
</form>
<!--
<h2 class="form-signin-heading">Please login</h2>
<label for="inputEmail" class="sr-only">Email address</label>
<input type="email" id="inputEmail" class="form-control" placeholder="Email address" required autofocus>
<label for="inputPassword" class="sr-only">Password</label>
<input type="password" id="inputPassword" class="form-control" placeholder="Password" required>
<div class="checkbox">
<label>
<input type="checkbox" value="remember-me"> Remember me
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit"></button>
-->

View File

@ -0,0 +1,62 @@
<!--<div class="container profileCard">-->
<div class="container profileCard">
<form {{action "saveCompany" on='submit'}} class="form-horizontal">
<div class="form-group">
<label for="company_name" class="col-sm-2 control-label">Company name:</label>
<div class="col-sm-10">
{{input id='company_name' placeholder='Company name' valueBinding=model.company_name class="form-control" required="required"}}
</div>
</div>
<br/>
<div class="form-group">
<label for="address1" class="col-sm-2 control-label">Address:</label>
<div class="col-sm-10">
{{input id='address1' placeholder='Address' valueBinding=model.address1 class="form-control" required="required"}}
{{input id='address2' placeholder='Address' valueBinding=model.address2 class="form-control" }}
{{input id='address3' placeholder='Address' valueBinding=model.address3 class="form-control" }}
</div>
</div>
<br/>
<div class="form-group">
<label for="town" class="col-sm-2 control-label">Town:</label>
<div class="col-sm-10">
{{input id='town' placeholder='Town' valueBinding=model.town class="form-control" required="required"}}
</div>
<label for="county" class="col-sm-2 control-label">County:</label>
<div class="col-sm-10">
{{input id='county' placeholder='County' valueBinding=model.county class="form-control" }}
</div>
<label for="postcode" class="col-sm-2 control-label">Postcode:</label>
<div class="col-sm-10">
{{input id='postcode' placeholder='Postcode' valueBinding=model.postcode class="form-control" required="required"}}
</div>
</div>
<br/>
<div class="form-group">
<label for="pcontact" class="col-sm-2 control-label">Primary Contact:</label>
<div class="col-sm-10">
{{input id='pcontact' placeholder='Primary contact number' valueBinding=model.pcontact class="form-control" required="required"}}
</div>
<label for="ocontact" class="col-sm-2 control-label">Other Contact:</label>
<div class="col-sm-10">
{{input id='ocontact' placeholder='Other contact phone number' valueBinding=model.ocontact class="form-control" }}
</div>
<label for="mobile" class="col-sm-2 control-label">Mobile:</label>
<div class="col-sm-10">
{{input id='mobile' placeholder='Mobile phone' valueBinding=model.mobile class="form-control" }}
</div>
</div>
<br/>
<div class="form-group">
<label for="email" class="col-sm-2 control-label">Email:</label>
<div class="col-sm-10">
{{input id='email' placeholder='Contact email address' valueBinding=model.email class="form-control" required="required"}}
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">Save</button>
</div>
</div>
</form>
</div>

View File

@ -0,0 +1,47 @@
<div class="container-fluid main-container">
<div class="col-md-12 content">
<div class="card">
<div class="card-header">
New Page
</div>
<div class="card-block">
<div class="row">
<div class="col-md-4 content">
<form {{action "savePage" on='submit'}}>
<div class="col-md-12 form-inline">
<label for="title">Title:</label>
{{input id='title' placeholder='title' value=model.content.title class="form-control" required="required"}}
</div>
<div class="col-md-12 form-inline">
<div>Link One</div>
<label for="link1title">Text:</label>
{{input id='link1title' placeholder='Text' value=model.content.link1Text class="form-control"}}
<label for="link1url">URL:</label>
{{input id='link1url' placeholder='http://something.com/link' value=model.content.link1Url class="form-control"}}
</div>
</form>
</div>
<div class="col-md-8 content">
<div id="fakeDevice" class="fakeDevice">
<h1 class="text-xs-center">{{ model.content.title }}</h1>
<img src="http://pipes.silvrtree.co.uk/assets/fm.png"
class="center-block"/>
<ul class="list-group">
{{#if model.content.link1Url }}
<li class="list-group-item">{{#link-to model.content.link1Url}}{{model.content.link1Text}}{{/link-to}}</li>
{{/if}}
<li class="list-group-item">List item 2</li>
<li class="list-group-item">List item 3</li>
<li class="list-group-item">List item 4</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,143 @@
<div class="container profileCard">
<form {{action "saveProfile" on='submit'}}>
<div class="row">
<div class="col-md-*">
<div class="panel panel-default">
<div class="panel-body">
<div class="row">
<div class="col-md-12 lead">User profile
<hr>
</div>
</div>
<div class="row">
<div class="col-md-4 text-center">
<!--<img class="img-circle avatar avatar-original"
style="-webkit-user-select:none;
display:block; margin:auto;"
src="http://robohash.org/sitsequiquia.png?size=120x120">-->
{{gravatar-image email=sessionAccount.account.login size=120 class="img-circle avatar avatar-original pull-right" defaultImage='identicon'}}
</div>
<div class="col-md-8">
<div class="row">
<div class="col-md-12 form-inline">
{{#if isEditing}}
<label for="forename">Forename:</label>
{{input id='forename' placeholder='Forename' value=model.forename class="form-control" required="required"}}
<label for="surname">Surname:</label>
{{input id='surname' placeholder='Surname' value=model.surname class="form-control" required="required"}}
{{else}}
<h1 class="only-bottom-margin">{{model.fullName}}</h1>
{{/if}}
</div>
</div>
<div class="row">
<div class="col-md-6">
<div>
<span
class="text-muted">Email:</span> {{sessionAccount.account.login}}
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<!-- Start dob -->
{{#if isEditing}}
<div class="form-group form-inline">
<label for="dob">Birth date:</label>
{{input id='dob' type='date' value=model.dob class="form-control" required="required"}}
</div>
{{else}}
<div><span class="text-muted">Birth date:</span>
{{moment-format model.dob 'MMM Do \'YY'}}
</div>
{{/if}}
<!-- End dob -->
</div>
</div>
<!-- Start Gender -->
<div class="row">
<div class="col-md-6">
<div>
{{#if isEditing}}
<div class="form-group form-inline">
<label for="gender">Gender:</label> <select
value={{model.gender}} class="form-control">
{{#each genders as |gender|}}
<option
value={{gender.id}} selected={{eq model.gender gender.id}} >{{gender.g}}</option>
{{/each}}
</select>
</div>
{{else}}
<div><span
class="text-muted">Gender:</span> {{model.qualifiedGender}}
</div>
{{/if}}
</div>
</div>
<!-- End Gender --><br><br>
</div>
<div class="row">
<div class="col-lg-9">
<div>
{{#if isEditing}}
<div class="form-group">
<!--<label for="bio">Bio:</label> <textarea id="bio" value=model.bio
class="form-control">{{model.bio}}</textarea>-->
{{textarea id=bio value=model.bio class="form-control"}}
</div>
{{else}}
<div>
<small class="text-muted">{{model.bio}}</small>
</div>
{{/if}}
</div>
</div>
</div>
</div>
<!--<div class="col-md-6">
<div class="activity-mini">
<i class="glyphicon glyphicon-comment text-muted"></i> 500
</div>
<div class="activity-mini">
<i class="glyphicon glyphicon-thumbs-up text-muted"></i> 1500
</div>
</div>-->
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<hr>
<button class="btn btn-default pull-right" {{action "editProfile"}}>
<i class="glyphicon glyphicon-pencil"></i> Edit
</button>
&nbsp;
{{#if isEditing}}
<button class="btn btn-primary pull-right" type="submit">
<i class="glyphicon glyphicon-pencil"></i> Save
</button>
{{/if}}
</div>
</div>
<div>
{{#if isEditing}}
<p>EDITING MODE!!!</p>
{{/if}}
</div>
</div>
</div>
</form>
</div>
<div></div>

View File

@ -0,0 +1 @@
{{outlet}}

View File

@ -0,0 +1 @@
{{outlet}}

View File

@ -0,0 +1,13 @@
{
"name": "obrand-admin",
"dependencies": {
"ember": "~2.4.1",
"ember-cli-shims": "0.1.0",
"ember-cli-test-loader": "0.2.2",
"ember-qunit-notifications": "0.1.0",
"tether": "^1.2.0",
"lodash": "~3.7.0",
"JavaScript-MD5": "^2.3.0",
"blueimp-md5": "2.1.0"
}
}

View File

@ -0,0 +1,52 @@
/* jshint node: true */
module.exports = function(environment) {
var ENV = {
modulePrefix: 'obrand-admin',
environment: environment,
baseURL: '/',
locationType: 'auto',
EmberENV: {
FEATURES: {
// Here you can enable experimental features on an ember canary build
// e.g. 'with-controller': true
}
},
APP: {
// Here you can pass flags/options to your application instance
// when it is created
},
contentSecurityPolicy: {
'style-src': "'self' 'unsafe-inline'",
'img-src':"'self' www.gravatar.com"
}
};
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 = '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') {
}
return ENV;
};

View File

@ -0,0 +1,25 @@
/*jshint node:true*/
/* global require, module */
var EmberApp = require('ember-cli/lib/broccoli/ember-app');
module.exports = function(defaults) {
var app = new EmberApp(defaults, {
// Add options here
});
app.import('bower_components/blueimp-md5/js/md5.js');
// 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.
return app.toTree();
};

View File

@ -0,0 +1,65 @@
{
"name": "obrand-admin",
"version": "0.0.0",
"description": "Small description for obrand-admin goes here",
"private": true,
"directories": {
"doc": "doc",
"test": "tests"
},
"scripts": {
"build": "ember build",
"start": "ember server",
"test": "ember test"
},
"repository": "",
"engines": {
"node": ">= 0.10.0"
},
"author": "",
"license": "MIT",
"devDependencies": {
"bcrypt-as-promised": "^1.1.0",
"body-parser": "^1.15.0",
"broccoli-asset-rev": "^2.2.0",
"ember-ajax": "0.7.1",
"ember-bootstrap-4": "0.1.0",
"ember-cli": "2.4.1",
"ember-cli-app-version": "^1.0.0",
"ember-cli-babel": "^5.1.5",
"ember-cli-dependency-checker": "^1.2.0",
"ember-cli-gravatar": "3.5.0",
"ember-cli-htmlbars": "^1.0.1",
"ember-cli-htmlbars-inline-precompile": "^0.3.1",
"ember-cli-inject-live-reload": "^1.3.1",
"ember-cli-md5": "^0.1.0",
"ember-cli-moment-shim": "1.1.0",
"ember-cli-qunit": "^1.2.1",
"ember-cli-release": "0.2.8",
"ember-cli-sass": "5.3.0",
"ember-cli-sri": "^2.1.0",
"ember-cli-uglify": "^1.2.0",
"ember-data": "^2.4.0",
"ember-disable-proxy-controllers": "^1.0.1",
"ember-export-application-global": "^1.0.4",
"ember-inflector": "^1.9.4",
"ember-load-initializers": "^0.5.0",
"ember-moment": "6.0.0",
"ember-resolver": "^2.0.3",
"ember-simple-auth": "1.1.0-beta.3",
"event": "^1.0.0",
"events": "^1.1.0",
"express": "^4.13.4",
"glob": "^4.5.3",
"loader.js": "^4.0.0",
"morgan": "^1.7.0",
"node-validator": "git+http://gitlab.silvrtree.co.uk/martind2000/node-validator.git",
"md-utils": "git+http://gitlab.silvrtree.co.uk/martind2000/md-utils.git",
"oauth2-server": "^2.4.1",
"pg-promise": "^3.3.0"
},
"dependencies": {
"bcrypt": "^0.8.5",
"pg": "^4.5.1"
}
}

View File

@ -0,0 +1,15 @@
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<!-- Read this: www.adobe.com/devnet/articles/crossdomain_policy_file_spec.html -->
<!-- Most restrictive policy: -->
<site-control permitted-cross-domain-policies="none"/>
<!-- Least restrictive policy: -->
<!--
<site-control permitted-cross-domain-policies="all"/>
<allow-access-from domain="*" to-ports="*" secure="false"/>
<allow-http-request-headers-from domain="*" headers="*" secure="false"/>
-->
</cross-domain-policy>

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 KiB

View File

@ -0,0 +1,3 @@
# http://www.robotstxt.org
User-agent: *
Disallow:

View File

@ -0,0 +1,3 @@
{
"node": true
}

View File

@ -0,0 +1,24 @@
/*jshint node:true*/
// To use it create some files under `mocks/`
// e.g. `server/mocks/ember-hamsters.js`
//
// module.exports = function(app) {
// app.get('/ember-hamsters', function(req, res) {
// res.send('hello');
// });
// };
module.exports = function(app) {
var globSync = require('glob').sync;
var mocks = globSync('./mocks/**/*.js', { cwd: __dirname }).map(require);
var proxies = globSync('./proxies/**/*.js', { cwd: __dirname }).map(require);
// Log proxy requests
var morgan = require('morgan');
app.use(morgan('dev'));
mocks.forEach(function(route) { route(app); });
proxies.forEach(function(route) { route(app); });
};

View File

@ -0,0 +1,35 @@
'use strict';
var db = require('../units/db-connector').dbConnection;
var dbAccounts = require('../units/db-accounts')(db);
module.exports = function(app) {
var express = require('express');
var accountsRouter = express.Router();
accountsRouter.get('/:uid', function(req, res) {
if (/Bearer .+/.test(req.headers.authorization)) {
dbAccounts.sqlGetAccountDetails(req.params.uid)
.then(function(data) {
'use strict';
const response = {
data: {
type: 'accounts', id: data.uid, attributes: {
uid: data.uid, login: data.email, forename: data.forename,
surname: data.surname, memberof: data.member_of
}
}
};
console.log(response);
res.status(200).send(response);
})
.catch(function(err) {
console.error(err);
res.status(401).end();
});
}
});
app.use('/accounts', accountsRouter);
};

View File

@ -0,0 +1,86 @@
/*jshint node:true*/
'use strict';
var db = require('../units/db-connector').dbConnection;
var dbCompany = require('../units/db-company')(db);
var $U = require('md-utils');
module.exports = function(app) {
var express = require('express');
var companiesRouter = express.Router();
companiesRouter.get('/:id', function(req, res) {
var id = req.params.id;
dbCompany.sqlGetSimpleCompany(id)
.then(function(data) {
const response = {
data: {
type: 'company', id: id, attributes: $U.reDashObject(data)
}
};
console.log(response);
res.status(200).send(response);
})
.catch(function(err) {
console.error(err);
res.status(401).end();
});
});
companiesRouter.post('/', function(req, res) {
res.status(201).end();
});
companiesRouter.get('/:id', function(req, res) {
res.send({
companies: {
id: req.params.id
}
});
});
companiesRouter.patch('/:id', function(req, res) {
if (/Bearer .+/.test(req.headers.authorization)) {
console.log('Patching: ' + req.params.id);
console.log(req.body.data);
var updateData = $U.unDashObject(req.body.data.attributes);
dbCompany.addNewCompany(updateData)
.then(function(d) {
let response = {
data: {
type: 'company', id: d.cid, attributes: d
}
};
res.status(200).send(response);
})
.catch(function(e) {
console.error(e);
res.status(401).end();
});
}
});
companiesRouter.delete('/:id', function(req, res) {
res.status(204).end();
});
// The POST and PUT call will not contain a request body
// because the body-parser is not included by default.
// To use req.body, run:
// Npm install --save-dev body-parser
app.use('/api/companies', require('body-parser').json({type: 'application/vnd.api+json'}));
// After installing, you need to `use` the body-parser for
// this mock uncommenting the following line:
//
//App.use('/api/companies', require('body-parser').json());
app.use('/api/companies', companiesRouter);
};

View File

@ -0,0 +1,83 @@
/*jshint node:true*/
'use strict';
var db = require('../units/db-connector').dbConnection;
var dbCompany = require('../units/db-company')(db);
var dbAccounts = require('../units/db-accounts')(db);
var $U = require('md-utils');
var events = require('events');
// Create an eventEmitter object
var eventEmitter = new events.EventEmitter();
module.exports = function(app) {
var express = require('express');
var newcompaniesRouter = express.Router();
eventEmitter.on('makeMemberOf', (uid, cid) => {
console.log('Make ' + uid + ' a member of ' + cid);
dbAccounts.makeMemberOf(uid, cid)
.catch(function(err) {
console.error(err);
});
});
newcompaniesRouter.get('/', function(req, res) {
res.send({
newcompanies: []
});
});
newcompaniesRouter.post('/', function(req, res) {
var updateData = $U.unDashObject(req.body.data.attributes);
if (/Bearer .+/.test(req.headers.authorization)) {
dbCompany.addNewCompany(updateData)
.then(function(d) {
updateData.cid = d.cid;
let response = {
data: {
type: 'newcompany', id: d.cid, attributes: updateData
}
};
eventEmitter.emit('makeMemberOf', updateData.uid, d.cid);
res.status(200).send(response);
})
.catch(function(e) {
console.error(e);
res.status(401).end();
});
}
});
newcompaniesRouter.get('/:id', function(req, res) {
res.send({
newcompanies: {
id: req.params.id
}
});
});
newcompaniesRouter.put('/:id', function(req, res) {
res.send({
newcompanies: {
id: req.params.id
}
});
});
newcompaniesRouter.delete('/:id', function(req, res) {
res.status(204).end();
});
// The POST and PUT call will not contain a request body
// because the body-parser is not included by default.
// To use req.body, run:
// Npm install --save-dev body-parser
app.use('/api/newcompanies', require('body-parser').json({type: 'application/vnd.api+json'}));
// After installing, you need to `use` the body-parser for
// this mock uncommenting the following line:
app.use('/api/newcompanies', newcompaniesRouter);
};

View File

@ -0,0 +1,113 @@
/*jshint node:true*/
'use strict';
var db = require('../units/db-connector').dbConnection;
var dbAccounts = require('../units/db-accounts')(db);
module.exports = function(app) {
var express = require('express');
var profilesRouter = express.Router();
var moment = require('moment');
profilesRouter.get('/:uid', function(req, res) {
if (/Bearer .+/.test(req.headers.authorization)) {
dbAccounts.sqlGetProfile(req.params.uid)
.then(function(data) {
let response = {data: {}};
if (data === null) {
// No record yet, return an empty one.
response.data = {
type: 'profile', id: req.params.uid, attributes: {
forename: '', surname: '', gender: 0, dob: '', bio: ''
}};
} else {
response.data = {
type: 'profile', id: data.uid, attributes: {
forename: data.forename,
surname: data.surname,
gender: data.gender,
dob: moment(data.dob).format('YYYY-MM-DD'),
bio: data.bio
}
};
}
res.status(200).send(response);
})
.catch(function(e) {
'use strict';
console.error(e);
res.status(401).end();
});
};
});
profilesRouter.post('/', function(req, res) {
res.status(201).end();
});
profilesRouter.get('/:id', function(req, res) {
res.send({
profiles: {
id: req.params.id
}
});
});
profilesRouter.put('/:id', function(req, res) {
res.send({
profiles: {
id: req.params.id
}
});
});
profilesRouter.patch('/:id', function(req, res) {
var data = req.body.data;
var attr = data.attributes;
var updateData = {
uid: data.id,
forename: attr.forename,
surname: attr.surname,
gender: attr.gender,
dob: attr.dob,
bio: attr.bio
};
dbAccounts.addInsertProfile(updateData)
.then(function() {
let response = {
data: {
type: 'profile', id: req.params.id, attributes: data.attributes
}
};
res.status(200).send(response);
})
.catch(function(err) {
'use strict';
console.error(err);
res.status(401).end();
});
});
profilesRouter.delete('/:id', function(req, res) {
res.status(204).end();
});
// The POST and PUT call will not contain a request body
// because the body-parser is not included by default.
// To use req.body, run:
// Npm install --save-dev body-parser
// After installing, you need to `use` the body-parser for
// this mock uncommenting the following line:
//
//App.use('/api/profiles', require('body-parser').json());
app.use('/api/profiles', require('body-parser').json());
app.use('/api/profiles',
require('body-parser').json({type: 'application/vnd.api+json'}));
app.use('/api/profiles', profilesRouter);
};

View File

@ -0,0 +1,84 @@
/*jshint node:true*/
'use strict';
var db = require('../units/db-connector').dbConnection;
var dbAccounts = require('../units/db-accounts')(db);
module.exports = function(app) {
var express = require('express');
var tokenRouter = express.Router();
tokenRouter.get('/', function(req, res) {
res.send({
token: []
});
});
tokenRouter.post('/', function(req, res) {
if (req.body.hasOwnProperty('grant_type')) {
if (req.body.grant_type === 'password') {
dbAccounts.findAccount({
email: req.body.username,
password: req.body.password
})
.then(function(d) {
let loginObj = {
access_token: 'secret token!',
account_id: d.uid,
username: d.username,
account: d.email
};
// Res.status(200).send('{ "access_token": "secret token!", "account_id": d.id }');
res.status(200).send(loginObj);
})
.catch(function(err) {
res.status(400).send(
'{ "error": "No account could be found with those details" }');
});
} else {
res.status(400).send(
'{ "error": "No account could be found with those details" }');
}
} else {
res.status(400).send(
'{ "error": "No account could be found with those details" }');
}
});
tokenRouter.get('/:id', function(req, res) {
res.send({
token: {
id: req.params.id
}
});
});
tokenRouter.put('/:id', function(req, res) {
res.send({
token: {
id: req.params.id
}
});
});
tokenRouter.delete('/:id', function(req, res) {
res.status(204).end();
});
// The POST and PUT call will not contain a request body
// because the body-parser is not included by default.
// To use req.body, run:
// Npm install --save-dev body-parser
// After installing, you need to `use` the body-parser for
// this mock uncommenting the following line:
//
app.use('/token', require('body-parser').json());
app.use('/token', require('body-parser').text());
app.use('/token', require('body-parser').urlencoded());
app.use('/token', tokenRouter);
};

View File

@ -0,0 +1,204 @@
'use strict';
var mdValidator = require('node-validator');
var mdErrors = require('./md-errors');
var bcrypt = require('bcrypt-as-promised');
var newId = require('uuid-pure').newId;
module.exports = function(db) {
var module = {};
module.connectPGP = function() {
return new Promise(function(resolve, reject) {
db.query('select $1::int as number', [1])
.then((data)=> {
resolve(data);
})
.catch((error)=> {
reject(error);
});
});
};
module.sqlInsertAccount = function(data) {
let _data = data;
_data.uid = newId();
return new Promise(function(resolve, reject) {
db.func('insert_user',
[_data.username, _data.email, _data.hash, _data.uid])
.then(()=> {
return resolve('ok');
})
.catch((err)=> {
return reject(err);
});
});
};
module.sqlGetAccount = function(email) {
return new Promise(function(resolve, reject) {
db.oneOrNone('select * from logins where email=$1;', [email])
.then(function(d) {
return resolve(d);
})
.catch((err)=> {
return reject(err);
});
});
};
module.sqlGetAccountDetails = function(uid) {
return new Promise(function(resolve, reject) {
db.one('select * from getAccountDetails($1);',[uid])
.then(function(d) {
console.log('+ sqlGetAccountDetails');
console.log(d);
return resolve(d);
})
.catch((err)=> {
return reject(err);
});
});
};
module.sqlUpsertProfile = function(data) {
var propArray = [
data.uid,
data.forename,
data.surname,
data.gender,
data.dob,
data.bio
];
return new Promise(function(resolve, reject) {
db.func('upsert_profile', propArray)
.then(()=> {
return resolve(true);
})
.catch((err)=> {
return reject(err);
});
});
};
module.sqlMakeMemberOf = function(cid, uid) {
var propArray = [cid,uid];
return new Promise(function(resolve, reject) {
db.func('makeMemberOf', propArray)
.then(()=> {
return resolve(true);
})
.catch((err)=> {
return reject(err);
});
});
};
module.sqlGetProfile = function(uid) {
return new Promise(function(resolve, reject) {
db.oneOrNone('select * from profile where uid=$1;', [uid])
.then(function(d) {
return resolve(d);
})
.catch((err)=> {
return reject(err);
});
});
};
module.addNewAccount = function(data) {
var self = this;
return new Promise((resolve, reject) => {
let _data = {};
_data.username = data.username.trim();
_data.password = data.password.trim();
_data.email = data.email.trim();
if (Object.keys(data).length === 3) {
if (_data.username.length === 0 || _data.password.length === 0 || _data.email.length === 0) {
return reject(mdErrors.error(1000));
}
if (mdValidator.Email(data.email) === false) {
return reject(mdErrors.error(1001));
} else {
// It should be possible to insert the user now.
bcrypt.hash(data.password,10).then((d) => {
_data.hash = d;
self.sqlInsertAccount(_data)
.then(()=> {
return resolve({reply: 'user added'});
})
.catch((err)=> {
return reject(err);
});
});
}
} else {
// Error - required details missing
return reject(mdErrors.error(1002));
}
});
};
module.findAccount = function(data) {
var _data = data;
return new Promise((resolve, reject) => {
this.sqlGetAccount(_data.email)
.then((row) => {
if (row === null) {
return reject(mdErrors.error(1004));
}
// Check password against hash held in db
// noinspection JSUnresolvedVariable
bcrypt.compare(_data.password, row.password_hash)
.then(function() {
let loginDetails = {
id: row.id,
username: row.username,
email: row.email,
uid: row.uid
};
return resolve(loginDetails);
})
// Failure, reject
.catch(function() {
return reject(mdErrors.error(1004));
});
})
.catch(function(err) {
return reject(err);
});
});
};
module.addInsertProfile = function(data) {
return new Promise((resolve, reject) => {
this.sqlUpsertProfile(data)
.then((d)=> {
return resolve(d);
})
.catch((err)=> {
return reject(err);
});
});
};
//makeMemberOf(cid, uid)
module.makeMemberOf = function(cid, uid) {
return new Promise((resolve, reject) => {
this.sqlMakeMemberOf(cid, uid)
.then((d)=> {
return resolve(d);
})
.catch((err)=> {
return reject(err);
});
});
};
return module;
};

View File

@ -0,0 +1,115 @@
/**
*
* User: Martin Donnelly
* Date: 2016-03-15
* Time: 14:04
*
*/
'use strict';
var $V = require('node-validator');
var mdErrors = require('./md-errors');
var newId = require('uuid-pure').newId;
var $U = require('md-utils');
module.exports = function(db) {
var module = {};
module.sqlInsertCompany = function(data) {
return new Promise(function(resolve, reject) {
db.proc('upsert_company',data)
.then(()=> {
console.log('+sqlInsertCompany OK');
return resolve('ok');
})
.catch((err)=> {
console.log('+sqlInsertCompany failed');
console.log(err);
return reject(err);
});
});
};
module.sqlGetSimpleCompany = function(id) {
return new Promise(function(resolve, reject) {
//db.oneOrNone('select *, company_name company-name from company where cid=$1;', [id])
db.oneOrNone('select company.* from company where cid=$1;', [id])
.then(function(d) {
console.log(d);
return resolve(d);
})
.catch((err)=> {
console.log(err);
return reject(err);
});
});
};
module.addNewCompany = function(data) {
return new Promise((resolve, reject) => {
let _data;
_data = $U.cloneTrim(data);
_data = $U.sanitiseObj(_data,
{company_name: true, address1: true, address2: true, address3: true,
town: false, county: false, pcontact: true, ocontact: true,mobile: true});
if (_data.hasOwnProperty('company_name') && (_data.company_name.length === 0)) {
return reject(mdErrors.error(1100));
}
if ([
_data.address1, _data.address2, _data.address3
].join('').trim().length === 0) {
return reject(mdErrors.error(1101));
}
if ([_data.town, _data.county].join('').trim().length === 0) {
return reject(mdErrors.error(1102));
}
var pcv = $V.checkPostCode(_data.postcode);
if (pcv === '') {
return reject(mdErrors.error(1103));
} else {
_data.postcode = pcv;
}
_data.pcontact = $V.validatePhone(_data.pcontact);
_data.ocontact = $V.validatePhone(_data.ocontact);
_data.mobile = $V.validatePhone(_data.mobile);
if ([
_data.pcontact, _data.ocontact, _data.mobile
].join('').trim().length === 0) {
return reject(mdErrors.error(1104));
}
if (_data.email.length === 0 || !$V.Email(_data.email)) {
return reject(mdErrors.error(1105));
}
if (typeof _data.cid === 'undefined' || _data.cid === null) {
_data.cid = newId();
}
const sqlData = [_data.cid, _data.company_name, _data.address1, _data.address2,
_data.address3, _data.town, _data.county, _data.postcode, _data.country, _data.pcontact,
_data.ocontact, _data.mobile, _data.email];
this.sqlInsertCompany(sqlData)
.then(function(d) {
console.log('Inserted');
console.log(d);
return resolve({cid: _data.cid});
})
.catch(function(err) {
console.log('Failed to insert');
return reject(err);
});
});
};
return module;
};

View File

@ -0,0 +1,21 @@
'uses strict';
/**
*
* User: Martin Donnelly
* Date: 2016-03-11
* Time: 10:22
*
*/
var pgp = require('pg-promise')();
var cn = {
host: 'localhost',
port: 5432,
database: 'oBrand',
user: 'obrand',
password: 'obrand'
};
exports.dbConnection = pgp(cn);

View File

@ -0,0 +1,38 @@
/**
*
* User: Martin Donnelly
* Date: 2016-03-10
* Time: 11:31
*
*/
var logger = require('log4js').getLogger();
var MDERRORS = new function() {
'use strict';
var errors = {
1000: {name: 'Account error', title: 'Signup data missing'},
1001: {name: 'Account error', title: 'Email address is not in the correct format'},
1002: {name: 'Account error', title: 'Required details missing'},
1003: {name: 'Account error', title: 'Email does not exist in login table'},
1004: {name: 'Account error', title: 'Email address or password are incorrect'},
1100: {name: 'Company Error', title: 'Company name is missing'},
1101: {name: 'Company Error', title: 'Address details are missing'},
1102: {name: 'Company Error', title: 'Town/County details are missing'},
1103: {name: 'Company Error', title: 'Postcode is missing / incorrect'},
1104: {name: 'Company Error', title: 'Contact phone number is missing'},
1105: {name: 'Company Error', title: 'Email is missing / invalid'}
};
this.error = function(code) {
var estring = '';
estring = errors[code].name + ': ' + errors[code].title + '\nCode: ' + code + '\n';
logger.error(estring);
return ({code: code, name: errors[code].name, title: errors[code].title, string: estring});
};
}();
module.exports = MDERRORS;

View File

@ -0,0 +1,13 @@
/*jshint node:true*/
module.exports = {
"framework": "qunit",
"test_page": "tests/index.html?hidepassed",
"disable_watching": true,
"launch_in_ci": [
"PhantomJS"
],
"launch_in_dev": [
"PhantomJS",
"Chrome"
]
};

View File

@ -0,0 +1,53 @@
{
"predef": [
"server",
"document",
"window",
"location",
"setTimeout",
"$",
"-Promise",
"define",
"console",
"visit",
"exists",
"fillIn",
"click",
"keyEvent",
"triggerEvent",
"find",
"findWithAssert",
"wait",
"DS",
"andThen",
"currentURL",
"currentPath",
"currentRouteName"
],
"node": false,
"browser": false,
"boss": true,
"curly": true,
"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,
"unused": true
}

View File

@ -0,0 +1,5 @@
import Ember from 'ember';
export default function destroyApp(application) {
Ember.run(application, 'destroy');
}

View File

@ -0,0 +1,23 @@
import { module } from 'qunit';
import startApp from '../helpers/start-app';
import destroyApp from '../helpers/destroy-app';
export default function(name, options = {}) {
module(name, {
beforeEach() {
this.application = startApp();
if (options.beforeEach) {
options.beforeEach.apply(this, arguments);
}
},
afterEach() {
if (options.afterEach) {
options.afterEach.apply(this, arguments);
}
destroyApp(this.application);
}
});
}

View File

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

View File

@ -0,0 +1,18 @@
import Ember from 'ember';
import Application from '../../app';
import config from '../../config/environment';
export default function startApp(attrs) {
let application;
let attributes = Ember.merge({}, config.APP);
attributes = Ember.merge(attributes, attrs); // use defaults, but you can override;
Ember.run(() => {
application = Application.create(attributes);
application.setupForTesting();
application.injectTestHelpers();
});
return application;
}

View File

@ -0,0 +1,34 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>ObrandAdmin 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/obrand-admin.css">
<link rel="stylesheet" href="assets/test-support.css">
{{content-for "head-footer"}}
{{content-for "test-head-footer"}}
</head>
<body>
{{content-for "body"}}
{{content-for "test-body"}}
<script src="testem.js" integrity=""></script>
<script src="assets/vendor.js"></script>
<script src="assets/test-support.js"></script>
<script src="assets/obrand-admin.js"></script>
<script src="assets/tests.js"></script>
<script src="assets/test-loader.js"></script>
{{content-for "body-footer"}}
{{content-for "test-body-footer"}}
</body>
</html>

View File

@ -0,0 +1,24 @@
import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
moduleForComponent('nav-bar', 'Integration | Component | nav bar', {
integration: true
});
test('it renders', function(assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.on('myAction', function(val) { ... });
this.render(hbs`{{nav-bar}}`);
assert.notEqual(this.$().text().trim(), '');
// Template block usage:
/* this.render(hbs`
{{#nav-bar}}
template block text
{{/nav-bar}}
`);
assert.equal(this.$().text().trim(), 'template block text');*/
});

View File

@ -0,0 +1,24 @@
import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
moduleForComponent('page-manager', 'Integration | Component | page manager', {
integration: true
});
test('it renders', function(assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.on('myAction', function(val) { ... });
this.render(hbs`{{page-manager}}`);
assert.equal(this.$().text().trim(), '');
// Template block usage:
this.render(hbs`
{{#page-manager}}
template block text
{{/page-manager}}
`);
assert.equal(this.$().text().trim(), 'template block text');
});

Some files were not shown because too many files have changed in this diff Show More