├── frontend ├── app │ ├── .buildignore │ ├── robots.txt │ ├── views │ │ ├── 404.html │ │ ├── partials │ │ │ ├── admin │ │ │ │ ├── taxons │ │ │ │ │ └── taxons.list.html │ │ │ │ ├── users │ │ │ │ │ ├── home.html │ │ │ │ │ ├── layout.html │ │ │ │ │ └── users.edit.html │ │ │ │ ├── orders │ │ │ │ │ ├── layout.html │ │ │ │ │ └── orders.state_changes.html │ │ │ │ ├── layout.html │ │ │ │ ├── assets │ │ │ │ │ └── layout.html │ │ │ │ ├── variants │ │ │ │ │ └── layout.html │ │ │ │ ├── forums │ │ │ │ │ ├── forums.new.html │ │ │ │ │ ├── forums.edit.html │ │ │ │ │ └── layout.html │ │ │ │ ├── products │ │ │ │ │ └── layout.html │ │ │ │ ├── supports │ │ │ │ │ └── tickets.edit.html │ │ │ │ ├── shipping_methods │ │ │ │ │ └── shipping_methods.edit.html │ │ │ │ ├── payment_methods │ │ │ │ │ └── payment_methods.edit.html │ │ │ │ └── taxonomies │ │ │ │ │ └── taxonomies.list.html │ │ │ ├── include │ │ │ │ ├── footer.html │ │ │ │ ├── taxonTree.html │ │ │ │ ├── input_file.html │ │ │ │ ├── idle_dialog.html │ │ │ │ └── upload.html │ │ │ ├── forums │ │ │ │ └── topics │ │ │ │ │ ├── layout.html │ │ │ │ │ ├── topics.edit.html │ │ │ │ │ └── topics.new.html │ │ │ ├── products │ │ │ │ ├── layout.html │ │ │ │ └── products.list.html │ │ │ ├── orders │ │ │ │ ├── orders.payment.html │ │ │ │ ├── orders.delivery.html │ │ │ │ ├── layout.html │ │ │ │ └── orders.list.html │ │ │ ├── resetPasswordMail.html │ │ │ ├── supports │ │ │ │ ├── tickets.edit.html │ │ │ │ └── tickets.new.html │ │ │ ├── taxons │ │ │ │ └── taxons.products.html │ │ │ ├── news │ │ │ │ ├── news.new.html │ │ │ │ ├── news.edit.html │ │ │ │ └── news.view.html │ │ │ └── login.html │ │ ├── user.html │ │ └── main.html │ ├── favicon.ico │ ├── images │ │ ├── yeoman.png │ │ ├── nodesoft-logo-253x30.png │ │ └── nodesoft-skyblue-212.png │ ├── i18n │ │ ├── kr │ │ │ ├── error.json │ │ │ └── language.json │ │ └── en │ │ │ ├── error.json │ │ │ └── language.json │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.ttf │ │ └── glyphicons-halflings-regular.woff │ └── scripts │ │ ├── translations.js │ │ ├── common │ │ ├── utils.js │ │ ├── settings.js │ │ └── tree.js │ │ ├── services │ │ ├── mailfactory.js │ │ ├── redirects.js │ │ ├── rolefactory.js │ │ ├── userfactory.js │ │ ├── payments.js │ │ ├── languages.js │ │ ├── rememberfactory.js │ │ ├── sessionfactory.js │ │ ├── articles.js │ │ └── profiles.js │ │ ├── directives │ │ ├── input.js │ │ ├── servererror.js │ │ ├── ngconfirmclick.js │ │ ├── jqdatepicker.js │ │ ├── file_upload.js │ │ ├── passwordmatch.js │ │ ├── activenav.js │ │ ├── accesslevel.js │ │ ├── markdowneditor.js │ │ └── onfocus.js │ │ ├── controllers │ │ ├── language.js │ │ ├── navbar.js │ │ ├── payment.js │ │ ├── delivery.js │ │ ├── address.js │ │ ├── user.js │ │ ├── forum.js │ │ ├── cart.js │ │ ├── signup.js │ │ ├── password.js │ │ ├── product.js │ │ ├── login.js │ │ └── taxon_tree.js │ │ └── filters │ │ └── todate.js ├── .gitattributes ├── .bowerrc ├── .gitignore ├── .travis.yml ├── test │ ├── runner.html │ ├── spec │ │ ├── services │ │ │ ├── assets.js │ │ │ ├── forums.js │ │ │ ├── orders.js │ │ │ ├── taxons.js │ │ │ ├── topics.js │ │ │ ├── tickets.js │ │ │ ├── articles.js │ │ │ ├── payments.js │ │ │ ├── products.js │ │ │ ├── profiles.js │ │ │ ├── variants.js │ │ │ ├── languages.js │ │ │ ├── redirects.js │ │ │ ├── shipments.js │ │ │ ├── taxonomies.js │ │ │ ├── mailfactory.js │ │ │ ├── optiontypes.js │ │ │ ├── rolefactory.js │ │ │ ├── userfactory.js │ │ │ ├── optionvalues.js │ │ │ ├── payment_methods.js │ │ │ ├── rememberfactory.js │ │ │ ├── shipment_methods.js │ │ │ └── sessionfactory.js │ │ ├── filters │ │ │ └── todate.js │ │ ├── directives │ │ │ ├── input.js │ │ │ ├── onfocus.js │ │ │ ├── activenav.js │ │ │ ├── accesslevel.js │ │ │ ├── file_upload.js │ │ │ ├── servererror.js │ │ │ ├── jqdatepicker.js │ │ │ ├── passwordcheck.js │ │ │ ├── markdowneditor.js │ │ │ └── ngconfirmclick.js │ │ └── controllers │ │ │ ├── cart.js │ │ │ ├── mail.js │ │ │ ├── main.js │ │ │ ├── news.js │ │ │ ├── user.js │ │ │ ├── forum.js │ │ │ ├── login.js │ │ │ ├── order.js │ │ │ ├── topic.js │ │ │ ├── events.js │ │ │ ├── navbar.js │ │ │ ├── upload.js │ │ │ ├── address.js │ │ │ ├── payment.js │ │ │ ├── product.js │ │ │ ├── profile.js │ │ │ ├── support.js │ │ │ ├── delivery.js │ │ │ ├── language.js │ │ │ ├── password.js │ │ │ ├── admin │ │ │ ├── user.js │ │ │ ├── asset.js │ │ │ ├── forum.js │ │ │ ├── order.js │ │ │ ├── product.js │ │ │ ├── support.js │ │ │ ├── variant.js │ │ │ ├── taxonomy.js │ │ │ ├── optiontype.js │ │ │ ├── payment_method.js │ │ │ └── shipping_method.js │ │ │ └── taxon_tree.js │ └── .jshintrc ├── .jshintrc ├── .editorconfig ├── lang │ ├── template.pot │ └── ko.po ├── package.json ├── bower.json ├── karma-e2e.conf.js ├── karma.conf.js └── README.md ├── backend ├── .gitignore ├── start.sh ├── bin │ ├── forever │ └── www ├── controllers │ ├── auth │ │ └── roles.js │ └── shipments.js ├── template │ └── order_confirm_mail.hogan.html ├── config │ ├── log4js.json │ ├── settings.sample.js │ └── passport.js ├── README.md ├── package.json └── models │ ├── address.js │ ├── payment_method.js │ ├── taxonomy.js │ ├── article.js │ ├── message.js │ ├── state_change.js │ ├── option_type.js │ ├── ticket.js │ ├── payment.js │ ├── profile.js │ ├── option_value.js │ ├── line_item.js │ ├── post.js │ ├── shipping_method.js │ ├── topic.js │ ├── product.js │ ├── shipment.js │ ├── variant.js │ └── role.js ├── .gitignore ├── schema └── schema.sql └── .idea └── encodings.xml /frontend/app/.buildignore: -------------------------------------------------------------------------------- 1 | *.coffee -------------------------------------------------------------------------------- /frontend/.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto -------------------------------------------------------------------------------- /frontend/app/robots.txt: -------------------------------------------------------------------------------- 1 | # robotstxt.org 2 | 3 | User-agent: * 4 | -------------------------------------------------------------------------------- /frontend/.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "app/bower_components" 3 | } 4 | -------------------------------------------------------------------------------- /frontend/app/views/404.html: -------------------------------------------------------------------------------- 1 |

404

2 |

Ain't nothing here

-------------------------------------------------------------------------------- /frontend/app/views/partials/admin/taxons/taxons.list.html: -------------------------------------------------------------------------------- 1 |

Taxons List

2 | -------------------------------------------------------------------------------- /frontend/app/views/partials/admin/users/home.html: -------------------------------------------------------------------------------- 1 |

List of Users

2 |

사용자 계정 조회 및 수정 화면

-------------------------------------------------------------------------------- /backend/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .tmp 4 | .sass-cache 5 | app/bower_components 6 | log 7 | .idea -------------------------------------------------------------------------------- /backend/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | NODE_ENV=production PORT=3000 pm2 start $(dirname "$0")/bin/forever 3 | 4 | -------------------------------------------------------------------------------- /frontend/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usemodj/angularjs-express-mysql/HEAD/frontend/app/favicon.ico -------------------------------------------------------------------------------- /frontend/app/images/yeoman.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usemodj/angularjs-express-mysql/HEAD/frontend/app/images/yeoman.png -------------------------------------------------------------------------------- /frontend/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .tmp 4 | .sass-cache 5 | app/bower_components 6 | log 7 | app/uploads/* 8 | .idea 9 | -------------------------------------------------------------------------------- /frontend/app/i18n/kr/error.json: -------------------------------------------------------------------------------- 1 | { 2 | "errors": { 3 | "title": "에러 페이지!", 4 | "403": "이 페이지에 접근할 권한이 없습니다." 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /frontend/app/images/nodesoft-logo-253x30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usemodj/angularjs-express-mysql/HEAD/frontend/app/images/nodesoft-logo-253x30.png -------------------------------------------------------------------------------- /frontend/app/images/nodesoft-skyblue-212.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usemodj/angularjs-express-mysql/HEAD/frontend/app/images/nodesoft-skyblue-212.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .tmp 4 | .sass-cache 5 | app/bower_components 6 | log 7 | uploads/* 8 | .idea 9 | backend/config/settings.js 10 | -------------------------------------------------------------------------------- /frontend/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '0.8' 4 | - '0.10' 5 | before_script: 6 | - 'npm install -g bower grunt-cli' 7 | - 'bower install' 8 | -------------------------------------------------------------------------------- /frontend/app/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usemodj/angularjs-express-mysql/HEAD/frontend/app/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /frontend/app/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usemodj/angularjs-express-mysql/HEAD/frontend/app/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /frontend/app/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usemodj/angularjs-express-mysql/HEAD/frontend/app/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /frontend/app/i18n/en/error.json: -------------------------------------------------------------------------------- 1 | { 2 | "errors": { 3 | "title": "Error page!", 4 | "403": "You are not authorized to access the page." 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /frontend/app/views/partials/admin/orders/layout.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 | -------------------------------------------------------------------------------- /frontend/app/views/partials/include/footer.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |
6 |
7 |

8 | Nodesoft © 2015. All Rights Reserved. 9 |

10 |
11 |
12 | -------------------------------------------------------------------------------- /frontend/test/runner.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | End2end Test Runner 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /frontend/app/scripts/translations.js: -------------------------------------------------------------------------------- 1 | angular.module('gettext').run(['gettextCatalog', function (gettextCatalog) { 2 | /* jshint -W100 */ 3 | gettextCatalog.setStrings('ko', {"Forums":"포럼","Support":"지원","Login":"로그인","My Order":"내주문","News":"뉴스","Signup":"회원가입"}); 4 | /* jshint +W100 */ 5 | }]); -------------------------------------------------------------------------------- /frontend/app/scripts/common/utils.js: -------------------------------------------------------------------------------- 1 | String.prototype.repeat = function(count) { 2 | if (count < 1) return ''; 3 | var result = '', pattern = this.valueOf(); 4 | while (count > 1) { 5 | if (count & 1) result += pattern; 6 | count >>= 1, pattern += pattern; 7 | } 8 | return result + pattern; 9 | }; -------------------------------------------------------------------------------- /frontend/app/scripts/services/mailfactory.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var services = angular.module('frontendApp'); 4 | services.factory('MailFactory', ['$resource', 5 | function($resource) { 6 | return $resource('/auth/mail/', { },{ 7 | update: { method: 'PUT'} 8 | }); 9 | } 10 | ]); 11 | -------------------------------------------------------------------------------- /frontend/app/scripts/common/settings.js: -------------------------------------------------------------------------------- 1 | var settings = { 2 | markdownEditor: { 3 | language: 'kr' 4 | }, 5 | gettext: { 6 | language: 'ko', 7 | debug: false 8 | }, 9 | resetPasswordUrl: 'http://localhost:3000/#/resetPassword', 10 | resetPasswordFromEmail : 'NodeSoft.co.kr ' 11 | }; 12 | -------------------------------------------------------------------------------- /backend/bin/forever: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | var path = require('path'); 3 | var forever = require('forever-monitor'); 4 | 5 | var child = new (forever.Monitor)( path.join(__dirname, 'www'), { 6 | max: 3, 7 | silent: false, 8 | args: [] 9 | }); 10 | 11 | child.on('exit', function () { 12 | console.log('www has exited after 3 restarts'); 13 | }); 14 | 15 | child.start(); -------------------------------------------------------------------------------- /frontend/app/views/user.html: -------------------------------------------------------------------------------- 1 |

This is the user view.

2 | 3 | 6 | 7 | 8 |
9 | 12 |
13 | 14 |
-------------------------------------------------------------------------------- /backend/controllers/auth/roles.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = { 3 | //roles GET 4 | index: function (req, res, next) { 5 | var Role = req.models.roles; 6 | 7 | Role.find().all(function (err, roles) { 8 | if (err) return next(err); 9 | 10 | //console.log('>> roles.index:'); 11 | //console.log(JSON.stringify(roles)); 12 | res.json(roles); 13 | }); 14 | } 15 | }; -------------------------------------------------------------------------------- /frontend/test/spec/services/assets.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Service: Assets', function () { 4 | 5 | // load the service's module 6 | beforeEach(module('frontendApp')); 7 | 8 | // instantiate service 9 | var assets; 10 | beforeEach(inject(function (_assets_) { 11 | assets = _assets_; 12 | })); 13 | 14 | it('should do something', function () { 15 | expect(!!assets).toBe(true); 16 | }); 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/test/spec/services/forums.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Service: forums', function () { 4 | 5 | // load the service's module 6 | beforeEach(module('frontendApp')); 7 | 8 | // instantiate service 9 | var forums; 10 | beforeEach(inject(function (_forums_) { 11 | forums = _forums_; 12 | })); 13 | 14 | it('should do something', function () { 15 | expect(!!forums).toBe(true); 16 | }); 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/test/spec/services/orders.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Service: orders', function () { 4 | 5 | // load the service's module 6 | beforeEach(module('frontendApp')); 7 | 8 | // instantiate service 9 | var orders; 10 | beforeEach(inject(function (_orders_) { 11 | orders = _orders_; 12 | })); 13 | 14 | it('should do something', function () { 15 | expect(!!orders).toBe(true); 16 | }); 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/test/spec/services/taxons.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Service: taxons', function () { 4 | 5 | // load the service's module 6 | beforeEach(module('frontendApp')); 7 | 8 | // instantiate service 9 | var taxons; 10 | beforeEach(inject(function (_taxons_) { 11 | taxons = _taxons_; 12 | })); 13 | 14 | it('should do something', function () { 15 | expect(!!taxons).toBe(true); 16 | }); 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/test/spec/services/topics.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Service: topics', function () { 4 | 5 | // load the service's module 6 | beforeEach(module('frontendApp')); 7 | 8 | // instantiate service 9 | var topics; 10 | beforeEach(inject(function (_topics_) { 11 | topics = _topics_; 12 | })); 13 | 14 | it('should do something', function () { 15 | expect(!!topics).toBe(true); 16 | }); 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/test/spec/services/tickets.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Service: tickets', function () { 4 | 5 | // load the service's module 6 | beforeEach(module('frontendApp')); 7 | 8 | // instantiate service 9 | var tickets; 10 | beforeEach(inject(function (_tickets_) { 11 | tickets = _tickets_; 12 | })); 13 | 14 | it('should do something', function () { 15 | expect(!!tickets).toBe(true); 16 | }); 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/test/spec/services/articles.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Service: articles', function () { 4 | 5 | // load the service's module 6 | beforeEach(module('frontendApp')); 7 | 8 | // instantiate service 9 | var articles; 10 | beforeEach(inject(function (_articles_) { 11 | articles = _articles_; 12 | })); 13 | 14 | it('should do something', function () { 15 | expect(!!articles).toBe(true); 16 | }); 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/test/spec/services/payments.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Service: payments', function () { 4 | 5 | // load the service's module 6 | beforeEach(module('frontendApp')); 7 | 8 | // instantiate service 9 | var payments; 10 | beforeEach(inject(function (_payments_) { 11 | payments = _payments_; 12 | })); 13 | 14 | it('should do something', function () { 15 | expect(!!payments).toBe(true); 16 | }); 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/test/spec/services/products.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Service: products', function () { 4 | 5 | // load the service's module 6 | beforeEach(module('frontendApp')); 7 | 8 | // instantiate service 9 | var products; 10 | beforeEach(inject(function (_products_) { 11 | products = _products_; 12 | })); 13 | 14 | it('should do something', function () { 15 | expect(!!products).toBe(true); 16 | }); 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/test/spec/services/profiles.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Service: profiles', function () { 4 | 5 | // load the service's module 6 | beforeEach(module('frontendApp')); 7 | 8 | // instantiate service 9 | var profiles; 10 | beforeEach(inject(function (_profiles_) { 11 | profiles = _profiles_; 12 | })); 13 | 14 | it('should do something', function () { 15 | expect(!!profiles).toBe(true); 16 | }); 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/test/spec/services/variants.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Service: variants', function () { 4 | 5 | // load the service's module 6 | beforeEach(module('frontendApp')); 7 | 8 | // instantiate service 9 | var variants; 10 | beforeEach(inject(function (_variants_) { 11 | variants = _variants_; 12 | })); 13 | 14 | it('should do something', function () { 15 | expect(!!variants).toBe(true); 16 | }); 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/test/spec/services/languages.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Service: languages', function () { 4 | 5 | // load the service's module 6 | beforeEach(module('frontendApp')); 7 | 8 | // instantiate service 9 | var languages; 10 | beforeEach(inject(function (_languages_) { 11 | languages = _languages_; 12 | })); 13 | 14 | it('should do something', function () { 15 | expect(!!languages).toBe(true); 16 | }); 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/test/spec/services/redirects.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Service: redirects', function () { 4 | 5 | // load the service's module 6 | beforeEach(module('frontendApp')); 7 | 8 | // instantiate service 9 | var redirects; 10 | beforeEach(inject(function (_redirects_) { 11 | redirects = _redirects_; 12 | })); 13 | 14 | it('should do something', function () { 15 | expect(!!redirects).toBe(true); 16 | }); 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/test/spec/services/shipments.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Service: shipments', function () { 4 | 5 | // load the service's module 6 | beforeEach(module('frontendApp')); 7 | 8 | // instantiate service 9 | var shipments; 10 | beforeEach(inject(function (_shipments_) { 11 | shipments = _shipments_; 12 | })); 13 | 14 | it('should do something', function () { 15 | expect(!!shipments).toBe(true); 16 | }); 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/test/spec/services/taxonomies.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Service: taxonomies', function () { 4 | 5 | // load the service's module 6 | beforeEach(module('frontendApp')); 7 | 8 | // instantiate service 9 | var taxonomies; 10 | beforeEach(inject(function (_taxonomies_) { 11 | taxonomies = _taxonomies_; 12 | })); 13 | 14 | it('should do something', function () { 15 | expect(!!taxonomies).toBe(true); 16 | }); 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/test/spec/services/mailfactory.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Service: MailFactory', function () { 4 | 5 | // load the service's module 6 | beforeEach(module('frontendApp')); 7 | 8 | // instantiate service 9 | var MailFactory; 10 | beforeEach(inject(function (_MailFactory_) { 11 | MailFactory = _MailFactory_; 12 | })); 13 | 14 | it('should do something', function () { 15 | expect(!!MailFactory).toBe(true); 16 | }); 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/test/spec/services/optiontypes.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Service: optionTypes', function () { 4 | 5 | // load the service's module 6 | beforeEach(module('frontendApp')); 7 | 8 | // instantiate service 9 | var optionTypes; 10 | beforeEach(inject(function (_optionTypes_) { 11 | optionTypes = _optionTypes_; 12 | })); 13 | 14 | it('should do something', function () { 15 | expect(!!optionTypes).toBe(true); 16 | }); 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/test/spec/services/rolefactory.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Service: RoleFactory', function () { 4 | 5 | // load the service's module 6 | beforeEach(module('frontendApp')); 7 | 8 | // instantiate service 9 | var RoleFactory; 10 | beforeEach(inject(function (_RoleFactory_) { 11 | RoleFactory = _RoleFactory_; 12 | })); 13 | 14 | it('should do something', function () { 15 | expect(!!RoleFactory).toBe(true); 16 | }); 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/test/spec/services/userfactory.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Service: UserFactory', function () { 4 | 5 | // load the service's module 6 | beforeEach(module('frontendApp')); 7 | 8 | // instantiate service 9 | var UserFactory; 10 | beforeEach(inject(function (_UserFactory_) { 11 | UserFactory = _UserFactory_; 12 | })); 13 | 14 | it('should do something', function () { 15 | expect(!!UserFactory).toBe(true); 16 | }); 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/app/scripts/directives/input.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('frontendApp') 4 | .directive('input', ['$parse', function ($parse) { 5 | return { 6 | restrict: 'E', 7 | require: '?ngModel', 8 | link: function postLink(scope, element, attrs) { 9 | if(attrs.ngModel){ 10 | var val = attrs.value || element.text(); 11 | $parse(attrs.ngModel).assign(scope, val); 12 | } 13 | } 14 | }; 15 | }]); 16 | -------------------------------------------------------------------------------- /frontend/test/spec/services/optionvalues.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Service: optionValues', function () { 4 | 5 | // load the service's module 6 | beforeEach(module('frontendApp')); 7 | 8 | // instantiate service 9 | var optionValues; 10 | beforeEach(inject(function (_optionValues_) { 11 | optionValues = _optionValues_; 12 | })); 13 | 14 | it('should do something', function () { 15 | expect(!!optionValues).toBe(true); 16 | }); 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/app/i18n/kr/language.json: -------------------------------------------------------------------------------- 1 | { 2 | "language": { 3 | "ca": "카탈로니아의", 4 | "da": "덴마크어", 5 | "en": "영어", 6 | "es": "스페인의", 7 | "fr": "불어", 8 | "ja": "일본어", 9 | "de": "독어", 10 | "sv": "스웨덴어", 11 | "pl": "폴란드어", 12 | "pt-br": "포르투갈어 (브라질)", 13 | "ru": "러시아어", 14 | "kr": "한국어", 15 | "tr": "터키의", 16 | "zh-cn": "중국어 (간체자)", 17 | "zh-tw": "중국어 (번체)" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /frontend/test/spec/services/payment_methods.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Service: paymentMethods', function () { 4 | 5 | // load the service's module 6 | beforeEach(module('frontendApp')); 7 | 8 | // instantiate service 9 | var paymentMethods; 10 | beforeEach(inject(function (_paymentMethods_) { 11 | paymentMethods = _paymentMethods_; 12 | })); 13 | 14 | it('should do something', function () { 15 | expect(!!paymentMethods).toBe(true); 16 | }); 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/test/spec/services/rememberfactory.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Service: RememberFactory', function () { 4 | 5 | // load the service's module 6 | beforeEach(module('frontendApp')); 7 | 8 | // instantiate service 9 | var RememberFactory; 10 | beforeEach(inject(function (_RememberFactory_) { 11 | RememberFactory = _RememberFactory_; 12 | })); 13 | 14 | it('should do something', function () { 15 | expect(!!RememberFactory).toBe(true); 16 | }); 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/test/spec/services/shipment_methods.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Service: shipmentMethods', function () { 4 | 5 | // load the service's module 6 | beforeEach(module('frontendApp')); 7 | 8 | // instantiate service 9 | var shipmentMethods; 10 | beforeEach(inject(function (_shipmentMethods_) { 11 | shipmentMethods = _shipmentMethods_; 12 | })); 13 | 14 | it('should do something', function () { 15 | expect(!!shipmentMethods).toBe(true); 16 | }); 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "browser": true, 4 | "esnext": true, 5 | "bitwise": true, 6 | "camelcase": true, 7 | "curly": true, 8 | "eqeqeq": true, 9 | "immed": true, 10 | "indent": 2, 11 | "latedef": true, 12 | "newcap": true, 13 | "noarg": true, 14 | "quotmark": "single", 15 | "regexp": true, 16 | "undef": true, 17 | "unused": true, 18 | "strict": true, 19 | "trailing": true, 20 | "smarttabs": true, 21 | "globals": { 22 | "angular": false 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /frontend/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | 10 | # Change these settings to your own preference 11 | indent_style = space 12 | indent_size = 2 13 | 14 | # We recommend you to keep these unchanged 15 | end_of_line = lf 16 | charset = utf-8 17 | trim_trailing_whitespace = true 18 | insert_final_newline = true 19 | 20 | [*.md] 21 | trim_trailing_whitespace = false 22 | -------------------------------------------------------------------------------- /frontend/app/scripts/directives/servererror.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('frontendApp') 4 | /** 5 | * Removes server error when user updates input 6 | */ 7 | .directive('serverError', function() { 8 | return { 9 | restrict: 'A', 10 | require: 'ngModel', 11 | link: function(scope, element, attrs, ngModelCtrl) { 12 | element.on('keydown', function() { 13 | return ngModelCtrl.$setValidity('server', true); 14 | }); 15 | } 16 | }; 17 | }); 18 | -------------------------------------------------------------------------------- /frontend/app/views/partials/include/taxonTree.html: -------------------------------------------------------------------------------- 1 |
2 |
10 |
11 |
12 | -------------------------------------------------------------------------------- /frontend/app/views/partials/include/input_file.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 |
6 | 7 |
8 |
9 | 10 |
11 |
12 | -------------------------------------------------------------------------------- /frontend/test/spec/filters/todate.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Filter: toDate', function () { 4 | 5 | // load the filter's module 6 | beforeEach(module('frontendApp')); 7 | 8 | // initialize a new instance of the filter before each test 9 | var toDate; 10 | beforeEach(inject(function ($filter) { 11 | toDate = $filter('toDate'); 12 | })); 13 | 14 | it('should return the input prefixed with "toDate filter:"', function () { 15 | var text = 'angularjs'; 16 | expect(toDate(text)).toBe('toDate filter: ' + text); 17 | }); 18 | 19 | }); 20 | -------------------------------------------------------------------------------- /frontend/app/scripts/services/redirects.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc service 5 | * @name frontendApp.redirects 6 | * @description 7 | * # redirects 8 | * Factory in the frontendApp. 9 | */ 10 | angular.module('frontendApp') 11 | .factory('redirects', function () { 12 | var redirectURL = ''; 13 | 14 | // Public API here 15 | return { 16 | setRedirectURL: function (url) { 17 | this.redirectURL = url; 18 | }, 19 | getRedirectURL: function(){ 20 | return this.redirectURL; 21 | } 22 | }; 23 | }); 24 | -------------------------------------------------------------------------------- /frontend/app/scripts/services/rolefactory.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /* 3 | * $resource: The default set contains these actions: 4 | 5 | { 'get': {method:'GET'}, 6 | 'save': {method:'POST'}, 7 | 'query': {method:'GET', isArray:true}, 8 | 'remove': {method:'DELETE'}, 9 | 'delete': {method:'DELETE'} 10 | }; 11 | */ 12 | 13 | angular.module('frontendApp') 14 | .factory('RoleFactory', ['$resource', function ($resource) { 15 | // Public API here 16 | return $resource('/roles/:id', {id:'@id'}, { 17 | update: {method: 'PUT'} 18 | }); 19 | }]); 20 | -------------------------------------------------------------------------------- /frontend/app/i18n/en/language.json: -------------------------------------------------------------------------------- 1 | { 2 | "language": { 3 | "ca": "Catalan", 4 | "zh-cn": "Chinese (simplified)", 5 | "zh-tw": "Chinese (traditional)", 6 | "da": "Danish", 7 | "en": "English", 8 | "fr": "French", 9 | "de": "German", 10 | "ja": "Japanese", 11 | "kr": "Korean", 12 | "hu": "Hungarian", 13 | "pl": "Polish", 14 | "pt-br": "Portuguese (brazilian)", 15 | "ru": "Russian", 16 | "es": "Spanish", 17 | "sv": "Swedish", 18 | "tr": "Turkish" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /frontend/app/views/partials/admin/users/layout.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 | Nested Menu 7 |
8 | Users List 9 |
10 |
11 |
12 |
13 |
14 |
15 | -------------------------------------------------------------------------------- /frontend/test/spec/directives/input.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Directive: input', function () { 4 | 5 | // load the directive's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var element, 9 | scope; 10 | 11 | beforeEach(inject(function ($rootScope) { 12 | scope = $rootScope.$new(); 13 | })); 14 | 15 | it('should make hidden element visible', inject(function ($compile) { 16 | element = angular.element(''); 17 | element = $compile(element)(scope); 18 | expect(element.text()).toBe('this is the input directive'); 19 | })); 20 | }); 21 | -------------------------------------------------------------------------------- /frontend/test/spec/directives/onfocus.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Directive: onFocus', function () { 4 | 5 | // load the directive's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var element, 9 | scope; 10 | 11 | beforeEach(inject(function ($rootScope) { 12 | scope = $rootScope.$new(); 13 | })); 14 | 15 | it('should make hidden element visible', inject(function ($compile) { 16 | element = angular.element(''); 17 | element = $compile(element)(scope); 18 | expect(element.text()).toBe('this is the onFocus directive'); 19 | })); 20 | }); 21 | -------------------------------------------------------------------------------- /frontend/app/scripts/controllers/language.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc function 5 | * @name frontendApp.controller:LanguageCtrl 6 | * @description 7 | * # LanguageCtrl 8 | * Controller of the frontendApp 9 | */ 10 | angular.module('frontendApp') 11 | .controller('LanguageCtrl', ['$scope', '$translate', 'languages', function ($scope, $translate, languages) { 12 | $scope.changeLanguage = function (languageKey) { 13 | $translate.use(languageKey); 14 | }; 15 | 16 | languages.getAll().then(function (languages) { 17 | $scope.languages = languages; 18 | }); 19 | }]); 20 | -------------------------------------------------------------------------------- /frontend/app/scripts/directives/ngconfirmclick.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('frontendApp') 4 | .directive('ngConfirmClick', function () { 5 | return { 6 | priority: -1, 7 | restrict: 'A', 8 | link: function (scope, element, attrs) { 9 | element.bind('click', function (e) { 10 | var message = attrs.ngConfirmClick; 11 | if (message && !confirm(message)) { 12 | e.stopImmediatePropagation(); 13 | e.preventDefault(); 14 | } 15 | }); 16 | } 17 | }; 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/app/views/partials/include/idle_dialog.html: -------------------------------------------------------------------------------- 1 | 10 | 11 | 21 | -------------------------------------------------------------------------------- /frontend/test/spec/directives/activenav.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Directive: activeNav', function () { 4 | 5 | // load the directive's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var element, 9 | scope; 10 | 11 | beforeEach(inject(function ($rootScope) { 12 | scope = $rootScope.$new(); 13 | })); 14 | 15 | it('should make hidden element visible', inject(function ($compile) { 16 | element = angular.element(''); 17 | element = $compile(element)(scope); 18 | expect(element.text()).toBe('this is the activeNav directive'); 19 | })); 20 | }); 21 | -------------------------------------------------------------------------------- /frontend/app/scripts/directives/jqdatepicker.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('frontendApp') 4 | .directive('jqdatepicker', function () { 5 | return { 6 | restrict: 'A', 7 | require: 'ngModel', 8 | link: function(scope, element, attrs, ctrl) { 9 | $(element).datepicker({ 10 | dateFormat: 'yy-mm-dd', 11 | onSelect: function(date) { 12 | ctrl.$setViewValue(date); 13 | ctrl.$render(); 14 | scope.$apply(); 15 | } 16 | }); 17 | } 18 | }; 19 | }); 20 | -------------------------------------------------------------------------------- /frontend/test/spec/directives/accesslevel.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Directive: accessLevel', function () { 4 | 5 | // load the directive's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var element, 9 | scope; 10 | 11 | beforeEach(inject(function ($rootScope) { 12 | scope = $rootScope.$new(); 13 | })); 14 | 15 | it('should make hidden element visible', inject(function ($compile) { 16 | element = angular.element(''); 17 | element = $compile(element)(scope); 18 | expect(element.text()).toBe('this is the accessLevel directive'); 19 | })); 20 | }); 21 | -------------------------------------------------------------------------------- /frontend/test/spec/directives/file_upload.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Directive: fileUpload', function () { 4 | 5 | // load the directive's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var element, 9 | scope; 10 | 11 | beforeEach(inject(function ($rootScope) { 12 | scope = $rootScope.$new(); 13 | })); 14 | 15 | it('should make hidden element visible', inject(function ($compile) { 16 | element = angular.element(''); 17 | element = $compile(element)(scope); 18 | expect(element.text()).toBe('this is the fileUpload directive'); 19 | })); 20 | }); 21 | -------------------------------------------------------------------------------- /frontend/test/spec/directives/servererror.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Directive: serverError', function () { 4 | 5 | // load the directive's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var element, 9 | scope; 10 | 11 | beforeEach(inject(function ($rootScope) { 12 | scope = $rootScope.$new(); 13 | })); 14 | 15 | it('should make hidden element visible', inject(function ($compile) { 16 | element = angular.element(''); 17 | element = $compile(element)(scope); 18 | expect(element.text()).toBe('this is the serverError directive'); 19 | })); 20 | }); 21 | -------------------------------------------------------------------------------- /frontend/test/spec/directives/jqdatepicker.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Directive: jqdatepicker', function () { 4 | 5 | // load the directive's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var element, 9 | scope; 10 | 11 | beforeEach(inject(function ($rootScope) { 12 | scope = $rootScope.$new(); 13 | })); 14 | 15 | it('should make hidden element visible', inject(function ($compile) { 16 | element = angular.element(''); 17 | element = $compile(element)(scope); 18 | expect(element.text()).toBe('this is the jqdatepicker directive'); 19 | })); 20 | }); 21 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/cart.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: CartCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var CartCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | CartCtrl = $controller('CartCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/mail.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: MailCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var MailCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | MailCtrl = $controller('MailCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/main.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: MainCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var MainCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | MainCtrl = $controller('MainCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/news.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: NewsCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var NewsCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | NewsCtrl = $controller('NewsCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/user.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: UserCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var UserCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | UserCtrl = $controller('UserCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/directives/passwordcheck.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Directive: passwordCheck', function () { 4 | 5 | // load the directive's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var element, 9 | scope; 10 | 11 | beforeEach(inject(function ($rootScope) { 12 | scope = $rootScope.$new(); 13 | })); 14 | 15 | it('should make hidden element visible', inject(function ($compile) { 16 | element = angular.element(''); 17 | element = $compile(element)(scope); 18 | expect(element.text()).toBe('this is the passwordCheck directive'); 19 | })); 20 | }); 21 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/forum.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: ForumCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var ForumCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | ForumCtrl = $controller('ForumCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/login.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: LoginCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var LoginCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | LoginCtrl = $controller('LoginCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/order.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: OrderCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var OrderCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | OrderCtrl = $controller('OrderCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/topic.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: TopicCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var TopicCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | TopicCtrl = $controller('TopicCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/directives/markdowneditor.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Directive: markdownEditor', function () { 4 | 5 | // load the directive's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var element, 9 | scope; 10 | 11 | beforeEach(inject(function ($rootScope) { 12 | scope = $rootScope.$new(); 13 | })); 14 | 15 | it('should make hidden element visible', inject(function ($compile) { 16 | element = angular.element(''); 17 | element = $compile(element)(scope); 18 | expect(element.text()).toBe('this is the markdownEditor directive'); 19 | })); 20 | }); 21 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/events.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: EventsCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var EventsCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | EventsCtrl = $controller('EventsCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/navbar.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: NavbarCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var NavbarCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | NavbarCtrl = $controller('NavbarCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/upload.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: UploadCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var UploadCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | UploadCtrl = $controller('UploadCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/directives/ngconfirmclick.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Directive: ngConfirmClick', function () { 4 | 5 | // load the directive's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var element, 9 | scope; 10 | 11 | beforeEach(inject(function ($rootScope) { 12 | scope = $rootScope.$new(); 13 | })); 14 | 15 | it('should make hidden element visible', inject(function ($compile) { 16 | element = angular.element(''); 17 | element = $compile(element)(scope); 18 | expect(element.text()).toBe('this is the ngConfirmClick directive'); 19 | })); 20 | }); 21 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/address.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: AddressCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var AddressCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | AddressCtrl = $controller('AddressCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/payment.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: PaymentCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var PaymentCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | PaymentCtrl = $controller('PaymentCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/product.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: ProductCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var ProductCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | ProductCtrl = $controller('ProductCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/profile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: ProfileCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var ProfileCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | ProfileCtrl = $controller('ProfileCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/support.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: SupportCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var SupportCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | SupportCtrl = $controller('SupportCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/delivery.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: DeliveryCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var DeliveryCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | DeliveryCtrl = $controller('DeliveryCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/language.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: LanguageCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var LanguageCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | LanguageCtrl = $controller('LanguageCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/password.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: PasswordCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var PasswordCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | PasswordCtrl = $controller('PasswordCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/admin/user.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: AdminUserCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var AdminUserCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | AdminUserCtrl = $controller('AdminUserCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/taxon_tree.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: TaxonTreeCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var TaxonTreeCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | TaxonTreeCtrl = $controller('TaxonTreeCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/admin/asset.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: AdminAssetCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var AdminAssetCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | AdminAssetCtrl = $controller('AdminAssetCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/admin/forum.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: AdminForumCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var AdminForumCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | AdminForumCtrl = $controller('AdminForumCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/admin/order.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: AdminOrderCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var AdminOrderCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | AdminOrderCtrl = $controller('AdminOrderCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/admin/product.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: AdminProductCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var AdminProductCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | AdminProductCtrl = $controller('AdminProductCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/admin/support.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: AdminSupportCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var AdminSupportCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | AdminSupportCtrl = $controller('AdminSupportCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/admin/variant.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: AdminVariantCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var AdminVariantCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | AdminVariantCtrl = $controller('AdminVariantCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/admin/taxonomy.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: AdminTaxonomyCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var AdminTaxonomyCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | AdminTaxonomyCtrl = $controller('AdminTaxonomyCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/admin/optiontype.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: AdminOptiontypeCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var AdminOptiontypeCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | AdminOptiontypeCtrl = $controller('AdminOptiontypeCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/admin/payment_method.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: AdminPaymentMethodCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var AdminPaymentMethodCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | AdminPaymentMethodCtrl = $controller('AdminPaymentMethodCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/spec/controllers/admin/shipping_method.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: AdminShippingMethodCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('frontendApp')); 7 | 8 | var AdminShippingMethodCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | AdminShippingMethodCtrl = $controller('AdminShippingMethodCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/app/views/partials/forums/topics/layout.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 |
6 |
7 | Nested Menu 8 |
9 | Forums List 10 | Topics List 11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | -------------------------------------------------------------------------------- /frontend/test/spec/services/sessionfactory.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Service: SessionFactory', function () { 4 | 5 | // load the service's module 6 | beforeEach(module('frontendApp')); 7 | 8 | // instantiate service 9 | var SessionFactory; 10 | beforeEach(inject(function (_SessionFactory_) { 11 | SessionFactory = _SessionFactory_; 12 | })); 13 | 14 | it('should do something', function () { 15 | expect(!!SessionFactory).toBe(true); 16 | }); 17 | 18 | it('gets session item', function(){ 19 | SessionFactory.get(function(user) { 20 | console.log('>>authfactory currentUser:'); 21 | console.log(user); 22 | //$rootScope.currentUser = user; 23 | }); 24 | 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /frontend/app/scripts/controllers/navbar.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('frontendApp') 4 | .controller('NavbarCtrl', ['$scope', 'AuthFactory', '$location', 5 | function($scope, AuthFactory, $location) { 6 | $scope.user = AuthFactory.user; 7 | $scope.userRoles = AuthFactory.userRoles; 8 | $scope.accessLevels = AuthFactory.accessLevels; 9 | 10 | $scope.logout = function() { 11 | AuthFactory.logout(function(err) { 12 | if (err) { 13 | console.log(err); 14 | } else { 15 | $location.path('/login'); 16 | } 17 | }); 18 | }; 19 | } 20 | ]); 21 | -------------------------------------------------------------------------------- /backend/template/order_confirm_mail.hogan.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{#order.line_items}} 4 | 5 | 6 | 7 | 8 | 9 | 10 | {{/order.line_items}} 11 | 12 | 13 | 14 | 17 | 20 | 21 | 22 |
{{name}}
{{options}}
{{price}} x {{quantity}}{{subtotal}}
Shipment:
15 | Total: 16 |
{{order.shipment_total}}
18 | {{order.total}} 19 |
-------------------------------------------------------------------------------- /frontend/app/views/partials/products/layout.html: -------------------------------------------------------------------------------- 1 |
2 | Home 3 |
4 |
5 | Cart 6 |
7 |
8 |
9 |
10 |
11 |
12 | Categories 13 |
14 |
15 |
16 | 17 |
18 |
19 |
20 |
21 |
22 | -------------------------------------------------------------------------------- /frontend/test/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "browser": true, 4 | "esnext": true, 5 | "bitwise": true, 6 | "camelcase": true, 7 | "curly": true, 8 | "eqeqeq": true, 9 | "immed": true, 10 | "indent": 2, 11 | "latedef": true, 12 | "newcap": true, 13 | "noarg": true, 14 | "quotmark": "single", 15 | "regexp": true, 16 | "undef": true, 17 | "unused": true, 18 | "strict": true, 19 | "trailing": true, 20 | "smarttabs": true, 21 | "globals": { 22 | "after": false, 23 | "afterEach": false, 24 | "angular": false, 25 | "before": false, 26 | "beforeEach": false, 27 | "browser": false, 28 | "describe": false, 29 | "expect": false, 30 | "inject": false, 31 | "it": false, 32 | "jasmine": false, 33 | "spyOn": false 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /backend/controllers/shipments.js: -------------------------------------------------------------------------------- 1 | var log = require('log4js').getLogger("shipments"); 2 | 3 | module.exports = { 4 | getByOrderId: function(req, res, next){ 5 | var Shipment = req.models.shipments; 6 | var orderId = req.body.order_id; 7 | 8 | Shipment.one({order_id: orderId}, function(err, shipment){ 9 | if(err || !shipment) { 10 | var msg = err ? err: 'Shipment is empty!'; 11 | return res.status(400).json(msg); 12 | } 13 | shipment.getShipping_method(function(err, shippingMethod){ 14 | log.debug(JSON.stringify(shippingMethod)); 15 | shipment.shipping_method = shippingMethod; 16 | return res.status(200).json(shipment); 17 | }); 18 | 19 | }); 20 | } 21 | }; -------------------------------------------------------------------------------- /frontend/app/scripts/controllers/payment.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('frontendApp') 4 | .controller('PaymentCtrl', ['$scope','$state', 'payments', 'orders', function ($scope, $state, payments, orders) { 5 | $scope.payment = {}; 6 | 7 | $scope.getPaymentMethods = function(){ 8 | payments.getPaymentMethods(function(err, data){ 9 | $scope.payment_methods = data; 10 | $scope.payment.payment_method = data[0]; 11 | //console.log(data); 12 | }); 13 | }; 14 | 15 | $scope.savePayment = function(){ 16 | orders.savePayment($scope.payment, function(err, order){ 17 | if(err) $scope.error = err; 18 | else $state.go('orders.view', {id: order.id}); 19 | }); 20 | }; 21 | 22 | $scope.getPaymentMethods(); 23 | }]); 24 | -------------------------------------------------------------------------------- /backend/config/log4js.json: -------------------------------------------------------------------------------- 1 | { 2 | "appenders": [ 3 | { 4 | "type": "clustered", 5 | "replaceConsole": "false", 6 | "appenders": [ 7 | { 8 | "type": "dateFile", 9 | "filename": "log/access.log", 10 | "pattern": "-yyyy-MM-dd", 11 | "category": "http" 12 | }, 13 | { 14 | "type": "file", 15 | "level": "error", 16 | "filename": "log/app.log", 17 | "maxLogSize": 10485760, 18 | "numBackups": 3 19 | }, 20 | { 21 | "type": "logLevelFilter", 22 | "level": "ERROR", 23 | "appender": { 24 | "type": "file", 25 | "filename": "log/errors.log" 26 | } 27 | }, 28 | { 29 | "type": "console" 30 | } 31 | ] 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /frontend/app/scripts/controllers/delivery.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('frontendApp') 4 | .controller('DeliveryCtrl', ['$scope','$state', 'orders', 'shipments','shippingMethods', function ($scope, $state, orders, shipments, shippingMethods) { 5 | $scope.data = {}; 6 | $scope.data.shipping_methods = shippingMethods.index(); 7 | 8 | orders.getOrder(function(err, order){ 9 | shipments.getByOrderId({order_id: order.id}, function(err, shipment){ 10 | $scope.shipment = shipment; 11 | //console.log(shipment); 12 | }); 13 | }); 14 | 15 | $scope.saveShipment = function(){ 16 | orders.saveShipment($scope.shipment, function(err, order){ 17 | if(err) $scope.error = err; 18 | else $state.go('orders.payment', {id: order.id}); 19 | 20 | }); 21 | } 22 | 23 | }]); 24 | -------------------------------------------------------------------------------- /frontend/app/scripts/directives/file_upload.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc directive 5 | * @name frontendApp.directive:fileUpload 6 | * @description 7 | * # fileUpload 8 | */ 9 | angular.module('frontendApp') 10 | .directive('fileUpload', function () { 11 | return { 12 | scope: true, //create a new scope 13 | link: function (scope, el, attrs) { 14 | el.bind('change', function (event) { 15 | var files = event.target.files; 16 | //iterate files since 'multiple' may be specified on the element 17 | for (var i = 0; i < files.length; i++) { 18 | //emit event upward 19 | scope.$emit("fileSelected", { file: files[i] }); 20 | } 21 | }); 22 | } 23 | } 24 | }); 25 | -------------------------------------------------------------------------------- /frontend/app/views/partials/admin/layout.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 9 |
10 |
11 |
12 |
13 | -------------------------------------------------------------------------------- /frontend/app/scripts/services/userfactory.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /* 3 | * $resource: The default set contains these actions: 4 | 5 | { 'get': {method:'GET'}, 6 | 'save': {method:'POST'}, 7 | 'query': {method:'GET', isArray:true}, 8 | 'remove': {method:'DELETE'}, 9 | 'delete': {method:'DELETE'} 10 | }; 11 | */ 12 | var services = angular.module('frontendApp'); 13 | services.factory('UserFactory', ['$resource', 14 | function($resource) { 15 | return $resource('/users/:id', {id:"@id"}, { 16 | list: {//query 17 | method: 'GET', 18 | isArray: true 19 | }, 20 | show: {//get 21 | method: 'GET' 22 | }, 23 | //get: { method: 'GET', params: {id: '@id'} }, 24 | update: { 25 | method: 'PUT' 26 | } 27 | }); 28 | } 29 | ]); 30 | -------------------------------------------------------------------------------- /frontend/lang/template.pot: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Content-Type: text/plain; charset=UTF-8\n" 4 | "Content-Transfer-Encoding: 8bit\n" 5 | "Project-Id-Version: \n" 6 | 7 | #: app/views/partials/include/navbar.html 8 | #: dist/views/partials/include/navbar.html 9 | msgid "Forums" 10 | msgstr "" 11 | 12 | #: app/views/partials/include/navbar.html 13 | #: dist/views/partials/include/navbar.html 14 | msgid "Login" 15 | msgstr "" 16 | 17 | #: app/views/partials/include/navbar.html 18 | #: dist/views/partials/include/navbar.html 19 | msgid "My Order" 20 | msgstr "" 21 | 22 | #: app/views/partials/include/navbar.html 23 | #: dist/views/partials/include/navbar.html 24 | msgid "News" 25 | msgstr "" 26 | 27 | #: app/views/partials/include/navbar.html 28 | #: dist/views/partials/include/navbar.html 29 | msgid "Signup" 30 | msgstr "" 31 | 32 | #: app/views/partials/include/navbar.html 33 | msgid "Support" 34 | msgstr "" 35 | -------------------------------------------------------------------------------- /backend/README.md: -------------------------------------------------------------------------------- 1 | # Express backend server 2 | ## Install Express' application generator. 3 | https://github.com/expressjs/generator 4 | 5 | $ sudo npm install -g express-generator 6 | 7 | ## Generate expressjs project 8 | $ express backend && cd backend 9 | 10 | ## Install dependencies: 11 | 12 | $ npm install 13 | 14 | ## Start express server 15 | 16 | $ npm start 17 | or 18 | $ ./bin/forever 19 | 20 | or production mode: 21 | $ NODE_ENV=production ./bin/forever 22 | 23 | or development environment: 24 | $ nodemon ./bin/forever 25 | 26 | ## Install node packages 27 | 28 | $ npm install mysql --save 29 | 30 | $ npm install orm --save 31 | 32 | $ npm install crypto --save 33 | 34 | $ npm install connect-multiparty --save 35 | 36 | ## GraphicMagick 37 | First install either GraphicsMagick or ImageMagick. 38 | 39 | $ sudo apt-get install libmagickwand-dev imagemagick 40 | 41 | Then: 42 | 43 | $ npm install gm --save -------------------------------------------------------------------------------- /frontend/app/scripts/directives/passwordmatch.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('frontendApp') 4 | .directive('passwordMatch', function() { 5 | return { 6 | restrict: 'A', 7 | scope: true, 8 | require: 'ngModel', 9 | link: function postLink(scope, element, attrs, ctrl) { 10 | var checker = function() { 11 | // get the value of the first password 12 | var e1 = scope.$eval(attrs.ngModel); 13 | // get the value of the other password 14 | var e2 = scope.$eval(attrs.passwordMatch); 15 | return e1 == e2; 16 | }; 17 | scope.$watch(checker, function(n) { 18 | // set the form control to valid if both passwords are 19 | // the same, else invalid 20 | ctrl.$setValidity('passwordMatch', n); 21 | }); 22 | } 23 | }; 24 | }); 25 | -------------------------------------------------------------------------------- /frontend/app/scripts/services/payments.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('frontendApp') 4 | .factory('payments', ['$http', '$resource', function ($http, $resource) { 5 | // Service logic 6 | 7 | // Public API here 8 | return { 9 | getPaymentMethods: function(callback){ 10 | var cb = callback || angular.noop; 11 | $http.get('/orders/payment_methods') 12 | .success(function(data, status, headers, config){ 13 | //console.log('>> status:'+ status); 14 | return cb(null, data); 15 | }).error(function(data, status, headers, config) { 16 | //console.log('>> error data:'+ data); 17 | // called asynchronously if an error occurs 18 | // or server returns response with an error status. 19 | return cb(data); 20 | }); 21 | } 22 | }; 23 | }]); 24 | -------------------------------------------------------------------------------- /frontend/lang/ko.po: -------------------------------------------------------------------------------- 1 | # jinny , 2015. 2 | msgid "" 3 | msgstr "" 4 | "Project-Id-Version: \n" 5 | "PO-Revision-Date: 2015-04-14 16:55+0900\n" 6 | "Last-Translator: jinny \n" 7 | "Language-Team: jinny\n" 8 | "Language: ko\n" 9 | "Content-Type: text/plain; charset=UTF-8\n" 10 | "Content-Transfer-Encoding: 8bit\n" 11 | "Plural-Forms: nplurals=1; plural=0;\n" 12 | "X-Generator: Virtaal 0.7.1\n" 13 | 14 | #: app/views/partials/include/navbar.html 15 | msgid "Forums" 16 | msgstr "포럼" 17 | 18 | #: app/views/partials/include/navbar.html 19 | msgid "Support" 20 | msgstr "지원" 21 | 22 | #: app/views/partials/include/navbar.html 23 | msgid "Login" 24 | msgstr "로그인" 25 | 26 | #: app/views/partials/include/navbar.html 27 | msgid "My Order" 28 | msgstr "내주문" 29 | 30 | #: app/views/partials/include/navbar.html 31 | msgid "News" 32 | msgstr "뉴스" 33 | 34 | #: app/views/partials/include/navbar.html 35 | msgid "Signup" 36 | msgstr "회원가입" 37 | -------------------------------------------------------------------------------- /backend/config/settings.sample.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | //console.log(process.env); 3 | var settings = { 4 | site_url: 'http://localhost:3000', 5 | upload_path: (process.env.NODE_ENV == 'production')? path.normalize(path.join(__dirname, './../../frontend/dist/uploads/')) 6 | : path.normalize(path.join(__dirname, './../../frontend/app/uploads/')), 7 | port: process.env.NODE_PORT || 3000, 8 | 9 | postmailer: 'postmaster@localhost', 10 | 11 | database: { 12 | protocol: "mysql", // or "postgresql" 13 | query: { 14 | debug: (process.env.NODE_ENV == 'production')? false: true, //prints queries to console 15 | pool: true 16 | }, 17 | host: "127.0.0.1", 18 | port: 3306, 19 | database: "nodesoft2", 20 | user: "root", 21 | password: "", 22 | timezone: "+09:00" //'Asia/Seoul' 23 | } 24 | }; 25 | 26 | module.exports = settings; 27 | -------------------------------------------------------------------------------- /frontend/app/scripts/controllers/address.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('frontendApp') 4 | .controller('AddressCtrl', ['$scope','$state', 'orders', function ($scope, $state, orders) { 5 | $scope.order = {}; 6 | 7 | $scope.useBillingAddress = function(){ 8 | //console.log($scope.order); 9 | if($scope.order.use_bill_address){ 10 | $scope.order.ship_address = angular.copy($scope.order.bill_address); 11 | } else { 12 | $scope.order.ship_address = {}; 13 | } 14 | }; 15 | 16 | $scope.saveAddress = function(){ 17 | orders.saveAddress($scope.order, function(err, order){ 18 | if(err) $scope.error = err; 19 | else $state.go('orders.delivery', {id: order.id}); 20 | }); 21 | } 22 | 23 | $scope.getOrder = function(){ 24 | orders.getOrder(function(err, data){ 25 | $scope.order = data; 26 | //console.log(data); 27 | }); 28 | 29 | }; 30 | 31 | $scope.getOrder(); 32 | }]); 33 | -------------------------------------------------------------------------------- /frontend/app/views/partials/admin/users/users.edit.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 | {{currentUser.email}} 6 |
7 |
8 | 9 | {{currentUser.role.title}} 10 |
11 |
12 | 13 | 16 |
17 |
18 | {{currentUser.active}} 19 | 20 |
21 | 22 | 23 |
24 |
25 | -------------------------------------------------------------------------------- /frontend/app/scripts/directives/activenav.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('frontendApp') 4 | .directive('activeNav', ['$location', function ($location) { 5 | return { 6 | restrict: 'A', 7 | link: function (scope, element, attrs) { 8 | var anchor = element[0]; 9 | if(element[0].tagName.toUpperCase() != 'A') 10 | anchor = element.find('a')[0]; 11 | var path = anchor.href; 12 | 13 | scope.location = $location; 14 | scope.$watch('location.absUrl()', function(newPath){ 15 | path = normalizeUrl(path); 16 | newPath = normalizeUrl(newPath); 17 | 18 | if(path === newPath || (attrs.activeNav === 'nestedTop' && newPath.indexOf(path) === 0)){ 19 | element.addClass('active'); 20 | } else { 21 | element.removeClass('active'); 22 | } 23 | }); 24 | } 25 | }; 26 | 27 | function normalizeUrl(url){ 28 | if(url[url.length - 1] !== '/') 29 | url = url + '/'; 30 | return url; 31 | } 32 | }]); 33 | -------------------------------------------------------------------------------- /frontend/app/views/partials/orders/orders.payment.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |
6 |
7 |
8 |
9 |

Payment Information:

10 |
11 | {{item.name}}
12 | {{item.description}} 13 |
14 | 15 |
16 |
17 |
18 |
19 |
20 |

{{ error }}

21 |
22 | 24 |
25 |
26 |
27 |
28 | -------------------------------------------------------------------------------- /frontend/app/scripts/directives/accesslevel.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('frontendApp') 4 | .directive('accessLevel', ['AuthFactory', function (AuthFactory) { 5 | return { 6 | restrict: 'A', 7 | link: function(scope, element, attrs) { 8 | var prevDisp = element.css('display'), 9 | userRole, 10 | accessLevel; 11 | scope.user = AuthFactory.user; 12 | scope.$watch('user', function(user){ 13 | if(user.role) userRole = user.role; 14 | updateCSS(); 15 | }, true); 16 | 17 | attrs.$observe('accessLevel', function(al){ 18 | if(al) accessLevel = scope.$eval(al); 19 | updateCSS(); 20 | }); 21 | 22 | function updateCSS(){ 23 | if(userRole && accessLevel){ 24 | if(!AuthFactory.authorize(accessLevel, userRole)){ 25 | element.css('display', 'none'); 26 | } else { 27 | element.css('display', prevDisp); 28 | } 29 | } 30 | } 31 | } 32 | }; 33 | }]); 34 | -------------------------------------------------------------------------------- /frontend/app/scripts/directives/markdowneditor.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('frontendApp') 4 | .directive('markdownEditor', ['$window', function ($window) { 5 | return { 6 | restrict: 'A', 7 | link: function postLink(scope, element, attrs) { 8 | var hiddenButtons = attrs.mdHiddenButtons ? attrs.mdHiddenButtons.split(","): new Array(); 9 | element.markdown({ 10 | language: settings.markdownEditor.language, 11 | hiddenButtons: hiddenButtons, 12 | additionalButtons: [ 13 | [{ 14 | name:"groupCustom", 15 | data: [{ 16 | name: "cmdHelp", 17 | toggle: true, 18 | title: "Help", 19 | icon: "glyphicon glyphicon-question-sign", 20 | callback: function(e){ 21 | $window.open("http://daringfireball.net/projects/markdown/syntax", "_blank"); 22 | } 23 | }] 24 | 25 | }] 26 | ] 27 | }); 28 | } 29 | }; 30 | }]); 31 | -------------------------------------------------------------------------------- /frontend/app/views/partials/orders/orders.delivery.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |
6 |
7 |
8 |
9 |

Delivery Information:

10 | 11 |
12 | 13 | {{item.name}} 14 | ({{item.currency}}) {{item.amount | currency}} 15 | 16 |
17 | 18 |
19 |
20 |
21 |
22 |
23 |

{{ error }}

24 |
25 | 27 |
28 |
29 |
30 |
31 | -------------------------------------------------------------------------------- /frontend/app/views/partials/admin/assets/layout.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 |
6 |
7 | Menu 8 |
9 | Products List 10 | Product Details 11 | Variants 12 | Images 13 |
14 |
15 |
16 |
17 |
18 | -------------------------------------------------------------------------------- /frontend/app/scripts/services/languages.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc service 5 | * @name frontendApp.languages 6 | * @description 7 | * # languages 8 | * Factory in the frontendApp. 9 | */ 10 | angular.module('frontendApp') 11 | .factory('languages', ['$q', '$http', '$translate', 'LANGUAGES', function ($q, $http, $translate, LANGUAGES) { 12 | return { 13 | getCurrent: function () { 14 | var deferred = $q.defer(); 15 | var language = $translate.storage().get('NG_TRANSLATE_LANG_KEY'); 16 | 17 | if (angular.isUndefined(language)) { 18 | language = 'en'; 19 | } 20 | 21 | deferred.resolve(language); 22 | return deferred.promise; 23 | }, 24 | getAll: function () { 25 | var deferred = $q.defer(); 26 | deferred.resolve(LANGUAGES); 27 | return deferred.promise; 28 | } 29 | }; 30 | }]) 31 | 32 | /* 33 | Languages codes are ISO_639-1 codes, see http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes 34 | They are written in English to avoid character encoding issues (not a perfect solution) 35 | */ 36 | .constant('LANGUAGES', [ 37 | 'en','kr' 38 | ] 39 | ); 40 | -------------------------------------------------------------------------------- /frontend/app/views/partials/admin/variants/layout.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 |
6 |
7 | Menu 8 |
9 | Products List 10 | Product Details 11 | Variants 12 | Images 13 |
14 |
15 |
16 |
17 |
18 | -------------------------------------------------------------------------------- /frontend/app/scripts/controllers/user.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var app = angular.module('frontendApp'); 4 | app.controller('UserCtrl', ['$scope', 'UserFactory', 5 | function($scope, UserFactory) { 6 | $scope.list = function() { 7 | 8 | UserFactory.query(null, function(users) { // success 9 | //console.log('>>UserFactory.query: '); 10 | //console.log(users); 11 | $scope.users = users; 12 | }, function(httpRes) { // error 13 | // var msg = HelperService.GetErrorMessage(httpRes); 14 | // $notification.error('Data Fetch Failed', msg); 15 | //console.log(httpRes); 16 | }); 17 | }; 18 | 19 | $scope.show = function(userId) { 20 | //console.log('>> userId:'); 21 | //console.log(userId); 22 | UserFactory.get({ 23 | id: userId 24 | }, function(user) { //Success 25 | //console.log(user); 26 | $scope.user = user; 27 | }, function(httpRes) { //Error 28 | console.log(httpRes); 29 | }); 30 | }; 31 | 32 | } 33 | ]); 34 | -------------------------------------------------------------------------------- /schema/schema.sql: -------------------------------------------------------------------------------- 1 | CREATE SCHEMA `nodesoft2` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ; 2 | 3 | CREATE TABLE `users` ( 4 | `id` int(11) NOT NULL AUTO_INCREMENT, 5 | `email` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', 6 | `encrypted_password` varchar(128) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', 7 | `password_salt` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', 8 | `reset_password_token` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, 9 | `remember_token` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, 10 | `remember_created_at` datetime DEFAULT NULL, 11 | `sign_in_count` int(11) DEFAULT '0', 12 | `current_sign_in_at` datetime DEFAULT NULL, 13 | `last_sign_in_at` datetime DEFAULT NULL, 14 | `current_sign_in_ip` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, 15 | `last_sign_in_ip` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, 16 | `created_at` datetime DEFAULT NULL, 17 | `updated_at` datetime DEFAULT NULL, 18 | PRIMARY KEY (`id`), 19 | UNIQUE KEY `index_users_on_email` (`email`), 20 | UNIQUE KEY `index_users_on_reset_password_token` (`reset_password_token`) 21 | ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 22 | -------------------------------------------------------------------------------- /frontend/app/views/partials/orders/layout.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | Home 4 |
5 |
6 | Cart 7 |
8 | 9 | 16 |
17 |
18 |
19 |
20 | -------------------------------------------------------------------------------- /frontend/app/scripts/directives/onfocus.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('frontendApp') 4 | .constant('focusConfig', { 5 | focusClass: 'focused' 6 | }) 7 | .directive('onFocus', ['focusConfig', 8 | function(focusConfig) { 9 | return { 10 | restrict: 'A', 11 | require: 'ngModel', 12 | link: function(scope, element, attrs, ngModelCtrl) { 13 | ngModelCtrl.$focused = false; 14 | element 15 | .bind('focus', function(evt) { 16 | element.addClass(focusConfig.focusClass); 17 | scope.$apply(function() { 18 | ngModelCtrl.$focused = true; 19 | }); 20 | }) 21 | .bind('blur', function(evt) { 22 | element.removeClass(focusConfig.focusClass); 23 | scope.$apply(function() { 24 | ngModelCtrl.$focused = false; 25 | }); 26 | }); 27 | } 28 | }; 29 | } 30 | ]); 31 | -------------------------------------------------------------------------------- /backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "application-name", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "async": "^0.9.0", 10 | "body-parser": "^1.4.3", 11 | "connect-modrewrite": "^0.7.5", 12 | "connect-multiparty": "^1.2.5", 13 | "cookie-parser": "^1.3.2", 14 | "crypto": "0.0.3", 15 | "csurf": "^1.7.0", 16 | "errorhandler": "*", 17 | "express": "^4.12.3", 18 | "express-cluster": "^0.0.3", 19 | "express-mysql-session": "^0.3.2", 20 | "express-session": "^1.11.1", 21 | "forever-monitor": "^1.5.2", 22 | "gm": "^1.16.0", 23 | "hogan": "^1.0.2", 24 | "log4js": "^0.6.16", 25 | "markdown": "^0.5.0", 26 | "method-override": "^1.0.0", 27 | "mkdirp": "^0.5.0", 28 | "morgan": "^1.0.0", 29 | "mv": "^2.0.3", 30 | "mysql": "^2.5.5", 31 | "nodemailer": "^1.3.0", 32 | "nodemailer-smtp-pool": "^0.1.8", 33 | "orm": "^3.1.0", 34 | "orm-transaction": "0.0.2", 35 | "passport": "^0.2.0", 36 | "passport-local": "^1.0.0", 37 | "path": "^0.4.9", 38 | "rimraf": "^2.2.8", 39 | "serve-favicon": "^2.2.0", 40 | "underscore": "^1.6.0" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /frontend/app/views/partials/admin/forums/forums.new.html: -------------------------------------------------------------------------------- 1 |
2 |

New Forum

3 |
4 |
5 | 6 | 7 |
8 |
9 | 10 | 11 |
12 |
13 | 16 |
17 |
18 |

{{ error }}

19 |
20 |
21 |

{{ message }}

22 |
23 | 24 | 25 | 26 |
27 |
28 | -------------------------------------------------------------------------------- /frontend/app/scripts/controllers/forum.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('frontendApp') 4 | .controller('ForumCtrl', ['$scope', '$state', '$stateParams', 'forums', function ($scope,$state, $stateParams, forums) { 5 | $scope.page = $stateParams.page; 6 | $scope.data = {}; 7 | $scope.conditions = {}; 8 | 9 | $scope.pageChanged = function() { 10 | $scope.searchForums(); 11 | //$state.go('admin.user.home',{page: $scope.page}); 12 | //$location.path('/users/page/'+$scope.page); 13 | }; 14 | 15 | $scope.searchForums = function(form){ 16 | forums.searchForums({ 17 | name: $scope.conditions.name, 18 | description: $scope.conditions.description, 19 | page: $scope.page 20 | }, function(err, data){ 21 | //console.log('>> data:'+ JSON.stringify(data)); 22 | if(!err && err === null) { 23 | $scope.data.forums = data.forums; 24 | $scope.totalItems = data.count; 25 | $scope.page = data.page; 26 | } 27 | }); 28 | }; 29 | 30 | $scope.searchForums(); 31 | }]) 32 | -------------------------------------------------------------------------------- /frontend/app/scripts/controllers/cart.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('frontendApp') 4 | .controller('CartCtrl', ['$scope', '$state', '$stateParams', 'orders', function ($scope, $state, $stateParams, orders) { 5 | $scope.orders = orders; 6 | $scope.data = {}; 7 | 8 | $scope.cart = function(){ 9 | orders.getCart(function(err, order){ 10 | $scope.data.order = order; 11 | //console.log(order); 12 | }); 13 | }; 14 | 15 | $scope.updateCart = function(){ 16 | //console.log($scope.data.order); 17 | orders.updateCart($scope.data.order, function(err, data){ 18 | $scope.data.order = data; 19 | $state.go('carts.list', {}, {reload: true}); 20 | }); 21 | }; 22 | 23 | $scope.deleteLineItem = function(item){ 24 | $scope.data.order.line_items.splice($scope.data.order.line_items.indexOf(item), 1); 25 | $scope.updateCart(); 26 | }; 27 | 28 | $scope.checkout = function(){ 29 | //console.log('>> checkout'); 30 | orders.updateAddressState(function(err, order){ 31 | //console.log(order); 32 | $state.go('orders.address', {id: order.id}); 33 | }); 34 | }; 35 | 36 | $scope.cart(); 37 | }]); 38 | -------------------------------------------------------------------------------- /backend/models/address.js: -------------------------------------------------------------------------------- 1 | module.exports = function(orm, db) { 2 | var Address = db.define('addresses', { 3 | name: { 4 | type: 'text' 5 | }, 6 | address1: { 7 | type: 'text' 8 | }, 9 | address2: { 10 | type: 'text' 11 | }, 12 | zipcode: { 13 | type: 'text' 14 | }, 15 | phone: { 16 | type: 'text' 17 | }, 18 | mobile: { 19 | type: 'text' 20 | }, 21 | created_at: { 22 | type: 'date', 23 | time: true 24 | }, 25 | updated_at: { 26 | type: 'date', 27 | required: true, 28 | time: true 29 | } 30 | 31 | }, { 32 | autoFetch: true, 33 | methods: {}, 34 | validations: {}, 35 | hooks: { 36 | beforeValidation: function() { 37 | this.updated_at = new Date(); 38 | }, 39 | beforeCreate: function () { 40 | this.created_at = new Date(); 41 | } 42 | 43 | } 44 | }); 45 | // creates column 'customer_id' in 'addresses' table 46 | //Address.hasOne('customer', db.models.customers, {reverse: 'addresses',autoFetch: true}); 47 | 48 | }; 49 | -------------------------------------------------------------------------------- /frontend/app/views/partials/admin/forums/forums.edit.html: -------------------------------------------------------------------------------- 1 |
2 |

Edit Forum

3 |
4 |
5 | 6 | 7 |
8 |
9 | 10 | 11 |
12 |
13 | 16 |
17 | 18 |
19 |

{{ error }}

20 |
21 |
22 |

{{ message }}

23 |
24 | 25 | 26 | 27 |
28 |
29 | -------------------------------------------------------------------------------- /frontend/app/scripts/filters/todate.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc filter 5 | * @name frontendApp.filter:toDate 6 | * @function 7 | * @description 8 | * # toDate 9 | * Filter in the frontendApp. 10 | */ 11 | angular.module('frontendApp') 12 | .filter('toDate', function () { 13 | var regexIso8601 = /^(\d{4}|\+\d{6})(?:-(\d{2})(?:-(\d{2})(?:T(\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,}))?(Z|([\-+])(\d{2}):(\d{2}))?)?)?)?$/; 14 | var re = /^(\d{4})(?:-(\d{2})(?:-(\d{2})(?:\s(\d{2}):(\d{2}):(\d{2}))?)?)?$/; 15 | 16 | return function (input) { 17 | if(!input) return null; 18 | var m = input.match(re); 19 | if(m) { 20 | //var milliseconds = Date.parse(m[0]) 21 | //if(!isNaN(milliseconds)) return new Date(milliseconds); 22 | console.log('match length: '+ m.length); 23 | if(m.length == 4) return new Date(Date.UTC(m[1],m[2]-1,m[3])); 24 | else if(m.length == 7) return new Date(Date.UTC(m[1],m[2]-1,m[3],m[4],m[5],m[6])); 25 | } else { 26 | m = input.match(regexIso8601); 27 | if(m){ 28 | console.log('regexIso8601 match length: '+ m.length); 29 | if(m.length == 4) return new Date(Date.UTC(m[1],m[2]-1,m[3])); 30 | else if(m.length >= 7) return new Date(Date.UTC(m[1],m[2]-1,m[3],m[4],m[5],m[6])); 31 | } 32 | } 33 | return null; 34 | }; 35 | }); 36 | -------------------------------------------------------------------------------- /frontend/app/views/partials/admin/forums/layout.html: -------------------------------------------------------------------------------- 1 | 18 | 19 |
20 |
21 |
22 |
23 |
24 | 25 |
26 |
27 |
28 |
29 |
30 |
31 | -------------------------------------------------------------------------------- /backend/models/payment_method.js: -------------------------------------------------------------------------------- 1 | module.exports = function(orm, db) { 2 | var PaymentMethod = db.define('payment_methods', { 3 | name: { 4 | type: 'text' 5 | }, 6 | description: { 7 | type: 'text', big: true 8 | }, 9 | active: { 10 | type: 'boolean' 11 | }, 12 | deleted_at: { 13 | type: 'date', time:true 14 | }, 15 | position: { 16 | type: 'integer' 17 | }, 18 | display_on: { 19 | type: 'text' 20 | }, 21 | auto_capture: { 22 | type: 'boolean' 23 | }, 24 | created_at: { 25 | type: 'date', 26 | time: true 27 | }, 28 | updated_at: { 29 | type: 'date', 30 | required: true, 31 | time: true 32 | } 33 | 34 | }, { 35 | autoFetch: true, 36 | methods: {}, 37 | validations: {}, 38 | hooks: { 39 | beforeValidation: function() { 40 | this.updated_at = new Date(); 41 | }, 42 | beforeCreate: function () { 43 | this.created_at = new Date(); 44 | } 45 | 46 | } 47 | }); 48 | // creates column 'customer_id' in 'addresses' table 49 | //Address.hasOne('customer', db.models.customers, {reverse: 'addresses',autoFetch: true}); 50 | }; 51 | -------------------------------------------------------------------------------- /frontend/app/views/partials/admin/products/layout.html: -------------------------------------------------------------------------------- 1 | 20 |
21 |
22 |
23 | -------------------------------------------------------------------------------- /frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontend", 3 | "version": "1.0.0", 4 | "dependencies": {}, 5 | "devDependencies": { 6 | "connect-modrewrite": "^0.7.5", 7 | "grunt": "^0.4.1", 8 | "grunt-angular-gettext": "^0.2.15", 9 | "grunt-autoprefixer": "^0.4.0", 10 | "grunt-concurrent": "^0.5.0", 11 | "grunt-connect-proxy": "^0.2.0", 12 | "grunt-contrib-clean": "^0.5.0", 13 | "grunt-contrib-concat": "^0.4.0", 14 | "grunt-contrib-connect": "^0.5.0", 15 | "grunt-contrib-copy": "^0.4.1", 16 | "grunt-contrib-cssmin": "^0.7.0", 17 | "grunt-contrib-htmlmin": "^0.1.3", 18 | "grunt-contrib-imagemin": "^0.3.0", 19 | "grunt-contrib-jshint": "^0.7.1", 20 | "grunt-contrib-livereload": "^0.1.2", 21 | "grunt-contrib-uglify": "^0.2.0", 22 | "grunt-contrib-watch": "^0.6.1", 23 | "grunt-express": "^1.3.3", 24 | "grunt-google-cdn": "^0.2.0", 25 | "grunt-jsbeautifier": "^0.2.7", 26 | "grunt-karma": "^0.8.3", 27 | "grunt-newer": "^0.6.1", 28 | "grunt-ng-annotate": "^0.10.0", 29 | "grunt-rev": "^0.1.0", 30 | "grunt-svgmin": "^0.2.0", 31 | "grunt-usemin": "^2.0.0", 32 | "grunt-wiredep": "^2.0.0", 33 | "jshint-stylish": "^0.1.3", 34 | "karma": "^0.12.31", 35 | "karma-ng-html2js-preprocessor": "^0.1.0", 36 | "karma-ng-scenario": "^0.1.0", 37 | "load-grunt-tasks": "^0.4.0", 38 | "time-grunt": "^0.2.1" 39 | }, 40 | "engines": { 41 | "node": ">=0.10.0" 42 | }, 43 | "scripts": { 44 | "test": "grunt test" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /backend/models/taxonomy.js: -------------------------------------------------------------------------------- 1 | module.exports = function(orm, db) { 2 | var Taxonomy = db.define('taxonomies', { 3 | 4 | name: { 5 | type: 'text' 6 | }, 7 | position: { 8 | type: 'integer', 9 | required: true, 10 | defaultValue: 0 11 | }, 12 | created_at: { 13 | type: 'date', 14 | time: true 15 | }, 16 | updated_at: { 17 | type: 'date', 18 | required: true, 19 | time: true 20 | } 21 | 22 | }, { 23 | cache: false, 24 | autoFetch: true, 25 | autoFetchLimit: 2, 26 | methods: { 27 | 28 | }, 29 | validations: { 30 | 31 | }, 32 | hooks: { 33 | beforeValidation: function () { 34 | this.updated_at = new Date(); 35 | }, 36 | afterLoad: function(){ 37 | 38 | }, 39 | beforeSave: function () { 40 | 41 | }, 42 | beforeCreate: function () { 43 | this.created_at = new Date(); 44 | } 45 | } 46 | 47 | }); 48 | // creates column 'customer_id' in 'users' table 49 | // User.hasOne('customer', db.models.customers, { required: true, reverse:'users', autoFetch: true }); 50 | //Variant.hasOne('product', db.models.products, { reverse: 'variants', autoFetch:false, autoFetchLimit:1 }); 51 | //Variant.hasOne('product', db.models.products, { autoFetch:true, autoFetchLimit:2 }); 52 | }; -------------------------------------------------------------------------------- /frontend/app/views/partials/resetPasswordMail.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

5 | Mail for password 6 |

7 | 29 | 30 |
31 |
32 |
33 | -------------------------------------------------------------------------------- /backend/models/article.js: -------------------------------------------------------------------------------- 1 | //var async = require('async'); 2 | 3 | module.exports = function(orm, db) { 4 | var Article = db.define('articles', { 5 | 6 | name: { 7 | type: 'text', 8 | required: true 9 | }, 10 | summary: { 11 | type: 'text' 12 | }, 13 | content: { 14 | type: 'text', big: true 15 | }, 16 | img_url: { 17 | type: 'text' 18 | }, 19 | user_id: { 20 | type: 'integer' 21 | }, 22 | created_at: { 23 | type: 'date', 24 | time: true 25 | }, 26 | updated_at: { 27 | type: 'date', 28 | required: true, 29 | time: true 30 | } 31 | 32 | }, { 33 | //cache: false, 34 | autoFetch: false, 35 | autoFetchLimit: 1, 36 | methods: { 37 | }, 38 | validations: { 39 | }, 40 | hooks: { 41 | beforeValidation: function () { 42 | this.updated_at = new Date(); 43 | }, 44 | afterLoad: function () { 45 | 46 | }, 47 | beforeSave: function () { 48 | 49 | }, 50 | beforeCreate: function () { 51 | this.created_at = new Date(); 52 | } 53 | } 54 | 55 | }); 56 | // creates column 'user_id' in 'articles' table 57 | Article.hasOne('user', db.models.users, {}); 58 | //Article.hasMany('products', db.models.products, {}, {}); 59 | 60 | }; 61 | -------------------------------------------------------------------------------- /frontend/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontend", 3 | "version": "1.0.0", 4 | "dependencies": { 5 | "ng-file-upload-shim": "^4.0.4", 6 | "angular": "^1.4.0", 7 | "json3": "^3.3.2", 8 | "es5-shim": "^4.1.1", 9 | "jquery": "^2.1.3", 10 | "bootstrap": "^3.3.4", 11 | "angular-resource": "^1.4.0", 12 | "angular-cookies": "^1.4.0", 13 | "angular-sanitize": "^1.4.0", 14 | "angular-ui-router": "^0.2.14", 15 | "angular-bootstrap": "^0.12.1", 16 | "angular-ui-select2": "~0.0.5", 17 | "angular-ui-sortable": "^0.13.3", 18 | "jquery-ui": "^1.11.4", 19 | "angular-ui-tree": "^2.3.0", 20 | "ng-file-upload": "^4.0.4", 21 | "angular-i18n": "^1.4.0", 22 | "markdown": "^0.6.0", 23 | "bootstrap-markdown": "^2.9.0", 24 | "fontawesome": "^4.3.0", 25 | "angular-fontawesome": "^0.3.2", 26 | "angular-gettext": "^2.0.5", 27 | "zeroclipboard": "^2.2.0", 28 | "ng-clip": "^0.2.6", 29 | "angular-markdown-filter": "^1.2.0", 30 | "angular-treeview": "*", 31 | "ng-idle": "^1.0.4", 32 | "angular-relative-date": "~1.0.0", 33 | "angular-dynamic-locale": "~0.1.27", 34 | "angular-translate": "~2.7.0", 35 | "angular-local-storage": "~0.2.0", 36 | "angular-translate-loader-partial": "~2.7.0", 37 | "angular-translate-storage-cookie": "~2.7.0", 38 | "angular-translate-storage-local": "~2.7.0" 39 | }, 40 | "devDependencies": { 41 | "angular-mocks": "^1.4.0", 42 | "angular-scenario": "^1.4.0" 43 | }, 44 | "resolutions": { 45 | "angular": "1.4.10" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /frontend/karma-e2e.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | // http://karma-runner.github.io/0.10/config/configuration-file.html 3 | 4 | module.exports = function(config) { 5 | config.set({ 6 | // base path, that will be used to resolve files and exclude 7 | basePath: '', 8 | 9 | // testing framework to use (jasmine/mocha/qunit/...) 10 | frameworks: ['ng-scenario'], 11 | 12 | // list of files / patterns to load in the browser 13 | files: [ 14 | 'test/e2e/**/*.js' 15 | ], 16 | 17 | // list of files / patterns to exclude 18 | exclude: [], 19 | 20 | // web server port 21 | port: 8080, 22 | 23 | // level of logging 24 | // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG 25 | logLevel: config.LOG_INFO, 26 | 27 | 28 | // enable / disable watching file and executing tests whenever any file changes 29 | autoWatch: false, 30 | 31 | 32 | // Start these browsers, currently available: 33 | // - Chrome 34 | // - ChromeCanary 35 | // - Firefox 36 | // - Opera 37 | // - Safari (only Mac) 38 | // - PhantomJS 39 | // - IE (only Windows) 40 | browsers: ['Chrome'], 41 | 42 | 43 | // Continuous Integration mode 44 | // if true, it capture browsers, run tests and exit 45 | singleRun: false 46 | 47 | // Uncomment the following lines if you are using grunt's server to run the tests 48 | // proxies: { 49 | // '/': 'http://localhost:9000/' 50 | // }, 51 | // URL root prevent conflicts with the site root 52 | // urlRoot: '_karma_' 53 | }); 54 | }; 55 | -------------------------------------------------------------------------------- /frontend/app/views/partials/admin/orders/orders.state_changes.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 | Menu 7 | 12 |
13 |
14 | 15 |
16 |
17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 |
NamePrevious StateNext StateBy UserCreated At
{{change.name}}{{change.previous_state}}{{change.next_state}}{{change.user.email}}{{change.created_at}}
39 |
40 |
41 |
42 | 43 |
44 | -------------------------------------------------------------------------------- /backend/models/message.js: -------------------------------------------------------------------------------- 1 | //var async = require('async'); 2 | 3 | module.exports = function(orm, db) { 4 | var Message = db.define('messages', { 5 | 6 | content: { 7 | type: 'text', big: true, 8 | required: true 9 | }, 10 | root: { 11 | type: 'boolean', defaultValue: false 12 | }, 13 | user_id: { 14 | type: 'integer' 15 | }, 16 | ticket_id: { 17 | type: 'integer' 18 | }, 19 | ipaddress: { 20 | type: 'text' 21 | }, 22 | created_at: { 23 | type: 'date', 24 | time: true 25 | }, 26 | updated_at: { 27 | type: 'date', 28 | required: true, 29 | time: true 30 | } 31 | 32 | }, { 33 | //cache: false, 34 | autoFetch: false, 35 | autoFetchLimit: 1, 36 | methods: { 37 | }, 38 | validations: { 39 | }, 40 | hooks: { 41 | beforeValidation: function () { 42 | this.updated_at = new Date(); 43 | }, 44 | afterLoad: function () { 45 | 46 | }, 47 | beforeSave: function () { 48 | 49 | }, 50 | beforeCreate: function () { 51 | this.created_at = new Date(); 52 | } 53 | } 54 | 55 | }); 56 | Message.hasOne('user', db.models.users, { }); 57 | // creates column 'ticket_id' in 'messages' table 58 | Message.hasOne('ticket', db.models.tickets, { reverse:'messages', cascadeRemove:true }); 59 | 60 | }; 61 | -------------------------------------------------------------------------------- /frontend/app/views/partials/include/upload.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 |
6 | 7 |
8 |
9 |
10 |
11 |
12 |
13 | 14 |
15 |
16 |
17 |
18 | 19 |
20 |
21 |
22 |
23 |

{{ error }}

24 |
25 |
26 |

{{ message }}

27 |
28 |
29 | 30 |
31 |
32 |
33 |
-------------------------------------------------------------------------------- /backend/models/state_change.js: -------------------------------------------------------------------------------- 1 | module.exports = function(orm, db) { 2 | var StateChange = db.define('state_changes', { 3 | 4 | name: { 5 | type: 'text' 6 | }, 7 | previous_state: { 8 | type: 'text' 9 | }, 10 | next_state: { 11 | type: 'text' 12 | 13 | }, 14 | order_id: { 15 | type: 'integer' 16 | }, 17 | user_id: { 18 | type: 'integer' 19 | }, 20 | created_at: { 21 | type: 'date', 22 | time: true 23 | }, 24 | updated_at: { 25 | type: 'date', 26 | required: true, 27 | time: true 28 | } 29 | 30 | }, { 31 | //cache: false, 32 | autoFetch: true, 33 | methods: { 34 | 35 | }, 36 | validations: { 37 | }, 38 | hooks: { 39 | beforeValidation: function () { 40 | this.updated_at = new Date(); 41 | }, 42 | afterLoad: function () { 43 | 44 | }, 45 | beforeSave: function () { 46 | 47 | }, 48 | beforeCreate: function () { 49 | this.created_at = new Date(); 50 | } 51 | } 52 | 53 | }); 54 | // creates column 'customer_id' in 'users' table 55 | // User.hasOne('customer', db.models.customers, { required: true, reverse:'users', autoFetch: true }); 56 | StateChange.hasOne('order', db.models.orders, { reverse: 'stateChanges'}); 57 | //StateChange.hasMany('users', db.models.users, {}, {key:true}); 58 | //StateChange.sync(); 59 | }; -------------------------------------------------------------------------------- /frontend/app/views/partials/supports/tickets.edit.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |

Edit Message

5 |
6 |
7 | 8 | 9 | 15 |
16 |
17 | 18 |
19 |

{{ error }}

20 |
21 |
22 |

{{ message }}

23 |
24 | 25 | 26 | 27 |
28 |
29 |
30 | -------------------------------------------------------------------------------- /frontend/app/views/partials/admin/supports/tickets.edit.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |

Edit Message

5 |
6 |
7 | 8 | 9 | 15 |
16 |
17 | 18 |
19 |

{{ error }}

20 |
21 |
22 |

{{ message }}

23 |
24 | 25 | 26 | 27 |
28 |
29 |
30 | -------------------------------------------------------------------------------- /backend/models/option_type.js: -------------------------------------------------------------------------------- 1 | module.exports = function(orm, db) { 2 | var OptionType = db.define('option_types', { 3 | 4 | name: { 5 | type: 'text' 6 | }, 7 | presentation: { 8 | type: 'text' 9 | }, 10 | position: { 11 | type: 'integer', 12 | required: true, 13 | defaultValue: 0 14 | }, 15 | created_at: { 16 | type: 'date', 17 | time: true 18 | }, 19 | updated_at: { 20 | type: 'date', 21 | required: true, 22 | time: true 23 | } 24 | 25 | }, { 26 | cache: false, 27 | autoFetch: true, 28 | //autoFetchLimit: 1, 29 | methods: { 30 | 31 | }, 32 | validations: { 33 | 34 | }, 35 | hooks: { 36 | beforeValidation: function () { 37 | this.updated_at = new Date(); 38 | }, 39 | afterLoad: function(){ 40 | 41 | }, 42 | beforeSave: function () { 43 | 44 | }, 45 | beforeCreate: function () { 46 | this.created_at = new Date(); 47 | } 48 | } 49 | 50 | }); 51 | // creates column 'customer_id' in 'users' table 52 | // User.hasOne('customer', db.models.customers, { required: true, reverse:'users', autoFetch: true }); 53 | //Variant.hasOne('product', db.models.products, { reverse: 'variants', autoFetch:false, autoFetchLimit:1 }); 54 | //Variant.hasOne('product', db.models.products, { autoFetch:true, autoFetchLimit:2 }); 55 | //OptionType.hasMany('products', db.models.products, {}, {}); 56 | 57 | }; -------------------------------------------------------------------------------- /frontend/app/views/partials/supports/tickets.new.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | Back 4 |
5 |
6 | 7 |
8 |
9 |

New Ticket

10 |
11 | 12 |
13 | 14 | 15 |
16 |
17 | 18 | 19 |
20 | 21 |
22 | 23 |
24 |

Progress... {{ progress }}%

25 |
26 |
27 |

{{ error }}

28 |
29 |
30 |

{{ message }}

31 |
32 | 33 | 34 | 35 |
36 |
37 |
38 | -------------------------------------------------------------------------------- /frontend/app/scripts/services/rememberfactory.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var services = angular.module('frontendApp'); 4 | // Create a cookie that expires in a year 5 | services.factory('$remember', function () { 6 | function fetchValue(name){ 7 | var gCookieVal = document.cookie.split("; "); 8 | for(var i = 0; i < gCookieVal.length; i++){ 9 | // a name/value pair (a crumb) is separated by an equal sign 10 | var gCrumb = gCookieVal[i].split("="); 11 | if(name === gCrumb[0]){ 12 | var value = ''; 13 | try { 14 | value = angular.fromJson(gCrumb[1]); 15 | } catch(e){ 16 | value = unescape(gCrumb[1]); 17 | } 18 | return value; 19 | } 20 | } 21 | // a cookie with the requested name does not exist 22 | return null; 23 | } 24 | // Public API here 25 | return function(name, values){ 26 | if(arguments.length === 1) return fetchValue(name); 27 | var cookie = name + "="; 28 | if(typeof values === "object"){ 29 | var expires = ''; 30 | cookie += (typeof values.value === "object")? angular.toJson(values.value) + ';' : values.value + ';'; 31 | if(values.expires){ 32 | var date = new Date(); 33 | date.setTime( date.getTime() +(values.expires * 24 * 60 * 60 *1000)); 34 | expires = date.toGMTString(); 35 | } 36 | cookie += (!values.session)? 'expires=' + expires + ';' : ''; 37 | cookie += (values.path)? 'path=' + values.path + ';' : ''; 38 | cookie += (values.secure)? 'secure' : ''; 39 | } else { 40 | cookie += values + ';'; 41 | } 42 | document.cookie = cookie; 43 | }; 44 | }); 45 | -------------------------------------------------------------------------------- /backend/models/ticket.js: -------------------------------------------------------------------------------- 1 | //var async = require('async'); 2 | 3 | module.exports = function(orm, db) { 4 | var Ticket = db.define('tickets', { 5 | 6 | subject: { 7 | type: 'text', 8 | required: true 9 | }, 10 | status: { 11 | type: 'enum', values: ['request', 'feedback'] 12 | }, 13 | user_id: { 14 | type: 'integer' 15 | }, 16 | views: { 17 | type: 'integer', defaultValue: 0 18 | }, 19 | replies: { 20 | type: 'integer', defaultValue: 0 21 | }, 22 | last_reply_id: { 23 | type: 'integer' 24 | }, 25 | last_replier_id: { 26 | type: 'integer' 27 | }, 28 | created_at: { 29 | type: 'date', 30 | time: true 31 | }, 32 | updated_at: { 33 | type: 'date', 34 | required: true, 35 | time: true 36 | } 37 | 38 | }, { 39 | //cache: false, 40 | autoFetch: false, 41 | autoFetchLimit: 1, 42 | methods: { 43 | }, 44 | validations: { 45 | }, 46 | hooks: { 47 | beforeValidation: function () { 48 | this.updated_at = new Date(); 49 | }, 50 | afterLoad: function () { 51 | 52 | }, 53 | beforeSave: function () { 54 | 55 | }, 56 | beforeCreate: function () { 57 | this.created_at = new Date(); 58 | } 59 | } 60 | 61 | }); 62 | // creates column 'user_id' in 'topics' table 63 | Ticket.hasOne('user', db.models.users, { }); 64 | 65 | }; 66 | -------------------------------------------------------------------------------- /backend/models/payment.js: -------------------------------------------------------------------------------- 1 | module.exports = function(orm, db) { 2 | var Payment = db.define('payments', { 3 | amount: { 4 | type: 'number' 5 | }, 6 | order_id: { 7 | type: 'integer' 8 | }, 9 | payment_method_id: { 10 | type: 'integer' 11 | }, 12 | state: { 13 | type: 'text' 14 | }, 15 | response_code: { 16 | type: 'text' 17 | }, 18 | avs_response: { 19 | type: 'text' 20 | }, 21 | identifier: { 22 | type: 'text' 23 | }, 24 | cvv_response_code: { 25 | type: 'text' 26 | }, 27 | cvv_response_message: { 28 | type: 'text' 29 | }, 30 | uncaptured_amount: { 31 | type: 'number' 32 | }, 33 | created_at: { 34 | type: 'date', 35 | time: true 36 | }, 37 | updated_at: { 38 | type: 'date', 39 | required: true, 40 | time: true 41 | } 42 | 43 | }, { 44 | autoFetch: true, 45 | autoFetchLimit: 2, 46 | methods: {}, 47 | validations: {}, 48 | hooks: { 49 | beforeValidation: function() { 50 | this.updated_at = new Date(); 51 | }, 52 | beforeCreate: function () { 53 | this.created_at = new Date(); 54 | } 55 | 56 | } 57 | }); 58 | // creates column 'order_id' in 'payments' table 59 | Payment.hasOne('order', db.models.orders, {reverse: 'payments'}); 60 | Payment.hasOne('payment_method', db.models.payment_methods); 61 | //Payment.sync(); 62 | }; 63 | -------------------------------------------------------------------------------- /frontend/app/scripts/controllers/signup.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('frontendApp') 4 | .controller('SignupCtrl', ['$scope', 'AuthFactory', '$location', 5 | function($scope, AuthFactory, $location) { 6 | $scope.register = function(form) { 7 | AuthFactory.createUser({ 8 | email: $scope.user.email, 9 | password: $scope.user.password, 10 | retype_password: $scope.user.retype_password, 11 | role: AuthFactory.userRoles.user 12 | }, 13 | function(errors) { 14 | $scope.errors = {}; 15 | 16 | if(errors) { 17 | //console.log(errors); 18 | if(!angular.isArray(errors)) errors = [errors]; 19 | angular.forEach(errors, function(error) { 20 | var msg = error.msg; 21 | var field = error.property; 22 | if (field === 'encrypted_password') field = 'password'; 23 | //console.log('>> field: ' + field); 24 | //console.log('>> msg: ' + msg); 25 | //console.log(form[field]); 26 | form[field].$setValidity('server', false); 27 | $scope.errors[field] = msg; 28 | }); 29 | 30 | } else { 31 | $location.path('/login'); 32 | } 33 | 34 | } 35 | ); 36 | }; 37 | } 38 | ]); 39 | -------------------------------------------------------------------------------- /backend/models/profile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(orm, db) { 2 | var Profile = db.define('profiles', { 3 | first_name: { 4 | type: 'text', size: 40, 5 | required: true 6 | }, 7 | last_name: { 8 | type: 'text', size: 40, 9 | required: true 10 | }, 11 | nickname: { 12 | type: 'text', size: 40 13 | }, 14 | gender: { 15 | type: 'enum', values:['Male', 'Female', 'Other'] 16 | }, 17 | birth_year: { 18 | type: 'text', size:4 19 | }, 20 | birth_month: { 21 | type: 'text', size:2 22 | }, 23 | birth_day: { 24 | type: 'text', size:2 25 | }, 26 | address_id: { 27 | type: 'integer' 28 | }, 29 | created_at: { 30 | type: 'date', 31 | time: true 32 | }, 33 | updated_at: { 34 | type: 'date', 35 | required: true, 36 | time: true 37 | } 38 | 39 | }, { 40 | cache: false, 41 | autoFetch: true, 42 | autoFetchLimit: 1, 43 | methods: {}, 44 | validations: {}, 45 | hooks: { 46 | beforeValidation: function() { 47 | this.updated_at = new Date(); 48 | }, 49 | beforeCreate: function () { 50 | this.created_at = new Date(); 51 | } 52 | 53 | } 54 | }); 55 | 56 | // creates column 'user_id' in 'customers' table 57 | //Profile.hasOne('user', db.models.users, {}); 58 | Profile.hasOne('address', db.models.addresses, {}); 59 | //Profile.hasMany('addresses', db.models.addresses, {}, {key: true}); 60 | }; 61 | -------------------------------------------------------------------------------- /backend/models/option_value.js: -------------------------------------------------------------------------------- 1 | module.exports = function(orm, db) { 2 | var OptionValue = db.define('option_values', { 3 | 4 | name: { 5 | type: 'text' 6 | }, 7 | presentation: { 8 | type: 'text' 9 | }, 10 | position: { 11 | type: 'integer', 12 | required: true, 13 | defaultValue: 0 14 | }, 15 | option_type_id: { 16 | type: 'integer' 17 | }, 18 | created_at: { 19 | type: 'date', 20 | time: true 21 | }, 22 | updated_at: { 23 | type: 'date', 24 | required: true, 25 | time: true 26 | } 27 | 28 | }, { 29 | //cache: false, 30 | //autoFetch: true, 31 | //autoFetchLimit: 1, 32 | methods: { 33 | 34 | }, 35 | validations: { 36 | 37 | }, 38 | hooks: { 39 | beforeValidation: function () { 40 | this.updated_at = new Date(); 41 | }, 42 | afterLoad: function() { 43 | 44 | }, 45 | beforeSave: function () { 46 | 47 | }, 48 | beforeCreate: function () { 49 | this.created_at = new Date(); 50 | } 51 | } 52 | 53 | }); 54 | // creates column 'customer_id' in 'users' table 55 | // User.hasOne('customer', db.models.customers, { required: true, reverse:'users', autoFetch: true }); 56 | //Variant.hasOne('product', db.models.products, { reverse: 'variants', autoFetch:false, autoFetchLimit:21 }); 57 | OptionValue.hasOne('option_type', db.models.option_types, { reverse: 'option_values', order:'position', sort:'position'}); 58 | //OptionValue.sync(); 59 | }; -------------------------------------------------------------------------------- /frontend/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | // http://karma-runner.github.io/0.10/config/configuration-file.html 3 | 4 | module.exports = function(config) { 5 | config.set({ 6 | // base path, that will be used to resolve files and exclude 7 | basePath: '', 8 | 9 | // testing framework to use (jasmine/mocha/qunit/...) 10 | frameworks: ['jasmine'], 11 | 12 | // list of files / patterns to load in the browser 13 | files: [ 14 | 'app/bower_components/angular/angular.js', 15 | 'app/bower_components/angular-mocks/angular-mocks.js', 16 | 'app/bower_components/angular-resource/angular-resource.js', 17 | 'app/bower_components/angular-cookies/angular-cookies.js', 18 | 'app/bower_components/angular-sanitize/angular-sanitize.js', 19 | 'app/bower_components/angular-route/angular-route.js', 20 | 'app/scripts/*.js', 21 | 'app/scripts/**/*.js', 22 | 'test/mock/**/*.js', 23 | 'test/spec/**/*.js' 24 | ], 25 | 26 | // list of files / patterns to exclude 27 | exclude: [], 28 | 29 | // web server port 30 | port: 8080, 31 | 32 | // level of logging 33 | // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG 34 | logLevel: config.LOG_INFO, 35 | 36 | 37 | // enable / disable watching file and executing tests whenever any file changes 38 | autoWatch: false, 39 | 40 | 41 | // Start these browsers, currently available: 42 | // - Chrome 43 | // - ChromeCanary 44 | // - Firefox 45 | // - Opera 46 | // - Safari (only Mac) 47 | // - PhantomJS 48 | // - IE (only Windows) 49 | browsers: ['Chrome'], 50 | 51 | 52 | // Continuous Integration mode 53 | // if true, it capture browsers, run tests and exit 54 | singleRun: false 55 | }); 56 | }; 57 | -------------------------------------------------------------------------------- /backend/models/line_item.js: -------------------------------------------------------------------------------- 1 | module.exports = function(orm, db) { 2 | var LineItem = db.define('line_items', { 3 | 4 | variant_id: { 5 | type: 'integer' 6 | }, 7 | order_id: { 8 | type: 'integer' 9 | }, 10 | quantity: { 11 | type: 'integer' 12 | }, 13 | price: { 14 | type: 'number' 15 | }, 16 | currency: { 17 | type: 'text' 18 | }, 19 | cost_price: { 20 | type: 'number' 21 | }, 22 | created_at: { 23 | type: 'date', 24 | time: true 25 | }, 26 | updated_at: { 27 | type: 'date', 28 | required: true, 29 | time: true 30 | } 31 | 32 | }, { 33 | //cache: false, 34 | autoFetch: true, 35 | methods: { 36 | 37 | }, 38 | validations: { 39 | }, 40 | hooks: { 41 | beforeValidation: function () { 42 | this.updated_at = new Date(); 43 | }, 44 | afterLoad: function () { 45 | 46 | }, 47 | beforeSave: function () { 48 | 49 | }, 50 | beforeCreate: function () { 51 | this.created_at = new Date(); 52 | } 53 | } 54 | 55 | }); 56 | // creates column 'customer_id' in 'users' table 57 | // User.hasOne('customer', db.models.customers, { required: true, reverse:'users', autoFetch: true }); 58 | // Product.hasMany('option_types', db.models.option_types, {}, { key:true}); 59 | // Product.hasMany('taxons', db.models.taxons,{}, { key:true}); 60 | LineItem.hasOne('order', db.models.orders, {reverse: 'line_items'}); 61 | //LineItem.sync(); //create a join table 'product_option_types' 62 | }; -------------------------------------------------------------------------------- /frontend/README.md: -------------------------------------------------------------------------------- 1 | 2 | ## bootstrap - AngularJS directives specific to Bootstrap 3 | https://github.com/angular-ui/bootstrap 4 | 5 | Install: bower install angular-bootstrap --save 6 | index.html: 7 | 8 | 9 | app.js: 10 | angular.module('myModule', ['ui.bootstrap']); 11 | 12 | ## angular-ui/ui-select2 - An AngularJS wrapper for select2 13 | An AngularJS wrapper for select2 14 | 15 | Install: 16 | $ bower install angular-ui-select2 --save 17 | $ bower install 18 | 19 | app.js: 20 | var myAppModule = angular.module('MyApp', ['ui.select2']); 21 | 22 | ## angular-i18n locale 23 | 24 | $ bower install angular-i18n --save 25 | index.html: 26 | 27 | 28 | ## ng-clip : Copy to clipboard using AngularJS 29 | https://github.com/asafdav/ng-clip 30 | 31 | ## angular-gettext 32 | http://lostechies.com/gabrielschenker/2014/02/11/angularjspart-12-multi-language-support/ 33 | $ bower install angular-gettext --save 34 | Usage: https://lostechies.com/gabrielschenker/2014/02/11/angularjspart-12-multi-language-support/ 35 | 36 | 1. frontend> grunt nggettext_extract 37 | 38 | 2. Open template.pot file and translate text to local language: 39 | virtaal lang/template.pot 40 | 41 | 3. Save to 'lang/ko.po' 42 | 43 | 4. frontend> grunt nggettext_compile 44 | update app/scripts/translations.js file 45 | 46 | ## Run production mode: 47 | // ngminify 48 | $ frontend> grunt build 49 | 50 | ### Ubuntu: 51 | $ backend> NODE_ENV=production ./bin/forever 52 | 53 | ### Windows 54 | // PowerShell 55 | $ backend> $env:NODE_ENV="production" 56 | $ backend> node ./bin/forever 57 | 58 | // cmd.exe 59 | $ backend> set NODE_ENV=production 60 | $ backend> node ./bin/forever 61 | 62 | -------------------------------------------------------------------------------- /backend/models/post.js: -------------------------------------------------------------------------------- 1 | //var async = require('async'); 2 | 3 | module.exports = function(orm, db) { 4 | var Post = db.define('posts', { 5 | 6 | name: { 7 | type: 'text', 8 | required: true 9 | }, 10 | content: { 11 | type: 'text', big: true 12 | }, 13 | root: { 14 | type: 'boolean', defaultValue: false 15 | }, 16 | user_id: { 17 | type: 'integer' 18 | }, 19 | forum_id: { 20 | type: 'integer' 21 | }, 22 | topic_id: { 23 | type: 'integer' 24 | }, 25 | created_at: { 26 | type: 'date', 27 | time: true 28 | }, 29 | updated_at: { 30 | type: 'date', 31 | required: true, 32 | time: true 33 | } 34 | 35 | }, { 36 | //cache: false, 37 | autoFetch: false, 38 | autoFetchLimit: 1, 39 | methods: { 40 | }, 41 | validations: { 42 | }, 43 | hooks: { 44 | beforeValidation: function () { 45 | this.updated_at = new Date(); 46 | }, 47 | afterLoad: function () { 48 | 49 | }, 50 | beforeSave: function () { 51 | 52 | }, 53 | beforeCreate: function () { 54 | this.created_at = new Date(); 55 | } 56 | } 57 | 58 | }); 59 | // creates column 'taxonomy_id' in 'taxons' table 60 | //Post.hasOne('topic', db.models.topics, { reverse:'posts', cascadeRemove:true }); 61 | Post.hasOne('topic', db.models.topics, { reverse:'posts', cascadeRemove:true }); 62 | //Taxon.hasMany('products', db.models.products, {}, {}); 63 | //Post.sync(); //create a join table 'product_taxons' 64 | 65 | }; 66 | -------------------------------------------------------------------------------- /frontend/app/views/main.html: -------------------------------------------------------------------------------- 1 |
2 | 14 |

frontend

15 |
16 | 17 |
18 |

'Allo, 'Allo!

19 |

20 | I'm Yeoman 21 |
Always a pleasure scaffolding your apps. 22 |

23 |

Splendid! 24 |

25 |
26 | 27 | 28 | 29 |
    30 |
  • {{user.email}}
  • 31 |
32 |
33 |
    34 |
  • 35 |
  • 36 |
37 | 38 |
39 |

HTML5 Boilerplate

40 |

41 | HTML5 Boilerplate is a professional front-end template for building fast, robust, and adaptable web apps or sites. 42 |

43 | 44 |

Angular

45 |

46 | AngularJS is a toolset for building the framework most suited to your application development. 47 |

48 | 49 |

Karma

50 |

Spectacular Test Runner for JavaScript.

51 |
52 | 53 | 56 | -------------------------------------------------------------------------------- /frontend/app/scripts/controllers/password.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('frontendApp') 4 | .controller('PasswordCtrl', ['$rootScope', '$scope', 'AuthFactory', '$location', 5 | function($rootScope, $scope, AuthFactory, $location) { 6 | 7 | $scope.user = AuthFactory.user; 8 | 9 | $scope.changePassword = function(form) { 10 | 11 | AuthFactory.changePassword( 12 | $scope.user.email, 13 | $scope.user.password, 14 | $scope.user.new_password, 15 | $scope.user.retype_password, function(errors) { 16 | $scope.errors = {}; 17 | $scope.success = {}; 18 | 19 | if (errors) { 20 | // console.log( err); 21 | angular.forEach(errors, function(error) { 22 | var msg = error.msg; 23 | var field = error.property; 24 | if (field === 'encrypted_password') field = 'password'; 25 | //console.log('>> field: ' + field); 26 | //console.log('>> msg: ' + msg); 27 | //console.log(form[field]); 28 | form[field].$setValidity('server', false); 29 | $scope.errors[field] = msg; 30 | }); 31 | } else { 32 | form['password'].$setValidity('server', true); 33 | $scope.success['password'] = 'Password changed.'; 34 | //$location.path('/'); 35 | } 36 | }); 37 | }; 38 | } 39 | ]); 40 | -------------------------------------------------------------------------------- /frontend/app/views/partials/forums/topics/topics.edit.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |

Edit Post

5 |
6 |
7 | 8 | 9 |
10 |
11 | 12 | 13 | 19 |
20 |
21 | 22 |
23 |

{{ error }}

24 |
25 |
26 |

{{ message }}

27 |
28 | 29 | 30 | 31 |
32 |
33 |
34 | -------------------------------------------------------------------------------- /frontend/app/views/partials/orders/orders.list.html: -------------------------------------------------------------------------------- 1 |
2 |

My Orders

3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
NumberDateStatusPayment StateShipment StateTotal
{{item.number}}{{item.completed_at | date: 'yyyy-MM-dd hh:mm:ss'}}{{item.state}}{{item.payment_state}}{{item.shipment_state}}{{item.total | currency}}
25 |
26 |
Page:{{page}}/{{numPages}} ({{totalItems}})
27 |
28 | 30 |
31 |
32 | 33 | Refresh 34 |
35 |
36 | 37 |
38 | -------------------------------------------------------------------------------- /backend/config/passport.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var passport = require('passport'), 4 | LocalStrategy = require('passport-local').Strategy; 5 | 6 | 7 | module.exports = function(db) { 8 | 9 | var User = db.models.users; 10 | 11 | // Serialize sessions 12 | passport.serializeUser(function(user, done) { 13 | done(null, user.id); 14 | }); 15 | 16 | passport.deserializeUser(function(id, done) { 17 | User.get(id, function(err, user) { 18 | done(err, user); 19 | }); 20 | }); 21 | 22 | // Use local strategy 23 | passport.use(new LocalStrategy({ 24 | usernameField: 'email', 25 | passwordField: 'password' 26 | }, 27 | function(email, password, done) { 28 | User.one({ 29 | email: email 30 | }, function(err, user) { 31 | if (err) { 32 | return done(err); 33 | } 34 | if (!user) { 35 | return done(null, false, { 36 | 'errors': { 37 | 'email': { 38 | type: 'Email is not registered.' 39 | } 40 | } 41 | }); 42 | } 43 | //console.log('>> config pass.js: '); 44 | console.log('>> user: '); console.log(JSON.stringify(user)); 45 | if (!user.authenticate(password)) { 46 | return done(null, false, { 47 | 'errors': { 48 | 'password': { 49 | type: 'Password is incorrect.' 50 | } 51 | } 52 | }); 53 | } 54 | return done(null, user); 55 | }); 56 | } 57 | )); 58 | }; 59 | -------------------------------------------------------------------------------- /backend/models/shipping_method.js: -------------------------------------------------------------------------------- 1 | module.exports = function(orm, db) { 2 | var ShippingMethod = db.define('shipping_methods', { 3 | 4 | name: { 5 | type: 'text' 6 | }, 7 | display_on: { 8 | type: 'text' 9 | }, 10 | deleted_at: { 11 | type: 'date', 12 | time: true 13 | }, 14 | amount: { 15 | type: 'number' 16 | }, 17 | currency: { 18 | type: 'text' 19 | }, 20 | position: { 21 | type: 'integer', 22 | required: true, 23 | defaultValue: 0 24 | }, 25 | created_at: { 26 | type: 'date', 27 | time: true 28 | }, 29 | updated_at: { 30 | type: 'date', 31 | required: true, 32 | time: true 33 | } 34 | 35 | }, { 36 | //cache: false, 37 | autoFetch: true, 38 | methods: { 39 | 40 | }, 41 | validations: { 42 | 43 | }, 44 | hooks: { 45 | beforeValidation: function () { 46 | this.updated_at = new Date(); 47 | }, 48 | afterLoad: function(){ 49 | 50 | }, 51 | beforeSave: function () { 52 | 53 | }, 54 | beforeCreate: function () { 55 | this.created_at = new Date(); 56 | } 57 | } 58 | 59 | }); 60 | // creates column 'customer_id' in 'users' table 61 | // User.hasOne('customer', db.models.customers, { required: true, reverse:'users', autoFetch: true }); 62 | //Variant.hasOne('product', db.models.products, { reverse: 'variants', autoFetch:false, autoFetchLimit:1 }); 63 | //Variant.hasOne('product', db.models.products, { autoFetch:true, autoFetchLimit:2 }); 64 | //OptionType.hasMany('products', db.models.products, {}, {}); 65 | //OptionType.sync(); 66 | }; -------------------------------------------------------------------------------- /frontend/app/scripts/services/sessionfactory.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var services = angular.module('frontendApp'); 4 | services.factory('SessionFactory', ['$resource', '$http', function($resource, $http) { 5 | return $resource('/auth/session'); 6 | //var resource = $resource('/auth/session',{ }, {update: {method: 'PUT'}}); 7 | //return { 8 | // save: function(data, success, fail){ 9 | // var success = success || angular.noop; 10 | // var fail = fail || angular.noop; 11 | // resource.save(data, function (session) { 12 | // return success(session); 13 | // }, function (err) { 14 | // return fail(err); 15 | // }); 16 | // }, 17 | // remove: function(success, fail){ 18 | // var success = success || angular.noop; 19 | // var fail = fail || angular.noop; 20 | // //resource.remove(function (session) { 21 | // // return success(session); 22 | // //}, function (err) { 23 | // // return fail(err); 24 | // //}); 25 | // $http.delete('/auth/session') 26 | // .success(function (data, status, headers, config) { 27 | // console.log('>> status:' + status); 28 | // return success( data); 29 | // }).error(function (data, status, headers, config) { 30 | // console.log('>> headers: '+ JSON.stringify(headers)); 31 | // console.log('>> error data:' + JSON.stringify(data)); 32 | // // called asynchronously if an error occurs 33 | // // or server returns response with an error status. 34 | // return fail( data); 35 | // }); 36 | // 37 | // } 38 | //}; 39 | } 40 | ]); 41 | -------------------------------------------------------------------------------- /backend/models/topic.js: -------------------------------------------------------------------------------- 1 | //var async = require('async'); 2 | 3 | module.exports = function(orm, db) { 4 | var Topic = db.define('topics', { 5 | 6 | name: { 7 | type: 'text', 8 | required: true 9 | }, 10 | forum_id: { 11 | type: 'integer' 12 | }, 13 | user_id: { 14 | type: 'integer' 15 | }, 16 | views: { 17 | type: 'integer', defaultValue: 0 18 | }, 19 | replies: { 20 | type: 'integer', defaultValue: 0 21 | }, 22 | last_post_id: { 23 | type: 'integer' 24 | }, 25 | last_poster_id: { 26 | type: 'integer' 27 | }, 28 | locked: { 29 | type: 'boolean', defaultValue: 0 30 | }, 31 | sticky: { 32 | type: 'boolean', defaultValue: 0 33 | }, 34 | created_at: { 35 | type: 'date', 36 | time: true 37 | }, 38 | updated_at: { 39 | type: 'date', 40 | required: true, 41 | time: true 42 | } 43 | 44 | }, { 45 | //cache: false, 46 | autoFetch: true, 47 | autoFetchLimit: 1, 48 | methods: { 49 | }, 50 | validations: { 51 | }, 52 | hooks: { 53 | beforeValidation: function () { 54 | this.updated_at = new Date(); 55 | }, 56 | afterLoad: function () { 57 | 58 | }, 59 | beforeSave: function () { 60 | 61 | }, 62 | beforeCreate: function () { 63 | this.created_at = new Date(); 64 | } 65 | } 66 | 67 | }); 68 | // creates column 'taxonomy_id' in 'taxons' table 69 | Topic.hasOne('forum', db.models.forums, { cascadeRemove:true }); 70 | Topic.hasOne('user', db.models.users, { }); 71 | //Topic.sync(); //create a join table 'product_taxons' 72 | 73 | 74 | }; 75 | -------------------------------------------------------------------------------- /backend/models/product.js: -------------------------------------------------------------------------------- 1 | module.exports = function(orm, db) { 2 | var Product = db.define('products', { 3 | 4 | name: { 5 | type: 'text' 6 | }, 7 | properties: { 8 | type: 'text', big: true 9 | }, 10 | description: { 11 | type: 'text', big: true 12 | }, 13 | available_on: { 14 | type: 'date', 15 | time: false 16 | }, 17 | deleted_at: { 18 | type: 'date', 19 | time: true 20 | }, 21 | slug: { 22 | type: 'text' 23 | }, 24 | meta_description: { 25 | type: 'text' 26 | }, 27 | meta_keywords: { 28 | type: 'text' 29 | }, 30 | // taxon_ids: { 31 | // type: 'text' 32 | // }, 33 | created_at: { 34 | type: 'date', 35 | time: true 36 | }, 37 | updated_at: { 38 | type: 'date', 39 | required: true, 40 | time: true 41 | } 42 | 43 | }, { 44 | //cache: false, 45 | autoFetch: true, 46 | autoFetchLimit: 1, 47 | methods: { 48 | 49 | }, 50 | validations: { 51 | }, 52 | hooks: { 53 | beforeValidation: function () { 54 | this.updated_at = new Date(); 55 | }, 56 | afterLoad: function () { 57 | 58 | }, 59 | beforeSave: function () { 60 | 61 | }, 62 | beforeCreate: function () { 63 | this.created_at = new Date(); 64 | } 65 | } 66 | 67 | }); 68 | // creates column 'customer_id' in 'users' table 69 | // User.hasOne('customer', db.models.customers, { required: true, reverse:'users', autoFetch: true }); 70 | Product.hasMany('option_types', db.models.option_types, {}, { key:true}); 71 | Product.hasMany('taxons', db.models.taxons,{}, { key:true}); 72 | 73 | }; -------------------------------------------------------------------------------- /backend/models/shipment.js: -------------------------------------------------------------------------------- 1 | module.exports = function(orm, db) { 2 | var Shipment = db.define('shipments', { 3 | tracking: { 4 | type: 'text' 5 | }, 6 | number: { 7 | type: 'text' 8 | }, 9 | cost: { 10 | type: 'number' 11 | }, 12 | shipped_at: { 13 | type: 'date', time: true 14 | }, 15 | order_id: { 16 | type: 'integer' 17 | }, 18 | address_id: { 19 | type: 'integer' 20 | }, 21 | shipping_method_id: { 22 | type: 'integer' 23 | }, 24 | state: { 25 | type: 'text' 26 | }, 27 | created_at: { 28 | type: 'date', 29 | time: true 30 | }, 31 | updated_at: { 32 | type: 'date', 33 | required: true, 34 | time: true 35 | } 36 | 37 | }, { 38 | autoFetch: true, 39 | autoFetchLimit: 2, 40 | methods: {}, 41 | validations: {}, 42 | hooks: { 43 | beforeValidation: function() { 44 | this.updated_at = new Date(); 45 | }, 46 | beforeCreate: function () { 47 | this.created_at = new Date(); 48 | } 49 | 50 | } 51 | }); 52 | 53 | // Returns a random integer between min (included) and max (excluded) 54 | // Using Math.round() will give you a non-uniform distribution! 55 | Shipment.getRandomInt = function(min, max) { 56 | return Math.floor(Math.random() * (max - min)) + min; 57 | }; 58 | Shipment.makeNumber = function(){ 59 | return 'H'+ this.getRandomInt(1000000000, 10000000000); 60 | }; 61 | 62 | // creates column 'order_id' in 'payments' table 63 | Shipment.hasOne('order', db.models.orders, {reverse: 'shipments'}); 64 | Shipment.hasOne('shipping_method', db.models.shipping_methods); 65 | //Shipment.hasOne('address', db.models.addresses); 66 | //Shipment.sync(); 67 | }; 68 | -------------------------------------------------------------------------------- /frontend/app/views/partials/taxons/taxons.products.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 |
7 | 8 |
9 |
10 | 11 |
12 |
13 |
14 |
15 |
16 | 17 |
18 | 33 |
34 | 35 | 36 |
37 |
Page:{{page}}/{{numPages}} ({{totalItems}})
38 |
39 | 41 |
42 |
43 | 44 | Refresh 45 |
46 |
47 |
48 |
49 | -------------------------------------------------------------------------------- /frontend/app/views/partials/news/news.new.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | Back 4 |     5 |
6 |
7 |
8 |
9 |
10 |

New Article

11 |
12 |
13 | 14 | 15 |
16 |
17 | 18 | 19 |
20 |
21 | 22 | 23 |
24 |
25 | 26 | 27 |
28 | 29 |
30 | 31 |
32 |

Progress... {{ progress }}%

33 |
34 |
35 |

{{ error }}

36 |
37 |
38 |

{{ message }}

39 |
40 | 41 | 42 | 43 |
44 |
45 |
46 |
47 | -------------------------------------------------------------------------------- /frontend/app/views/partials/news/news.edit.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |

Edit Article

5 |
6 |
7 | 8 | 9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 | 27 |
28 |
29 | 30 |
31 |

{{ error }}

32 |
33 |
34 |

{{ message }}

35 |
36 | 37 | 38 | 39 |
40 |
41 |
42 | -------------------------------------------------------------------------------- /frontend/app/scripts/controllers/product.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('frontendApp') 4 | .controller('ProductCtrl', ['$scope', '$state', '$stateParams', 'products', function ($scope, $state, $stateParams, products) { 5 | $scope.data = {}; 6 | $scope.conditions = {}; 7 | $scope.page = $stateParams.page; 8 | 9 | $scope.listProducts = function(){ 10 | $scope.conditions.page = $scope.page; 11 | products.listProducts($scope.conditions,function(err, data){ 12 | if(!err){ 13 | //console.log(data); 14 | $scope.data.products = data.products; 15 | $scope.totalItems = data.count; 16 | $scope.page = data.page; 17 | } 18 | }); 19 | }; 20 | $scope.pageChanged = function() { 21 | $scope.listProducts(); 22 | //$state.go('admin.user.home',{page: $scope.page}); 23 | //$location.path('/users/page/'+$scope.page); 24 | }; 25 | 26 | $scope.listProducts(); 27 | }]) 28 | .controller('ViewProductCtrl', ['$scope', '$state', '$stateParams', '$filter','AuthFactory', 'products', function ($scope, $state, $stateParams, $filter, AuthFactory, products) { 29 | $scope.data = {}; 30 | $scope.product = { 31 | quantity: 1 32 | }; 33 | $scope.mainImage = ''; 34 | 35 | products.viewProduct({id: $stateParams.id},function(err, data){ 36 | $scope.data.product = data.product; 37 | $scope.data.variants = data.variants; 38 | if(data.variants) $scope.product.variant = data.variants[0]; 39 | $scope.data.assets = $filter('orderBy')(data.assets, ['position', 'id']) ; 40 | //console.log( $scope.data.assets); 41 | if($scope.data.assets) $scope.mainImage = '/uploads/images/'+ $scope.data.assets[0].file_path; 42 | //console.log(data); 43 | }); 44 | 45 | $scope.addToCart = function(){ 46 | //console.log($scope.product); 47 | if(!AuthFactory.authorize('user')) return $state.go('anon.login'); 48 | 49 | products.addToCart($scope.product, function(err, data){ 50 | $state.go('carts.list'); 51 | }); 52 | }; 53 | 54 | $scope.viewImage = function(path){ 55 | $scope.mainImage = '/uploads/images/' + path; 56 | }; 57 | 58 | 59 | }]); 60 | -------------------------------------------------------------------------------- /backend/models/variant.js: -------------------------------------------------------------------------------- 1 | module.exports = function(orm, db) { 2 | var Variant = db.define('variants', { 3 | 4 | sku: { 5 | type: 'text', 6 | required: true 7 | }, 8 | weight: { 9 | type: 'number' 10 | }, 11 | height: { 12 | type: 'number' 13 | 14 | }, 15 | width: { 16 | type: 'number' 17 | }, 18 | depth: { 19 | type: 'number' 20 | }, 21 | is_master: { 22 | type: 'boolean' 23 | }, 24 | deleted_at:{ 25 | type: 'date', 26 | time: true 27 | }, 28 | product_id: { 29 | type: 'integer' 30 | }, 31 | price: { 32 | type: 'number' 33 | }, 34 | cost_price: { 35 | type: 'number' 36 | }, 37 | cost_currency: { 38 | type: 'text' 39 | }, 40 | position: { 41 | type: 'integer' 42 | }, 43 | track_inventory: { 44 | type: 'boolean' 45 | }, 46 | tax_category_id: { 47 | type: 'integer' 48 | }, 49 | updated_at: { 50 | type: 'date', 51 | required: true, 52 | time: true 53 | } 54 | 55 | }, { 56 | //cache: false, 57 | autoFetch: true, 58 | autoFetchLimit: 1, 59 | methods: { 60 | 61 | }, 62 | validations: { 63 | }, 64 | hooks: { 65 | beforeValidation: function () { 66 | this.updated_at = new Date(); 67 | }, 68 | afterLoad: function () { 69 | 70 | }, 71 | beforeSave: function () { 72 | 73 | }, 74 | beforeCreate: function () { 75 | //this.created_at = new Date(); 76 | } 77 | } 78 | 79 | }); 80 | // creates column 'customer_id' in 'users' table 81 | // User.hasOne('customer', db.models.customers, { required: true, reverse:'users', autoFetch: true }); 82 | Variant.hasOne('product', db.models.products, { reverse: 'variants'}); 83 | Variant.hasMany('option_values', db.models.option_values, {}, { key:true}); 84 | //Variant.sync(); 85 | }; -------------------------------------------------------------------------------- /frontend/app/views/partials/admin/shipping_methods/shipping_methods.edit.html: -------------------------------------------------------------------------------- 1 |

Editing Shipping Method: {{shippingMethod.name}}

2 | 3 |
4 |
5 |
6 |
7 |
8 | 9 |
10 |
11 |
12 | 13 |
14 |
15 |
16 | 17 |
18 |
19 |
20 |
21 |
22 |
23 |

{{ error }}

24 |
25 |
26 |

{{ message }}

27 |
28 | 29 |
30 |
31 |
32 |
33 | 34 |
35 |
36 | 37 | Back 38 | 39 | Refresh 40 |
41 |
42 |
43 |
-------------------------------------------------------------------------------- /frontend/app/views/partials/admin/payment_methods/payment_methods.edit.html: -------------------------------------------------------------------------------- 1 |

Editing Payment Method: {{paymentMethod.name}}

2 | 3 |
4 |
5 |
6 |
7 |
8 | 9 |
10 |
11 |
12 | 13 |
14 |
15 |
16 | 17 |
18 |
19 |
20 |
21 |
22 |
23 |

{{ error }}

24 |
25 |
26 |

{{ message }}

27 |
28 | 29 |
30 |
31 |
32 |
33 | 34 |
35 |
36 | 37 | Back 38 | 39 | Refresh 40 |
41 |
42 |
43 |
44 | -------------------------------------------------------------------------------- /frontend/app/views/partials/login.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

5 | Sign in 6 |

7 | 37 | 38 |
39 | Forgot password? 40 |
41 |
42 |
43 | -------------------------------------------------------------------------------- /backend/models/role.js: -------------------------------------------------------------------------------- 1 | var log = require('log4js').getLogger("roles model"); 2 | var userRoles = require('../../frontend/app/scripts/common/routingConfig').userRoles; 3 | var async = require('async'); 4 | 5 | module.exports = function(orm, db) { 6 | var Role = db.define('roles', { 7 | title: { 8 | type: 'text' 9 | 10 | }, 11 | bit_mask: { 12 | type: 'text' 13 | } 14 | }, { 15 | autoFetch: true, 16 | autoFetchLimit: 2, 17 | methods: {}, 18 | validations: {}, 19 | hooks: { 20 | beforeValidation: function() { 21 | //this.updated_at = new Date(); 22 | } 23 | } 24 | }); 25 | 26 | Role.loadRoles = function( callback){ 27 | Role.count(function(err, number){ 28 | if(err) return callback(err); 29 | else if(number !== 0) return callback(); 30 | 31 | //for(var title in userRoles) { 32 | // log.info('>> title: '+ title + ', userRoles[title][bit_mask]: '+ userRoles[title]['bit_mask']) 33 | // Role.create([{ 34 | // title: title, 35 | // bit_mask: userRoles[title]['bit_mask'] 36 | // }], function(err, item){ 37 | // if(err) log.error(err); 38 | // }); 39 | //} 40 | var keys = []; 41 | for(var title in userRoles) { 42 | keys.push(title); 43 | } 44 | async.eachSeries(keys, function( title, cb){ 45 | Role.create([{ 46 | title: title, 47 | bit_mask: userRoles[title]['bit_mask'] 48 | }], function(err, item){ 49 | if(err) { 50 | log.error(err); 51 | return cb(err); 52 | } 53 | return cb(); 54 | }); 55 | }, function(err){ 56 | if(err){ 57 | log.error(err); 58 | return callback(err); 59 | } else { 60 | log.info('>> Roles data created!'); 61 | return callback() 62 | } 63 | }); 64 | }); 65 | } 66 | }; 67 | -------------------------------------------------------------------------------- /backend/bin/www: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | //var debug = require('debug')('my-application'); 3 | var cluster = require('express-cluster'); 4 | var app = require('../app'); 5 | 6 | 7 | /** 8 | * Initialise log4js first, so we don't miss any log messages 9 | */ 10 | //var log4js = require('log4js'); 11 | //log4js.configure( 12 | // { 13 | // "appenders": [ 14 | // { 15 | // "type": "clustered", 16 | // "appenders": [ 17 | // { 18 | // "type": "dateFile", 19 | // "filename": "log/access.log", 20 | // "pattern": "-yyyy-MM-dd", 21 | // "category": "http" 22 | // }, 23 | // { 24 | // "type": "file", 25 | // "filename": "log/app.log", 26 | // "maxLogSize": 10485760, 27 | // "numBackups": 3 28 | // }, 29 | // { 30 | // "type": "logLevelFilter", 31 | // "level": "ERROR", 32 | // "appender": { 33 | // "type": "file", 34 | // "filename": "log/errors.log" 35 | // } 36 | // }, 37 | // { 38 | // "type": "console", 39 | // "level": "ERROR" 40 | // } 41 | // ] 42 | // //replaceConsole: true 43 | // } 44 | // ] 45 | // } 46 | // 47 | //); 48 | 49 | app.set('port', process.env.PORT || 3000); 50 | var server = app.listen(app.get('port'), function() { 51 | //debug('Express server listening on port ' + server.address().port); 52 | console.log('Express server listening on port %d in %s mode', server.address().port, app.get('env')); 53 | }); 54 | //var log = log4js.getLogger("startup"); 55 | ////let's start up a cluster 56 | //cluster(function() { 57 | // app.set('port', process.env.PORT || 3000); 58 | // 59 | // var server = app.listen(app.get('port'), function() { 60 | // log.info('Express server listening on port ', server.address().port, " with pid ", process.pid ); 61 | // }); 62 | //}); 63 | 64 | module.exports = app; -------------------------------------------------------------------------------- /frontend/app/views/partials/forums/topics/topics.new.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | Back 4 |
5 |
6 | 7 |
8 |
9 |

New Topic

10 |
11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 |
19 | 20 |
21 | 24 |
25 | 26 |
27 | 30 |
31 |
32 | 33 |
34 |

Progress... {{ progress }}%

35 |
36 |
37 |

{{ error }}

38 |
39 |
40 |

{{ message }}

41 |
42 | 43 | 44 | 45 |
46 |
47 |
48 | 51 | -------------------------------------------------------------------------------- /frontend/app/views/partials/products/products.list.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 |
7 | 8 |
9 |
10 | 11 |
12 |
13 |
14 |
15 |
16 | 17 |
18 | 33 |
34 | 35 | 36 |
37 |
Page:{{page}}/{{numPages}} ({{totalItems}})
38 |
39 | 41 |
42 |
43 | 44 | Refresh 45 |
46 |
47 |
48 |
49 | -------------------------------------------------------------------------------- /frontend/app/scripts/services/articles.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc service 5 | * @name frontendApp.articles 6 | * @description 7 | * # articles 8 | * Factory in the frontendApp. 9 | */ 10 | angular.module('frontendApp') 11 | .factory('articles', ['$http', '$resource', function ($http, $resource) { 12 | 13 | var resource = $resource('/articles/:id',{id:'@id'}, {update: {method: 'PUT'}}); 14 | 15 | // Public API here 16 | return { 17 | index: function () { //GET 18 | return resource.query(); 19 | }, 20 | get: function (data, callback) { //GET 21 | var cb = callback || angular.noop; 22 | resource.get(data, function (article) { 23 | //console.log(article); 24 | return cb(null, article); 25 | }, function (err) { 26 | return cb(err); 27 | }); 28 | }, 29 | update: function (data, callback) { //PUT 30 | var cb = callback || angular.noop; 31 | resource.update(data, function (article) { 32 | return cb(null, article); 33 | }, function (err) { 34 | return cb(err); 35 | }); 36 | }, 37 | save: function (data, callback) { //POST 38 | var cb = callback || angular.noop; 39 | resource.save(data, function (article) { 40 | return cb(null, article); 41 | }, function (err) { 42 | return cb(err); 43 | }); 44 | }, 45 | remove: function (data, callback) { //DELETE 46 | var cb = callback || angular.noop; 47 | return resource.remove(data, function(article){ 48 | return cb(null, article); 49 | }, function(err){ 50 | return cb(err); 51 | }); 52 | }, 53 | searchArticles: function (conditions, callback) { 54 | var cb = callback || angular.noop; 55 | //console.log(conditions); 56 | $http.post('/articles/search', conditions) 57 | .success(function (data, status, headers, config) { 58 | //console.log('>> status:' + status); 59 | return cb(null, data); 60 | }).error(function (data, status, headers, config) { 61 | //console.log('>> error data:' + data); 62 | // called asynchronously if an error occurs 63 | // or server returns response with an error status. 64 | return cb(status, data); 65 | }); 66 | } 67 | }; 68 | }]); 69 | -------------------------------------------------------------------------------- /frontend/app/scripts/services/profiles.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc service 5 | * @name frontendApp.profiles 6 | * @description 7 | * # profiles 8 | * Factory in the frontendApp. 9 | */ 10 | angular.module('frontendApp') 11 | .factory('profiles', ['$http', '$resource', function ($http, $resource) { 12 | 13 | var resource = $resource('/profiles/:id',{id:'@id'}, {update: {method: 'PUT'}}); 14 | 15 | // Public API here 16 | return { 17 | index: function () { //GET 18 | return resource.query(); 19 | }, 20 | get: function (conditions, callback) { //GET 21 | var cb = callback || angular.noop; 22 | resource.get(conditions, function (data) { 23 | //console.log(data); 24 | return cb(null, data); 25 | }, function (err) { 26 | //console.log('>>error:');console.log(err); 27 | return cb(err); 28 | }); 29 | }, 30 | update: function (conditions, callback) { //PUT 31 | var cb = callback || angular.noop; 32 | resource.update(conditions, function (data) { 33 | return cb(null, data); 34 | }, function (err) { 35 | return cb(err); 36 | }); 37 | }, 38 | save: function (conditions, callback) { //POST 39 | var cb = callback || angular.noop; 40 | resource.save(conditions, function (data) { 41 | return cb(null, data); 42 | }, function (err) { 43 | return cb(err, null); 44 | }); 45 | }, 46 | remove: function (conditions, callback) { //DELETE 47 | var cb = callback || angular.noop; 48 | return resource.remove(conditions, function (data) { 49 | return cb(null, data); 50 | }, function (err) { 51 | return cb(err); 52 | }); 53 | }, 54 | 55 | saveAddress: function (conditions, callback) { 56 | var cb = callback || angular.noop; 57 | //console.log(conditions); 58 | $http.post('/profiles/save_address', conditions) 59 | .success(function (data, status, headers, config) { 60 | //console.log('>> status:' + status); 61 | return cb(null, data); 62 | }).error(function (data, status, headers, config) { 63 | //console.log('>> error data:' + data); 64 | // called asynchronously if an error occurs 65 | // or server returns response with an error status. 66 | return cb(status, data); 67 | }); 68 | } 69 | 70 | }; 71 | }]); 72 | 73 | -------------------------------------------------------------------------------- /frontend/app/views/partials/admin/taxonomies/taxonomies.list.html: -------------------------------------------------------------------------------- 1 |

Taxonomies List

2 | 3 |
4 |
5 |
6 |
7 | 8 |
9 |
10 | 11 |
12 |
13 | 14 |
15 |
16 |
17 |

{{ error }}

18 |
19 |
20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 37 | 38 | 39 |
Name
{{item.name}} 34 | 35 | 36 |
40 |
41 |
42 |
43 |
44 |
45 | 46 | Refresh 47 |
48 |
49 |
50 | -------------------------------------------------------------------------------- /frontend/app/scripts/controllers/login.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('frontendApp') 4 | .controller( 5 | 'LoginCtrl', [ 6 | '$scope', 7 | 'AuthFactory', 8 | '$location', 9 | '$remember', 10 | 'redirects', 11 | function($scope, AuthFactory, $location, $remember, redirects) { 12 | $scope.error = {}; 13 | $scope.user = {}; 14 | $scope.user.rememberMe = false; 15 | 16 | if($remember('email')){ 17 | $scope.user.rememberMe = true; 18 | $scope.user.email = $remember('email'); 19 | //$scope.user.password = $remember('password'); 20 | } 21 | 22 | function rememberMe(){ 23 | if($scope.user.rememberMe){ 24 | $remember('email', $scope.user.email); 25 | //$remember('password', {value:$scope.user.password, secure: true}); 26 | } else { 27 | $remember('email', ''); 28 | //$remember('password', ''); 29 | } 30 | } 31 | 32 | $scope.login = function(form) { 33 | rememberMe(); 34 | AuthFactory.login('password', { 35 | 'email': $scope.user.email, 36 | 'password': $scope.user.password, 37 | 'rememberMe': $scope.user.rememberMe 38 | }, function(err) { 39 | $scope.errors = {}; 40 | 41 | if (!err) { 42 | //console.log('>>redirect: '+ $scope.redirect); 43 | //console.log('>>redirectURL: '+ redirects.getRedirectURL()); 44 | $location.path( redirects.getRedirectURL()? redirects.getRedirectURL(): '/'); 45 | //$location.path( $scope.redirect ? $scope.redirect : '/'); 46 | } else { 47 | //console.log('>>login controller error:'+ JSON.stringify(err)); 48 | //console.log(err); 49 | angular.forEach(err.errors, function(error, 50 | field) { 51 | form[field].$setValidity('server', false); 52 | $scope.errors[field] = error.type; 53 | }); 54 | $scope.error.other = err.message; 55 | } 56 | }); 57 | }; 58 | } 59 | ]); 60 | -------------------------------------------------------------------------------- /frontend/app/scripts/controllers/taxon_tree.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc function 5 | * @name frontendApp.controller:TaxonTreeCtrl 6 | * @description 7 | * # TaxonTreeCtrl 8 | * Controller of the frontendApp 9 | */ 10 | angular.module('frontendApp') 11 | .controller('TaxonTreeCtrl', ['$scope', '$state', '$stateParams','taxons', function ($scope, $state, $stateParams, taxons) { 12 | $scope.data = {}; 13 | $scope.page = $stateParams.page; 14 | 15 | $scope.selectNode=function(val){ 16 | //console.log(val); 17 | if( angular.isObject(val)){ 18 | var taxon = val; 19 | $state.go('taxons.products', {id: taxon.id}); 20 | } 21 | }; 22 | 23 | $scope.$watch('taxontree.currentNode', function( newObj, oldObj ) { 24 | //console.log( 'Node Selected!!' ); 25 | //console.log($scope.taxontree); 26 | if( $scope.taxontree && angular.isObject($scope.taxontree.currentNode) ) { 27 | //console.log( $scope.taxontree.currentNode ); 28 | var taxon = $scope.taxontree.currentNode; 29 | $state.go('taxons.products', {id: taxon.id}); 30 | } 31 | }, false); 32 | 33 | $scope.taxonTree = function(){ 34 | taxons.list(function(err, data){ 35 | if(!err && data){ 36 | //console.log(data); 37 | $scope.data.taxonTree = makeTree({q: data}); 38 | //console.log($scope.data.taxonTree); 39 | } 40 | }); 41 | }; 42 | 43 | $scope.taxonTree(); 44 | }]) 45 | .controller('TaxonCtrl', ['$scope', '$state', '$stateParams','taxons', function ($scope, $state, $stateParams, taxons) { 46 | $scope.data = {}; 47 | $scope.conditions = {}; 48 | $scope.page = $stateParams.page; 49 | $scope.taxonId = $stateParams.id; 50 | 51 | $scope.taxonProducts = function(){ 52 | $scope.conditions.id = $scope.taxonId; 53 | $scope.conditions.page = $scope.page; 54 | taxons.getProducts($scope.conditions, function(err, data){ 55 | if(!err){ 56 | //console.log(data); 57 | $scope.data.products = data.products; 58 | $scope.totalItems = data.count; 59 | $scope.page = data.page; 60 | } 61 | }); 62 | }; 63 | 64 | $scope.pageChanged = function() { 65 | $scope.taxonProducts(); 66 | //$state.go('admin.user.home',{page: $scope.page}); 67 | //$location.path('/users/page/'+$scope.page); 68 | }; 69 | 70 | $scope.taxonProducts(); 71 | }]); 72 | -------------------------------------------------------------------------------- /frontend/app/views/partials/news/news.view.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 12 |
13 |
14 |
15 |

{{data.article.name}}

16 |
17 |
18 |
19 |
Written by {{data.article.user.email}} {{data.article.created_at | date:'yyyy-MM-dd hh:mm:ss'}}
20 |
21 | 26 |
27 | Edit 28 | Delete 29 |
30 |
31 |
32 |
33 |
34 | 39 | -------------------------------------------------------------------------------- /frontend/app/scripts/common/tree.js: -------------------------------------------------------------------------------- 1 | /* 2 | convert tree to flatten array 3 | visitor(treeData) 4 | */ 5 | var visitor = function(graph) { 6 | var i, l, 7 | nodes=[], 8 | visited=[]; 9 | 10 | var clone = function(n) { 11 | // improve the function yourself I'm lazy 12 | var i,l, 13 | props=["id","parent_id","depth","index","text"], 14 | result={}; 15 | for (i = 0, l = props.length; i < l; i++) { 16 | result[props[i]]= n[props[i]]; 17 | } 18 | return result; 19 | }; 20 | 21 | var helper = function(node, parent_id, depth, permalink) { 22 | var i, limit; 23 | if (visited.indexOf(node.id) == -1) { 24 | visited.push(node.id); 25 | if(!permalink) permalink = []; 26 | permalink.push(node.name); 27 | node.permalink = permalink.join('/').toLowerCase(); 28 | permalink.pop(); 29 | node.parent_id = parent_id; 30 | node.depth = depth; 31 | //nodes.push(clone(node)); 32 | nodes.push(node); 33 | //console.log(node); 34 | if( node.children) { 35 | for (i = 0, limit = node.children.length; i < limit; i++) { 36 | permalink.push(node.name); 37 | helper(node.children[i], node.id, depth + 1, permalink); 38 | permalink.pop(); 39 | } 40 | } 41 | } 42 | }; 43 | 44 | //console.log('graph.length:'+ graph.length); 45 | for (i = 0, l = graph.length; i < l; i++) { 46 | var parent_id = graph[i].parent_id || null; 47 | var depth = 0; 48 | helper(graph[i], parent_id, depth); 49 | } 50 | 51 | return nodes; 52 | }; 53 | 54 | /* 55 | convert flatten array to tree 56 | makeTree{ q: arrayData [,id: 'id', parent_id: 'parent_id, children: 'children]}); 57 | */ 58 | var makeTree = function(options) { 59 | var children, e, id, o, pid, temp, _i, _len, _ref; 60 | id = options.id || "id"; 61 | pid = options.parent_id || "parent_id"; 62 | children = options.children || "children"; 63 | temp = {}; 64 | o = []; 65 | _ref = options.q; 66 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 67 | e = _ref[_i]; 68 | e[children] = []; 69 | temp[e[id]] = e; 70 | if (temp[e[pid]] != null) { 71 | temp[e[pid]][children].push(e); 72 | } else { 73 | o.push(e); 74 | } 75 | } 76 | return o; 77 | }; 78 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | --------------------------------------------------------------------------------