├── .gitignore ├── LICENSE ├── README.md ├── api ├── .editorconfig ├── .gitignore ├── .sailsrc ├── README.md ├── api │ ├── controllers │ │ ├── .gitkeep │ │ ├── AuthController.js │ │ ├── ChatController.js │ │ ├── ChatMessageController.js │ │ ├── CommentController.js │ │ ├── CompanyController.js │ │ ├── ConfirmEmailController.js │ │ ├── ContactController.js │ │ ├── ContactTypeController.js │ │ ├── DepartmentController.js │ │ ├── EducationController.js │ │ ├── EmailChangeController.js │ │ ├── FamilyController.js │ │ ├── FileController.js │ │ ├── FolderController.js │ │ ├── GenderController.js │ │ ├── JobController.js │ │ ├── LanguageController.js │ │ ├── LogLoginController.js │ │ ├── LogRequestController.js │ │ ├── ModuleController.js │ │ ├── PasswordResetController.js │ │ ├── PhotoController.js │ │ ├── PlaceController.js │ │ ├── ProfileController.js │ │ ├── RelationController.js │ │ ├── RelationshipController.js │ │ ├── UserController.js │ │ ├── UserRoleController.js │ │ └── helloController.js │ ├── hooks │ │ └── seeds │ │ │ └── index.js │ ├── models │ │ ├── .gitkeep │ │ ├── Chat.js │ │ ├── ChatMessage.js │ │ ├── Company.js │ │ ├── ConfirmEmail.js │ │ ├── Contact.js │ │ ├── ContactType.js │ │ ├── Department.js │ │ ├── Education.js │ │ ├── EmailChange.js │ │ ├── Family.js │ │ ├── File.js │ │ ├── Folder.js │ │ ├── Gender.js │ │ ├── Job.js │ │ ├── Language.js │ │ ├── LogLogin.js │ │ ├── LogRequest.js │ │ ├── Module.js │ │ ├── PasswordReset.js │ │ ├── Photo.js │ │ ├── Place.js │ │ ├── Profile.js │ │ ├── Relation.js │ │ ├── Relationship.js │ │ ├── User.js │ │ ├── UserRole.js │ │ ├── base.js │ │ └── hello.js │ ├── policies │ │ ├── isAuthenticated.js │ │ └── sessionAuth.js │ ├── responses │ │ ├── badRequest.js │ │ ├── forbidden.js │ │ ├── found.js │ │ ├── notFound.js │ │ ├── ok.js │ │ ├── serverError.js │ │ └── tokenExpired.js │ └── services │ │ ├── .gitkeep │ │ ├── EmailService.js │ │ ├── EncryptService.js │ │ ├── FileService.js │ │ ├── JWTService.js │ │ ├── LogService.js │ │ ├── ModuleService.js │ │ ├── RandTokenService.js │ │ └── UserService.js ├── app.js ├── config │ ├── apianalytics.js │ ├── blueprints.js │ ├── bootstrap.js │ ├── connections.js │ ├── cors.js │ ├── csrf.js │ ├── email.js │ ├── env │ │ ├── development.example.js │ │ └── production.example.js │ ├── globals.js │ ├── http.js │ ├── i18n.js │ ├── locales │ │ ├── _README.md │ │ ├── de.json │ │ ├── en.json │ │ ├── es.json │ │ └── fr.json │ ├── log.js │ ├── models.js │ ├── passport.js │ ├── policies.js │ ├── routes.js │ ├── session.js │ ├── sockets.js │ └── views.js ├── package.json ├── seeds │ └── development │ │ ├── company.json │ │ ├── contacttype.json │ │ ├── department.json │ │ ├── folder.json │ │ ├── gender.json │ │ ├── hello.json │ │ ├── job.json │ │ ├── language.json │ │ ├── module.json │ │ ├── profile.json │ │ ├── relation.json │ │ ├── relationship.json │ │ ├── user.json │ │ └── userrole.json └── views │ ├── 403.ejs │ ├── 404.ejs │ ├── 500.ejs │ ├── emailTemplates │ ├── confirmEmail │ │ └── html.ejs │ ├── emailChange │ │ └── html.ejs │ ├── emailChangeUpdate │ │ └── html.ejs │ ├── notification │ │ └── html.ejs │ ├── passwordReset │ │ └── html.ejs │ ├── passwordUpdate │ │ └── html.ejs │ ├── sendUserData │ │ └── html.ejs │ └── welcome │ │ └── html.ejs │ ├── homepage.ejs │ ├── layout.ejs │ └── transactional-email-templates-master │ ├── LICENSE │ ├── README.md │ └── templates │ ├── action.html │ ├── alert.html │ ├── billing.html │ ├── inlined │ ├── action.html │ ├── alert.html │ └── billing.html │ └── styles.css ├── app ├── app │ ├── app.config.js │ ├── app.js │ ├── helpers │ │ ├── checkbox │ │ │ ├── checkbox.directive.js │ │ │ └── checkedListBox.directive.js │ │ ├── comments │ │ │ ├── .DS_Store │ │ │ ├── comments.directive.js │ │ │ └── comments.html │ │ ├── events │ │ │ ├── enter.directive.js │ │ │ ├── escape.directive.js │ │ │ ├── focus.directive.js │ │ │ ├── scrollToBottom.directive.js │ │ │ └── scrollToTop.directive.js │ │ ├── files │ │ │ ├── .DS_Store │ │ │ ├── files.directive.js │ │ │ ├── files.html │ │ │ ├── grid.html │ │ │ └── list.html │ │ ├── helpers.module.js │ │ ├── loading-panel.directive.js │ │ ├── panel │ │ │ └── panel.directive.js │ │ ├── restFul │ │ │ ├── .DS_Store │ │ │ ├── restFul.service.js │ │ │ └── restFulSocket.service.js │ │ ├── sanitize │ │ │ └── sanitize.service.js │ │ └── tooltip.directive.js │ ├── images │ │ ├── avatar.jpg │ │ ├── error.svg │ │ ├── icon-loading.svg │ │ ├── icon-white.svg │ │ ├── logo.svg │ │ ├── modulr-orange.svg │ │ └── modulr-white.svg │ ├── index.html │ ├── modules │ │ ├── auth │ │ │ ├── auth.module.js │ │ │ ├── auth.service.js │ │ │ ├── beginPasswordReset.controller.js │ │ │ ├── beginPasswordReset.html │ │ │ ├── confirmEmail.controller.js │ │ │ ├── confirmEmail.html │ │ │ ├── interceptor.service.js │ │ │ ├── login.controller.js │ │ │ ├── login.html │ │ │ ├── passwordReset.controller.js │ │ │ ├── passwordReset.html │ │ │ ├── sendPasswordReset.controller.js │ │ │ ├── sendPasswordReset.html │ │ │ ├── signup.controller.js │ │ │ └── signup.html │ │ ├── chat │ │ │ ├── chat.controller.js │ │ │ └── chat.html │ │ ├── dashboard │ │ │ ├── dashboard.controller.js │ │ │ ├── dashboard.html │ │ │ └── dashboard.module.js │ │ ├── errors │ │ │ ├── error.controller.js │ │ │ ├── error.html │ │ │ ├── error.service.js │ │ │ └── errors.module.js │ │ ├── files │ │ │ ├── files.controller.js │ │ │ ├── files.html │ │ │ └── files.module.js │ │ ├── helloWorld │ │ │ ├── hello.controller.js │ │ │ ├── hello.html │ │ │ └── hello.module.js │ │ ├── layout │ │ │ ├── layout.controller.js │ │ │ ├── layout.html │ │ │ ├── layout.module.js │ │ │ ├── layoutAuth.controller.js │ │ │ └── layoutAuth.html │ │ ├── log │ │ │ ├── log.module.js │ │ │ ├── log.service.js │ │ │ ├── logLogin.controller.js │ │ │ ├── logLogin.html │ │ │ ├── logRequest.controller.js │ │ │ └── logRequest.html │ │ ├── profile │ │ │ ├── emailChange.controller.js │ │ │ ├── emailChange.html │ │ │ ├── information.html │ │ │ ├── permissions.html │ │ │ ├── profile.controller.js │ │ │ ├── profile.html │ │ │ ├── profile.module.js │ │ │ ├── profileInformation.controller.js │ │ │ ├── profilePermissions.controller.js │ │ │ ├── profileSettings.controller.js │ │ │ ├── profileWork.controller.js │ │ │ ├── settings.html │ │ │ └── work.html │ │ ├── settings │ │ │ ├── modules │ │ │ │ ├── modules.controller.js │ │ │ │ └── modules.html │ │ │ └── settings.module.js │ │ └── users │ │ │ ├── access │ │ │ ├── access.controller.js │ │ │ └── access.html │ │ │ ├── roles │ │ │ ├── roleAuthorizations.directive.js │ │ │ ├── roleAuthorizations.html │ │ │ ├── rolePermissions.directive.js │ │ │ ├── rolePermissions.html │ │ │ ├── roles.controller.js │ │ │ └── roles.html │ │ │ ├── users.module.js │ │ │ └── users │ │ │ ├── users.controller.js │ │ │ └── users.html │ ├── sass │ │ ├── main.scss │ │ ├── mixins │ │ │ ├── _animation.scss │ │ │ ├── _box-shadow.scss │ │ │ ├── _opacity.scss │ │ │ ├── _placeholder.scss │ │ │ └── _transition.scss │ │ ├── modules │ │ │ ├── _auth.scss │ │ │ ├── _comments.scss │ │ │ ├── _error.scss │ │ │ └── _profile.scss │ │ └── partials │ │ │ ├── _alerts.scss │ │ │ ├── _animations.scss │ │ │ ├── _aside.scss │ │ │ ├── _badges.scss │ │ │ ├── _breadcrumb.scss │ │ │ ├── _buttons.scss │ │ │ ├── _dropdowns.scss │ │ │ ├── _footer.scss │ │ │ ├── _forms.scss │ │ │ ├── _header.scss │ │ │ ├── _intro.scss │ │ │ ├── _labels.scss │ │ │ ├── _lists.scss │ │ │ ├── _loading-panel.scss │ │ │ ├── _loading.scss │ │ │ ├── _margin.scss │ │ │ ├── _media.scss │ │ │ ├── _modals.scss │ │ │ ├── _nav.scss │ │ │ ├── _normalize.scss │ │ │ ├── _pagination.scss │ │ │ ├── _panels.scss │ │ │ ├── _section.scss │ │ │ ├── _tables.scss │ │ │ ├── _tabs.scss │ │ │ ├── _tooltips.scss │ │ │ ├── _tree.scss │ │ │ └── _variables.scss │ └── sounds │ │ └── ios_notification.mp3 ├── bower.json ├── config │ ├── env │ │ ├── development.example.json │ │ └── production.example.json │ └── locales │ │ ├── en.json │ │ └── es.json ├── gulpfile.js ├── package.json ├── server.js └── storage │ └── .gitignore └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | api/node_modules 2 | api/config/env/development.js 3 | api/config/env/production.js 4 | 5 | app/bower_components 6 | app/node_modules 7 | app/config/env/development.json 8 | app/config/env/production.json 9 | app/public/* 10 | app/.sass-cache 11 | 12 | app/nohup.out 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 modulr 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /api/.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | -------------------------------------------------------------------------------- /api/.sailsrc: -------------------------------------------------------------------------------- 1 | { 2 | "generators": { 3 | "modules": {} 4 | } 5 | } -------------------------------------------------------------------------------- /api/README.md: -------------------------------------------------------------------------------- 1 | # api 2 | 3 | a [Sails](http://sailsjs.org) application 4 | -------------------------------------------------------------------------------- /api/api/controllers/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modulr/sails-angularjs/c99442dc9fa2402d71832fd44b793c009fdbebd9/api/api/controllers/.gitkeep -------------------------------------------------------------------------------- /api/api/controllers/ChatMessageController.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 3 | 4 | messages: function(req, res, cb) 5 | { 6 | var chatId = req.param('id'); 7 | var userId = req.param('userId'); 8 | var noRead = req.param('noRead'); 9 | var limit = 15 + Number(noRead); 10 | 11 | //if (req.isSocket){ 12 | sails.models.chatmessage.find({ chatId: chatId }) 13 | .sort('createdAt DESC') 14 | .limit(limit) 15 | .exec(function(err, messages){ 16 | if(err) cb(err); 17 | res.json({ data: messages }); 18 | }); 19 | //} 20 | }, 21 | 22 | moreMessages: function(req, res, cb) 23 | { 24 | var chatId = req.param('id'); 25 | var skip = req.param('skip'); 26 | 27 | sails.models.chatmessage 28 | .find({ where: { chatId: chatId }, limit: 15, skip: skip }) 29 | .sort('createdAt DESC') 30 | .exec(function(err, messages){ 31 | if(err) cb(err); 32 | res.json({ data: messages }); 33 | }); 34 | }, 35 | 36 | create: function(req, res, cb) 37 | { 38 | var newMessage = req.query; 39 | 40 | if (newMessage.to.isArray) { 41 | newMessage.to.forEach(function(v,k){ 42 | newMessage.to[k] = JSON.parse(v); 43 | }); 44 | } else { 45 | newMessage.to = [JSON.parse(newMessage.to)]; 46 | } 47 | 48 | sails.models.chatmessage.create(newMessage) 49 | .exec(function(err, message){ 50 | if(err) cb(err); 51 | 52 | sails.sockets.broadcast(message.to[0].userId, 'privateMessage', { data: message }); 53 | 54 | res.json({ data: message }); 55 | }); 56 | }, 57 | 58 | markRead: function(req, res, cb) 59 | { 60 | var chatId = req.param('id'); 61 | var userId = req.param('userId'); 62 | 63 | sails.models.chatmessage.find([{ chatId: chatId, 'to.userId': userId, 'to.read': false }]) 64 | .exec(function(err, messages){ 65 | 66 | async.each(messages, function(v, callback) { 67 | 68 | v.to[0].read = true; 69 | 70 | sails.models.chatmessage.update({id: v.id}, {'to': v.to}) 71 | .exec(function(err, message){ 72 | 73 | callback(); 74 | }); 75 | 76 | }, function(err) { 77 | res.json({ data: messages }); 78 | }); 79 | 80 | }); 81 | 82 | } 83 | 84 | }; 85 | -------------------------------------------------------------------------------- /api/api/controllers/CompanyController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * CompanyController 3 | * 4 | * @description :: Server-side logic for managing companies 5 | * @help :: See http://links.sailsjs.org/docs/controllers 6 | */ 7 | 8 | module.exports = { 9 | 10 | }; 11 | -------------------------------------------------------------------------------- /api/api/controllers/ConfirmEmailController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ConfirmEmailController 3 | * 4 | * @description :: Server-side logic for managing ConfirmEmails 5 | * @help :: See http://links.sailsjs.org/docs/controllers 6 | */ 7 | 8 | module.exports = { 9 | 10 | }; 11 | -------------------------------------------------------------------------------- /api/api/controllers/ContactController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ContactController 3 | * 4 | * @description :: Server-side logic for managing contacts 5 | * @help :: See http://links.sailsjs.org/docs/controllers 6 | */ 7 | 8 | module.exports = { 9 | 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /api/api/controllers/ContactTypeController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ContactTypeController 3 | * 4 | * @description :: Server-side logic for managing Contacttypes 5 | * @help :: See http://links.sailsjs.org/docs/controllers 6 | */ 7 | 8 | module.exports = { 9 | 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /api/api/controllers/DepartmentController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * DepartmentController 3 | * 4 | * @description :: Server-side logic for managing departments 5 | * @help :: See http://links.sailsjs.org/docs/controllers 6 | */ 7 | 8 | module.exports = { 9 | 10 | }; 11 | -------------------------------------------------------------------------------- /api/api/controllers/EducationController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * EducationController 3 | * 4 | * @description :: Server-side logic for managing Educations 5 | * @help :: See http://links.sailsjs.org/docs/controllers 6 | */ 7 | 8 | module.exports = { 9 | 10 | }; 11 | -------------------------------------------------------------------------------- /api/api/controllers/EmailChangeController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * EmailChangeController 3 | * 4 | * @description :: Server-side logic for managing auth 5 | * @help :: See http://links.sailsjs.org/docs/controllers 6 | */ 7 | 8 | var moment = require('moment'); 9 | 10 | module.exports = { 11 | 12 | validate: function(req, res, cb){ 13 | 14 | var token = req.params.token; 15 | var tokenId = req.params.tokenId; 16 | var userId = req.params.userId; 17 | 18 | // It find the token 19 | sails.models.emailchange.findOne({ id: tokenId, token: token, userId: userId }) 20 | .exec(function(err, emailchange){ 21 | if(err) return cb(err); 22 | 23 | // If token do not exist 24 | if(!emailchange) return res.notFound(); 25 | 26 | // If token it is used 27 | if (emailchange.deletedAt !== null) return res.tokenExpired(); 28 | 29 | var now = moment().format(); 30 | var createAt24 = moment(emailchange.createdAt).add(1, 'd'); 31 | 32 | // If the token has expired 33 | if (!createAt24.isAfter(now)) return res.tokenExpired(); 34 | 35 | // It updates the user 36 | sails.models.user.update({ id: userId }, {email: emailchange.email}) 37 | .exec(function(err, user){ 38 | if(err) return cb(err); 39 | 40 | // It deletes token 41 | sails.models.emailchange.update({ id: tokenId }, { deletedAt: now }) 42 | .exec(function(err, emailchange){ 43 | if(err) return cb(err); 44 | 45 | // It find the user 46 | sails.models.user.findOne({ id: userId }).populate('profile') 47 | .exec(function(err, user){ 48 | if(err) return cb(err); 49 | 50 | user = user.toJSON(); 51 | req.setLocale(user.lang); 52 | 53 | var options = { 54 | to: user.email, 55 | subject: req.__("email-change-update.subject"), 56 | data: { 57 | hi: req.__('hi', user.profile.fullName || user.username), 58 | paragraph: req.__('email-change-update.paragraph'), 59 | team: req.__('team') 60 | } 61 | }; 62 | 63 | // It send the mail 64 | EmailService.send('emailChangeUpdate', options); 65 | 66 | res.json(user); 67 | }); 68 | 69 | }); 70 | }); 71 | 72 | }); 73 | } 74 | 75 | }; 76 | -------------------------------------------------------------------------------- /api/api/controllers/FamilyController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * FamilyController 3 | * 4 | * @description :: Server-side logic for managing Families 5 | * @help :: See http://links.sailsjs.org/docs/controllers 6 | */ 7 | 8 | module.exports = { 9 | 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /api/api/controllers/GenderController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * GenderController 3 | * 4 | * @description :: Server-side logic for managing genders 5 | * @help :: See http://links.sailsjs.org/docs/controllers 6 | */ 7 | 8 | module.exports = { 9 | 10 | }; 11 | -------------------------------------------------------------------------------- /api/api/controllers/JobController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * JobController 3 | * 4 | * @description :: Server-side logic for managing jobs 5 | * @help :: See http://links.sailsjs.org/docs/controllers 6 | */ 7 | 8 | module.exports = { 9 | 10 | }; 11 | -------------------------------------------------------------------------------- /api/api/controllers/LanguageController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * LanguageController 3 | * 4 | * @description :: Server-side logic for managing languages 5 | * @help :: See http://links.sailsjs.org/docs/controllers 6 | */ 7 | 8 | module.exports = { 9 | 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /api/api/controllers/LogLoginController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * LogLoginController 3 | * 4 | * @description :: Server-side logic for managing users 5 | * @help :: See http://links.sailsjs.org/docs/controllers 6 | */ 7 | 8 | module.exports = { 9 | 10 | charts: function(req, res, cb) 11 | { 12 | var params = req.allParams(); 13 | 14 | if (req.isSocket){ 15 | sails.models.loglogin.watch(req); 16 | } 17 | 18 | sails.models.loglogin.find() 19 | .groupBy(params.id) 20 | .sum('count') 21 | .exec(function (err, loglogin){ 22 | if(err) return cb(err); 23 | return res.json(loglogin); 24 | }); 25 | }, 26 | 27 | table: function(req, res, cb) 28 | { 29 | if (req.isSocket){ 30 | sails.models.loglogin.watch(req); 31 | } 32 | 33 | sails.models.loglogin.find() 34 | .sort('createdAt DESC') 35 | .limit(50) 36 | .populate('user') 37 | .exec(function (err, loglogin){ 38 | if(err) return cb(err); 39 | return res.json(loglogin); 40 | }); 41 | } 42 | 43 | }; 44 | -------------------------------------------------------------------------------- /api/api/controllers/LogRequestController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * LogRequestController 3 | * 4 | * @description :: Server-side logic for managing users 5 | * @help :: See http://links.sailsjs.org/docs/controllers 6 | */ 7 | 8 | module.exports = { 9 | 10 | charts: function(req, res, cb) 11 | { 12 | var params = req.allParams(); 13 | 14 | if (req.isSocket){ 15 | sails.models.logrequest.watch(req); 16 | } 17 | 18 | sails.models.logrequest.find() 19 | .sum('count') 20 | .groupBy(params.id) 21 | .exec(function (err, logrequest){ 22 | if(err) return cb(err); 23 | return res.json(logrequest); 24 | }); 25 | }, 26 | 27 | chartTime: function(req, res, cb) 28 | { 29 | var params = req.allParams(); 30 | 31 | if (req.isSocket){ 32 | sails.models.logrequest.watch(req); 33 | } 34 | 35 | var data = []; 36 | 37 | sails.models.logrequest.find() 38 | .min(params.id) 39 | .exec(function (err, min){ 40 | if(err) return cb(err); 41 | data.push(min[0][params.id]); 42 | 43 | sails.models.logrequest.find() 44 | 45 | .average(params.id) 46 | .exec(function (err, average){ 47 | if(err) return cb(err); 48 | data.push(average[0][params.id].toFixed(2)); 49 | 50 | sails.models.logrequest.find() 51 | .max(params.id) 52 | .exec(function (err, max){ 53 | if(err) return cb(err); 54 | data.push(max[0][params.id]); 55 | 56 | return res.json(data); 57 | }); 58 | }); 59 | 60 | }); 61 | }, 62 | 63 | table: function(req, res, cb) 64 | { 65 | if (req.isSocket){ 66 | sails.models.logrequest.watch(req); 67 | } 68 | 69 | sails.models.logrequest.find({ 70 | url: { '!': '/__getcookie' } 71 | }) 72 | .limit(50) 73 | .populate('user') 74 | .sort('createdAt DESC') 75 | .exec(function (err, logrequest){ 76 | if(err) return cb(err); 77 | return res.json(logrequest); 78 | }); 79 | } 80 | 81 | }; 82 | -------------------------------------------------------------------------------- /api/api/controllers/ModuleController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ModuleController 3 | * 4 | * @description :: Server-side logic for managing Modules 5 | * @help :: See http://sailsjs.org/#!/documentation/concepts/Controllers 6 | */ 7 | 8 | module.exports = { 9 | 10 | all: function(req, res, cb) 11 | { 12 | sails.models.module.find({sort: 'order ASC'}).exec(function(err, modules){ 13 | if(err) return cb(err); 14 | res.json(modules); 15 | }); 16 | }, 17 | 18 | nav: function(req, res, cb) 19 | { 20 | sails.models.module.find({where: {active: true}, sort: 'order ASC'}).exec(function(err, modules){ 21 | if(err) return cb(err); 22 | res.json(modules); 23 | }); 24 | }, 25 | 26 | saveOrder: function(req, res, cb) 27 | { 28 | var data = req.body; 29 | var x = 0; 30 | async.each(data, function(module, callback) { 31 | x++; 32 | sails.models.module.update({ id: module.id }, {order:x} ).exec(function(err, update){ 33 | if(err) return cb(err); 34 | callback(); 35 | }); 36 | 37 | }, function(err) { 38 | sails.models.module.find({sort: 'order ASC'}).exec(function(err, modules){ 39 | if(err) return cb(err); 40 | res.json(modules); 41 | }); 42 | }); 43 | }, 44 | 45 | update: function(req, res, cb) 46 | { 47 | var id = req.params.id; 48 | var data = req.body; 49 | 50 | sails.models.module.update({ id:id }, data ).exec(function(err, update){ 51 | if(err) return cb(err); 52 | sails.models.module.find({sort: 'order ASC'}).exec(function(err, modules){ 53 | if(err) return cb(err); 54 | res.json(modules); 55 | }); 56 | }); 57 | } 58 | 59 | }; 60 | -------------------------------------------------------------------------------- /api/api/controllers/PasswordResetController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * PasswordResetController 3 | * 4 | * @description :: Server-side logic for managing tokens 5 | * @help :: See http://links.sailsjs.org/docs/controllers 6 | */ 7 | 8 | module.exports = { 9 | 10 | }; 11 | -------------------------------------------------------------------------------- /api/api/controllers/PhotoController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * PhotoController 3 | * 4 | * @description :: Server-side logic for managing photos 5 | * @help :: See http://links.sailsjs.org/docs/controllers 6 | */ 7 | 8 | var lwip = require('lwip'); 9 | var path = require('path'); 10 | // var fs = require('fs'); 11 | 12 | module.exports = { 13 | 14 | upload: function (req, res, cb) { 15 | 16 | var userId = req.param('id'); 17 | var folder = sails.config.settings.STORAGE + '/users/' + userId; 18 | 19 | req.file('file').upload({ 20 | dirname: path.resolve(folder) 21 | },function (err, files) { 22 | if (err) return cb(err); 23 | 24 | var array = files[0].fd.split("/"); 25 | var name = array[array.length - 1]; 26 | 27 | // Se ajusta el tamaño de la imagen 28 | lwip.open(files[0].fd, function(err, image){ 29 | if(err) return cb(err); 30 | 31 | image.batch() 32 | .resize(160, 160) 33 | .writeFile(folder + '/' + name, function(err){ 34 | if(err) return cb(err); 35 | // Se guarda el registro en el modelo photo y se actualiza el modelo user 36 | sails.models.photo.create({ name: name, filename: files[0].filename, user: userId }).exec(function(err, photo){ 37 | if(err) return cb(err); 38 | // Se actualiza la photo de usuario 39 | sails.models.user.update({ id: userId }, { photo: name }).exec(function(err, update){ 40 | if(err) return cb(err); 41 | res.json({avatar: update[0].getAvatar(), photo: photo}); 42 | }); 43 | }); 44 | }); 45 | 46 | }); 47 | 48 | }); 49 | }, 50 | 51 | // show: function (req, res){ 52 | // 53 | // req.validate({ 54 | // photo_id: 'string', 55 | // user_id: 'string' 56 | // }); 57 | // 58 | // sails.models.photo.findOne(req.param('photo_id')).exec(function (err, photo){ 59 | // if (err) return res.negotiate(err); 60 | // 61 | // var photoUrl = null; 62 | // 63 | // if (!photo){ 64 | // photoUrl = sails.config.appPath + '/assets/images/profile-photo.jpg'; 65 | // }else{ 66 | // photoUrl = sails.config.appPath + '/.tmp/uploads/' + req.param('user_id') + '/photos/' + photo.photo; 67 | // } 68 | // 69 | // fs.createReadStream(photoUrl).pipe(res); 70 | // }); 71 | // } 72 | }; 73 | -------------------------------------------------------------------------------- /api/api/controllers/PlaceController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * PlaceController 3 | * 4 | * @description :: Server-side logic for managing Places 5 | * @help :: See http://links.sailsjs.org/docs/controllers 6 | */ 7 | 8 | module.exports = { 9 | 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /api/api/controllers/ProfileController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ProfileController 3 | * 4 | * @description :: Server-side logic for managing profiles 5 | * @help :: See http://links.sailsjs.org/docs/controllers 6 | */ 7 | 8 | module.exports = { 9 | 10 | // update: function(req, res, next){ 11 | // var id = req.param('id'); 12 | // var data = req.body; 13 | // // Se actualiza el usuario 14 | // sails.models.profile.update({ id: id }, data).exec(function(err, update){ 15 | // if(err) return next(err); 16 | // res.json({ status: 200, profile: update }); 17 | // }); 18 | // } 19 | 20 | }; 21 | -------------------------------------------------------------------------------- /api/api/controllers/RelationController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * RelationController 3 | * 4 | * @description :: Server-side logic for managing Relations 5 | * @help :: See http://links.sailsjs.org/docs/controllers 6 | */ 7 | 8 | module.exports = { 9 | 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /api/api/controllers/RelationshipController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * RelationshipController 3 | * 4 | * @description :: Server-side logic for managing relationships 5 | * @help :: See http://links.sailsjs.org/docs/controllers 6 | */ 7 | 8 | module.exports = { 9 | 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /api/api/controllers/UserRoleController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * UserRoleController 3 | * 4 | * @description :: Server-side logic for managing userroles 5 | * @help :: See http://links.sailsjs.org/docs/controllers 6 | */ 7 | 8 | module.exports = { 9 | 10 | update: function(req, res, cb) { 11 | var id = req.params.id; 12 | var data = req.body; 13 | 14 | sails.models.userrole.update({id: id}, data).exec(function(err, role){ 15 | if(err) return cb(err); 16 | 17 | res.json(role[0]); 18 | }); 19 | } 20 | 21 | }; 22 | -------------------------------------------------------------------------------- /api/api/controllers/helloController.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 3 | find: function(req, res, cb) 4 | { 5 | sails.models.hello.find().exec(function(err, greeting){ 6 | if(err) return cb(err); 7 | res.json(greeting); 8 | }); 9 | } 10 | 11 | }; 12 | -------------------------------------------------------------------------------- /api/api/hooks/seeds/index.js: -------------------------------------------------------------------------------- 1 | var glob = require('glob'); 2 | var path = require('path'); 3 | 4 | module.exports = function seeds(sails) { 5 | return { 6 | initialize: function (cb) { 7 | sails.after('hook:orm:loaded', function () { 8 | 9 | // Find all seed files by environment. 10 | glob('seeds/' + sails.config.environment + '/**/*.json', function (err, files) { 11 | 12 | // Populate the model with a given seed. 13 | function populate(seed, next) { 14 | var attributes = Object.keys(seed.data[0] || {}); 15 | var criteria = {}; 16 | criteria[attributes[0]] = seed.data[0][attributes[0]]; 17 | sails.models[seed.model].findOrCreate(criteria, seed.data, next); 18 | } 19 | 20 | // Extract seeds data. 21 | var seeding = files.map(function (filePath) { 22 | return { 23 | model: path.basename(filePath, '.json'), 24 | data: require('../../../' + filePath) 25 | }; 26 | }); 27 | 28 | async.eachSeries(seeding, populate, cb); 29 | 30 | }); 31 | 32 | }); 33 | } 34 | }; 35 | }; 36 | -------------------------------------------------------------------------------- /api/api/models/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modulr/sails-angularjs/c99442dc9fa2402d71832fd44b793c009fdbebd9/api/api/models/.gitkeep -------------------------------------------------------------------------------- /api/api/models/Chat.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Chat.js 3 | * 4 | * @description :: TODO: You might write a short summary of how this model works and what it represents here. 5 | * @docs :: http://sailsjs.org/#!documentation/models 6 | */ 7 | 8 | var _ = require('lodash'); 9 | 10 | module.exports = _.merge(_.cloneDeep(require('./base')), { 11 | 12 | attributes: { 13 | name: { 14 | type:'string', 15 | defaultsTo: null 16 | }, 17 | photo: { 18 | type:'string', 19 | defaultsTo: 'avatar.jpg' 20 | }, 21 | // { 1: private, 2 group } 22 | type: { 23 | type: 'integer', 24 | defaultsTo: 1 25 | }, 26 | messages: { 27 | collection: 'chatmessage', 28 | via: 'chatId' 29 | }, 30 | // participants: { 31 | // type: 'array', 32 | // defaultsTo: [] 33 | // } 34 | participants: { 35 | collection: 'user', 36 | via: 'chats' 37 | }, 38 | getAvatar: function () { 39 | var avatar = null; 40 | if (this.photo == 'avatar.jpg') { 41 | avatar = 'images/' + this.photo; 42 | } else { 43 | avatar = 'storage/users/' + this.id + '/' + this.photo; 44 | } 45 | return avatar; 46 | }, 47 | toJSON: function() { 48 | var obj = this.toObject(); 49 | obj.avatar = this.getAvatar(); 50 | return obj; 51 | } 52 | } 53 | 54 | }); 55 | -------------------------------------------------------------------------------- /api/api/models/ChatMessage.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Chat.js 3 | * 4 | * @description :: TODO: You might write a short summary of how this model works and what it represents here. 5 | * @docs :: http://sailsjs.org/#!documentation/models 6 | */ 7 | 8 | var _ = require('lodash'); 9 | 10 | module.exports = _.merge(_.cloneDeep(require('./base')), { 11 | 12 | attributes: { 13 | chatId: { 14 | model: 'chat' 15 | }, 16 | from: { 17 | type: 'string', 18 | // model: 'user', 19 | // columnName: 'fromId', 20 | required: true 21 | }, 22 | // { userId, read } 23 | to: { 24 | type: 'array', 25 | defaultsTo: [] 26 | }, 27 | msg: { 28 | type:'string', 29 | required:true 30 | }, 31 | counter: { 32 | type: 'integer', 33 | defaultsTo: 1 34 | } 35 | } 36 | 37 | }); 38 | -------------------------------------------------------------------------------- /api/api/models/Company.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Company.js 3 | * 4 | * @description :: TODO: You might write a short summary of how this model works and what it represents here. 5 | * @docs :: http://sailsjs.org/#!documentation/models 6 | */ 7 | 8 | var _ = require('lodash'); 9 | 10 | module.exports = _.merge(_.cloneDeep(require('./base')), { 11 | 12 | attributes: { 13 | company: { 14 | type: 'string', 15 | unique: true, 16 | required: true 17 | } 18 | } 19 | 20 | }); 21 | -------------------------------------------------------------------------------- /api/api/models/ConfirmEmail.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ConfirmEmail.js 3 | * 4 | * @description :: TODO: You might write a short summary of how this model works and what it represents here. 5 | * @docs :: http://sailsjs.org/#!documentation/models 6 | */ 7 | 8 | var _ = require('lodash'); 9 | 10 | module.exports = _.merge(_.cloneDeep(require('./base')), { 11 | 12 | attributes: { 13 | userId: { 14 | model: 'user' 15 | }, 16 | token: { 17 | type: 'string' 18 | }, 19 | toJSON: function() { 20 | var obj = this.toObject(); 21 | delete obj.token; 22 | return obj; 23 | } 24 | } 25 | 26 | }); 27 | -------------------------------------------------------------------------------- /api/api/models/Contact.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Contact.js 3 | * 4 | * @description :: TODO: You might write a short summary of how this model works and what it represents here. 5 | * @docs :: http://sailsjs.org/#!documentation/models 6 | */ 7 | 8 | var _ = require('lodash'); 9 | 10 | module.exports = _.merge(_.cloneDeep(require('./base')), { 11 | 12 | attributes: { 13 | userId: { 14 | model: 'user' 15 | }, 16 | contact: { 17 | type: 'string', 18 | required: true 19 | }, 20 | type: { 21 | type: 'string', 22 | required: true 23 | } 24 | } 25 | 26 | }); 27 | -------------------------------------------------------------------------------- /api/api/models/ContactType.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ContactType.js 3 | * 4 | * @description :: TODO: You might write a short summary of how this model works and what it represents here. 5 | * @docs :: http://sailsjs.org/#!documentation/models 6 | */ 7 | 8 | var _ = require('lodash'); 9 | 10 | module.exports = _.merge(_.cloneDeep(require('./base')), { 11 | 12 | attributes: { 13 | type: { 14 | type: 'string', 15 | unique: true, 16 | required: true 17 | } 18 | } 19 | 20 | }); 21 | -------------------------------------------------------------------------------- /api/api/models/Department.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Department.js 3 | * 4 | * @description :: TODO: You might write a short summary of how this model works and what it represents here. 5 | * @docs :: http://sailsjs.org/#!documentation/models 6 | */ 7 | 8 | var _ = require('lodash'); 9 | 10 | module.exports = _.merge(_.cloneDeep(require('./base')), { 11 | 12 | attributes: { 13 | department: { 14 | type: 'string', 15 | unique: true, 16 | required: true 17 | } 18 | } 19 | 20 | }); 21 | -------------------------------------------------------------------------------- /api/api/models/Education.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Education.js 3 | * 4 | * @description :: TODO: You might write a short summary of how this model works and what it represents here. 5 | * @docs :: http://sailsjs.org/#!documentation/models 6 | */ 7 | 8 | var _ = require('lodash'); 9 | 10 | module.exports = _.merge(_.cloneDeep(require('./base')), { 11 | 12 | attributes: { 13 | userId: { 14 | model: 'user' 15 | }, 16 | schoolName: { 17 | type: 'string' 18 | }, 19 | major: { 20 | type: 'string' 21 | }, 22 | startYear: { 23 | type: 'string' 24 | }, 25 | endYear: { 26 | type: 'string' 27 | }, 28 | description: { 29 | type: 'string' 30 | } 31 | } 32 | 33 | }); 34 | -------------------------------------------------------------------------------- /api/api/models/EmailChange.js: -------------------------------------------------------------------------------- 1 | /** 2 | * emailChange.js 3 | * 4 | * @description :: TODO: You might write a short summary of how this model works and what it represents here. 5 | * @docs :: http://sailsjs.org/#!documentation/models 6 | */ 7 | 8 | var _ = require('lodash'); 9 | 10 | module.exports = _.merge(_.cloneDeep(require('./base')), { 11 | 12 | attributes: { 13 | userId: { 14 | model: 'user' 15 | }, 16 | token: { 17 | type: 'string', 18 | required: true 19 | }, 20 | email: { 21 | type: 'email', 22 | required: true 23 | }, 24 | toJSON: function() { 25 | var obj = this.toObject(); 26 | delete obj.token; 27 | return obj; 28 | } 29 | } 30 | 31 | }); 32 | -------------------------------------------------------------------------------- /api/api/models/Family.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Family.js 3 | * 4 | * @description :: TODO: You might write a short summary of how this model works and what it represents here. 5 | * @docs :: http://sailsjs.org/#!documentation/models 6 | */ 7 | 8 | var _ = require('lodash'); 9 | 10 | module.exports = _.merge(_.cloneDeep(require('./base')), { 11 | 12 | attributes: { 13 | userId: { 14 | model: 'user' 15 | }, 16 | name: { 17 | type: 'string' 18 | }, 19 | birthday: { 20 | type: 'date' 21 | }, 22 | relation: { 23 | type: 'string' 24 | } 25 | } 26 | 27 | }); 28 | -------------------------------------------------------------------------------- /api/api/models/File.js: -------------------------------------------------------------------------------- 1 | /** 2 | * File.js 3 | * 4 | * @description :: TODO: You might write a short summary of how this model works and what it represents here. 5 | * @docs :: http://sailsjs.org/#!documentation/models 6 | */ 7 | 8 | var _ = require('lodash'); 9 | 10 | module.exports = _.merge(_.cloneDeep(require('./base')), { 11 | 12 | attributes: { 13 | name: { 14 | type: 'string' 15 | }, 16 | description: { 17 | type: 'string' 18 | }, 19 | file: { 20 | type: 'string' 21 | }, 22 | size: { 23 | type: 'string' 24 | }, 25 | type: { 26 | type: 'string' 27 | }, 28 | owner: { 29 | model: 'user' 30 | }, 31 | shared: { 32 | type: 'array', 33 | defaultsTo: [] 34 | }, 35 | comments: { 36 | type: 'array', 37 | defaultsTo: [] 38 | }, 39 | folderId: { 40 | model: 'folder' 41 | }, 42 | getImage: function () { 43 | var image = false; 44 | var array = this.type.split("/"); 45 | if (array[0] == 'image') { 46 | image = true; 47 | } 48 | return image; 49 | }, 50 | toJSON: function() { 51 | var obj = this.toObject(); 52 | obj.image = this.getImage(); 53 | return obj; 54 | } 55 | } 56 | 57 | }); 58 | -------------------------------------------------------------------------------- /api/api/models/Folder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Folder.js 3 | * 4 | * @description :: TODO: You might write a short summary of how this model works and what it represents here. 5 | * @docs :: http://sailsjs.org/#!documentation/models 6 | */ 7 | 8 | var _ = require('lodash'); 9 | 10 | module.exports = _.merge(_.cloneDeep(require('./base')), { 11 | 12 | attributes: { 13 | name: { 14 | type: 'string' 15 | }, 16 | description: { 17 | type: 'string' 18 | }, 19 | url: { 20 | type: 'string' 21 | }, 22 | owner: { 23 | model: 'user' 24 | }, 25 | shared: { 26 | type: 'array', 27 | defaultsTo: [] 28 | }, 29 | comments: { 30 | type: 'array', 31 | defaultsTo: [] 32 | }, 33 | parentId: { 34 | type: 'string' 35 | }, 36 | files: { 37 | collection:'file', 38 | via: 'folderId' 39 | } 40 | } 41 | 42 | }); 43 | -------------------------------------------------------------------------------- /api/api/models/Gender.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Gender.js 3 | * 4 | * @description :: TODO: You might write a short summary of how this model works and what it represents here. 5 | * @docs :: http://sailsjs.org/#!documentation/models 6 | */ 7 | 8 | var _ = require('lodash'); 9 | 10 | module.exports = _.merge(_.cloneDeep(require('./base')), { 11 | 12 | attributes: { 13 | gender: { 14 | type: 'string', 15 | unique: true, 16 | required: true 17 | } 18 | } 19 | 20 | }); 21 | -------------------------------------------------------------------------------- /api/api/models/Job.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Job.js 3 | * 4 | * @description :: TODO: You might write a short summary of how this model works and what it represents here. 5 | * @docs :: http://sailsjs.org/#!documentation/models 6 | */ 7 | 8 | var _ = require('lodash'); 9 | 10 | module.exports = _.merge(_.cloneDeep(require('./base')), { 11 | 12 | attributes: { 13 | job: { 14 | type: 'string', 15 | unique: true, 16 | required: true 17 | } 18 | } 19 | 20 | }); 21 | -------------------------------------------------------------------------------- /api/api/models/Language.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Language.js 3 | * 4 | * @description :: TODO: You might write a short summary of how this model works and what it represents here. 5 | * @docs :: http://sailsjs.org/#!documentation/models 6 | */ 7 | 8 | var _ = require('lodash'); 9 | 10 | module.exports = _.merge(_.cloneDeep(require('./base')), { 11 | 12 | attributes: { 13 | language: { 14 | type: 'string', 15 | unique: true, 16 | required: true 17 | }, 18 | lang: { 19 | type: 'string', 20 | unique: true, 21 | required: true 22 | } 23 | } 24 | 25 | }); 26 | -------------------------------------------------------------------------------- /api/api/models/LogLogin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * LogLogin.js 3 | * 4 | * @description :: TODO: You might write a short summary of how this model works and what it represents here. 5 | * @docs :: http://sailsjs.org/#!documentation/models 6 | */ 7 | 8 | var _ = require('lodash'); 9 | 10 | module.exports = _.merge(_.cloneDeep(require('./base')), { 11 | 12 | attributes: { 13 | // User IP-address 14 | ip: { 15 | type: 'string', 16 | required: true 17 | }, 18 | // User hostname 19 | host: { 20 | type: 'string', 21 | required: true 22 | }, 23 | // User browser user-agent 24 | agent: { 25 | type: 'text', 26 | required: true 27 | }, 28 | // User browser 29 | browser: { 30 | type: 'string', 31 | defaultsTo: 'Unknown' 32 | }, 33 | // User browser version 34 | browserVersion: { 35 | type: 'string', 36 | defaultsTo: 'Unknown' 37 | }, 38 | // User browser family 39 | browserFamily: { 40 | type: 'string', 41 | defaultsTo: 'Unknown' 42 | }, 43 | // User operation system 44 | os: { 45 | type: 'string', 46 | defaultsTo: 'Unknown' 47 | }, 48 | // User operation system version 49 | osVersion: { 50 | type: 'string', 51 | defaultsTo: 'Unknown' 52 | }, 53 | // User operation system family 54 | osFamily: { 55 | type: 'string', 56 | defaultsTo: 'Unknown' 57 | }, 58 | // User device family 59 | device: { 60 | type: 'string', 61 | defaultsTo: 'Unknown' 62 | }, 63 | // This is needed for login summary data, dummy but no other choice atm... 64 | count: { 65 | type: 'integer', 66 | defaultsTo: 1 67 | }, 68 | 69 | // Below is all specification for relations to another models 70 | 71 | // Attached User object of this UserLogin 72 | user: { 73 | model: 'user', 74 | columnName: 'userId', 75 | required: true 76 | } 77 | } 78 | 79 | }); 80 | -------------------------------------------------------------------------------- /api/api/models/LogRequest.js: -------------------------------------------------------------------------------- 1 | /** 2 | * LogRequest.js 3 | * 4 | * @description :: TODO: You might write a short summary of how this model works and what it represents here. 5 | * @docs :: http://sailsjs.org/#!documentation/models 6 | */ 7 | 8 | var _ = require('lodash'); 9 | 10 | module.exports = _.merge(_.cloneDeep(require('./base')), { 11 | 12 | attributes: { 13 | // Request IP address 14 | ip: { 15 | type: 'string' 16 | }, 17 | // Request protocol 18 | protocol: { 19 | type: 'string' 20 | }, 21 | // Request method 22 | method: { 23 | type: 'string', 24 | required: true 25 | }, 26 | // Request URL 27 | url: { 28 | type: 'string', 29 | required: true 30 | }, 31 | // Request headers 32 | headers: { 33 | type: 'json' 34 | }, 35 | // Used parameters 36 | parameters: { 37 | type: 'json' 38 | }, 39 | // Request body 40 | body: { 41 | type: 'json' 42 | }, 43 | // Request query 44 | query: { 45 | type: 'json' 46 | }, 47 | // Request response time 48 | responseTime: { 49 | type: 'integer' 50 | }, 51 | // Middleware latency 52 | middlewareLatency: { 53 | type: 'integer' 54 | }, 55 | // This is needed for login summary data, dummy but no other choice atm... 56 | count: { 57 | type: 'integer', 58 | defaultsTo: 1 59 | }, 60 | 61 | // Below is all specification for relations to another models 62 | 63 | // User object 64 | user: { 65 | model: 'User', 66 | columnName: 'userId', 67 | required: true 68 | } 69 | } 70 | 71 | }); 72 | -------------------------------------------------------------------------------- /api/api/models/Module.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module.js 3 | * 4 | * @description :: TODO: You might write a short summary of how this model works and what it represents here. 5 | * @docs :: http://sailsjs.org/#!documentation/models 6 | */ 7 | 8 | var _ = require('lodash'); 9 | 10 | module.exports = _.merge(_.cloneDeep(require('./base')), { 11 | 12 | attributes: { 13 | title: { 14 | type: 'string', 15 | required: true 16 | }, 17 | icon: { 18 | type: 'string', 19 | defaultsTo: '' 20 | }, 21 | state: { 22 | type: 'string', 23 | defaultsTo: null 24 | }, 25 | url: { 26 | type: 'string', 27 | defaultsTo: null 28 | }, 29 | order: { 30 | type: 'integer' 31 | }, 32 | active: { 33 | type: 'boolean', 34 | defaultsTo: true 35 | }, 36 | lock: { 37 | type: 'boolean', 38 | defaultsTo: false 39 | }, 40 | submodules: { 41 | type: 'array', 42 | defaultsTo: [] 43 | } 44 | } 45 | 46 | }); 47 | -------------------------------------------------------------------------------- /api/api/models/PasswordReset.js: -------------------------------------------------------------------------------- 1 | /** 2 | * passwordReset.js 3 | * 4 | * @description :: TODO: You might write a short summary of how this model works and what it represents here. 5 | * @docs :: http://sailsjs.org/#!documentation/models 6 | */ 7 | 8 | var _ = require('lodash'); 9 | 10 | module.exports = _.merge(_.cloneDeep(require('./base')), { 11 | 12 | attributes: { 13 | userId: { 14 | model: 'user' 15 | }, 16 | token: { 17 | type: 'string', 18 | required: true 19 | }, 20 | toJSON: function() { 21 | var obj = this.toObject(); 22 | delete obj.token; 23 | return obj; 24 | } 25 | } 26 | 27 | }); 28 | -------------------------------------------------------------------------------- /api/api/models/Photo.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Photo.js 3 | * 4 | * @description :: TODO: You might write a short summary of how this model works and what it represents here. 5 | * @docs :: http://sailsjs.org/#!documentation/models 6 | */ 7 | 8 | var _ = require('lodash'); 9 | 10 | module.exports = _.merge(_.cloneDeep(require('./base')), { 11 | 12 | attributes: { 13 | name: { 14 | type: 'string' 15 | }, 16 | filename: { 17 | type: 'string' 18 | }, 19 | user: { 20 | model: 'user' 21 | } 22 | } 23 | 24 | }); 25 | -------------------------------------------------------------------------------- /api/api/models/Place.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Place.js 3 | * 4 | * @description :: TODO: You might write a short summary of how this model works and what it represents here. 5 | * @docs :: http://sailsjs.org/#!documentation/models 6 | */ 7 | 8 | var _ = require('lodash'); 9 | 10 | module.exports = _.merge(_.cloneDeep(require('./base')), { 11 | 12 | attributes: { 13 | userId: { 14 | model: 'user' 15 | }, 16 | adress: { 17 | type: 'string' 18 | }, 19 | currently: { 20 | type: 'boolean', 21 | defaultsTo: false 22 | } 23 | } 24 | 25 | }); 26 | -------------------------------------------------------------------------------- /api/api/models/Profile.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Profile.js 3 | * 4 | * @description :: TODO: You might write a short summary of how this model works and what it represents here. 5 | * @docs :: http://sailsjs.org/#!documentation/models 6 | */ 7 | 8 | var _ = require('lodash'); 9 | 10 | module.exports = _.merge(_.cloneDeep(require('./base')), { 11 | 12 | attributes: { 13 | user: { 14 | model: 'user' 15 | }, 16 | job: { 17 | type: 'string', 18 | defaultsTo: '' 19 | }, 20 | department: { 21 | type: 'string', 22 | defaultsTo: '' 23 | }, 24 | company: { 25 | type: 'string', 26 | defaultsTo: '' 27 | }, 28 | gender: { 29 | type: 'string', 30 | defaultsTo: '' 31 | }, 32 | birthday: { 33 | type: 'date', 34 | defaultsTo: '' 35 | }, 36 | relationship: { 37 | type: 'string', 38 | defaultsTo: '' 39 | }, 40 | contact: { 41 | type: 'json', 42 | defaultsTo: { 43 | emails: [], 44 | phones: [] 45 | } 46 | }, 47 | toJSON: function() { 48 | var obj = this.toObject(); 49 | return obj; 50 | } 51 | } 52 | 53 | }); 54 | -------------------------------------------------------------------------------- /api/api/models/Relation.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Relation.js 3 | * 4 | * @description :: TODO: You might write a short summary of how this model works and what it represents here. 5 | * @docs :: http://sailsjs.org/#!documentation/models 6 | */ 7 | 8 | var _ = require('lodash'); 9 | 10 | module.exports = _.merge(_.cloneDeep(require('./base')), { 11 | 12 | attributes: { 13 | relation: { 14 | type: 'string', 15 | unique: true, 16 | required: true 17 | } 18 | } 19 | 20 | }); 21 | -------------------------------------------------------------------------------- /api/api/models/Relationship.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Relationship.js 3 | * 4 | * @description :: TODO: You might write a short summary of how this model works and what it represents here. 5 | * @docs :: http://sailsjs.org/#!documentation/models 6 | */ 7 | 8 | var _ = require('lodash'); 9 | 10 | module.exports = _.merge(_.cloneDeep(require('./base')), { 11 | 12 | attributes: { 13 | relationship: { 14 | type: 'string', 15 | unique: true, 16 | required: true 17 | } 18 | } 19 | 20 | }); 21 | -------------------------------------------------------------------------------- /api/api/models/UserRole.js: -------------------------------------------------------------------------------- 1 | /** 2 | * UserRole.js 3 | * 4 | * @description :: TODO: You might write a short summary of how this model works and what it represents here. 5 | * @docs :: http://sailsjs.org/#!documentation/models 6 | */ 7 | 8 | var _ = require('lodash'); 9 | 10 | module.exports = _.merge(_.cloneDeep(require('./base')), { 11 | 12 | attributes: { 13 | role: { 14 | type: 'string', 15 | unique: true, 16 | required: true 17 | }, 18 | description: { 19 | type: 'text' 20 | }, 21 | lock: { 22 | type: 'boolean', 23 | defaultsTo: false 24 | }, 25 | users: { 26 | collection: 'user', 27 | via: 'role' 28 | }, 29 | permissions: { 30 | type: 'json', 31 | defaultsTo: {} 32 | } 33 | } 34 | 35 | }); 36 | -------------------------------------------------------------------------------- /api/api/models/base.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Base.js 3 | * 4 | * @description :: TODO: You might write a short summary of how this model works and what it represents here. 5 | * @docs :: http://sailsjs.org/#!documentation/models 6 | */ 7 | 8 | module.exports = { 9 | 10 | schema: true, 11 | 12 | attributes: { 13 | createdUser: { 14 | model: 'user', 15 | defaultsTo: null 16 | //required: true 17 | }, 18 | updatedUser: { 19 | model: 'user', 20 | defaultsTo: null 21 | //required: true 22 | }, 23 | deletedAt: { 24 | type: 'datetime', 25 | defaultsTo: null 26 | } 27 | // toJSON: function() { 28 | // var obj = this.toObject(); 29 | // if (obj.deletedAt === null) { 30 | // obj.toJSON = null; 31 | // delete obj.toJSON; 32 | // return obj; 33 | // } 34 | // } 35 | } 36 | // afterCreate: function(values, cb) { 37 | // if (values.user && values.body) { 38 | // values.body.createdUser = values.user; 39 | // values.body.updatedUser = values.user; 40 | // console.log(values); 41 | // cb(); 42 | // } else { 43 | // cb(); 44 | // } 45 | // } 46 | 47 | }; 48 | -------------------------------------------------------------------------------- /api/api/models/hello.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | 3 | module.exports = _.merge(_.cloneDeep(require('./base')), { 4 | 5 | attributes: { 6 | greeting: { 7 | type:'string' 8 | } 9 | } 10 | 11 | }); 12 | -------------------------------------------------------------------------------- /api/api/policies/isAuthenticated.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = function(req, res, next) { 3 | 4 | //console.log(req.isSocket); 5 | //console.log(req.headers); 6 | 7 | if (req.headers && req.headers.authorization) { 8 | 9 | JWTService.verify(req.headers.authorization, function(err, token) { 10 | //console.log(err); 11 | //console.log(token); 12 | if (err) return res.json(401, {error: 'The token is not valid'}); 13 | 14 | req.token = token; 15 | // req.body.createdUser = token.id; 16 | // req.body.updatedUser = token.id; 17 | 18 | next(); 19 | }); 20 | 21 | }else{ 22 | return res.json(403, {error: 'The token not exist'}); 23 | } 24 | 25 | }; 26 | -------------------------------------------------------------------------------- /api/api/policies/sessionAuth.js: -------------------------------------------------------------------------------- 1 | /** 2 | * sessionAuth 3 | * 4 | * @module :: Policy 5 | * @description :: Simple policy to allow any authenticated user 6 | * Assumes that your login action in one of your controllers sets `req.session.authenticated = true;` 7 | * @docs :: http://sailsjs.org/#!documentation/policies 8 | * 9 | */ 10 | module.exports = function(req, res, next) { 11 | 12 | // User is allowed, proceed to the next policy, 13 | // or if this is the last policy, the controller 14 | if (req.session.authenticated) { 15 | return next(); 16 | } 17 | 18 | // User is not allowed 19 | // (default res.forbidden() behavior can be overridden in `config/403.js`) 20 | return res.forbidden('You are not permitted to perform this action.'); 21 | }; 22 | -------------------------------------------------------------------------------- /api/api/responses/badRequest.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 400 (Bad Request) Handler 3 | * 4 | * Usage: 5 | * return res.badRequest(); 6 | * return res.badRequest(data); 7 | * return res.badRequest(data, 'some/specific/badRequest/view'); 8 | * 9 | * e.g.: 10 | * ``` 11 | * return res.badRequest( 12 | * 'Please choose a valid `password` (6-12 characters)', 13 | * 'trial/signup' 14 | * ); 15 | * ``` 16 | */ 17 | 18 | module.exports = function badRequest(data, options) { 19 | 20 | // Get access to `req`, `res`, & `sails` 21 | var req = this.req; 22 | var res = this.res; 23 | var sails = req._sails; 24 | 25 | // Set status code 26 | res.status(400); 27 | 28 | // Log error to console 29 | if (data !== undefined) { 30 | sails.log.verbose('Sending 400 ("Bad Request") response: \n',data); 31 | } 32 | else sails.log.verbose('Sending 400 ("Bad Request") response'); 33 | 34 | // Only include errors in response if application environment 35 | // is not set to 'production'. In production, we shouldn't 36 | // send back any identifying information about errors. 37 | if (sails.config.environment === 'production') { 38 | data = undefined; 39 | } 40 | 41 | // If the user-agent wants JSON, always respond with JSON 42 | if (req.wantsJSON) { 43 | return res.jsonx(data); 44 | } 45 | 46 | // If second argument is a string, we take that to mean it refers to a view. 47 | // If it was omitted, use an empty object (`{}`) 48 | options = (typeof options === 'string') ? { view: options } : options || {}; 49 | 50 | // If a view was provided in options, serve it. 51 | // Otherwise try to guess an appropriate view, or if that doesn't 52 | // work, just send JSON. 53 | if (options.view) { 54 | return res.view(options.view, { data: data }); 55 | } 56 | 57 | // If no second argument provided, try to serve the implied view, 58 | // but fall back to sending JSON(P) if no view can be inferred. 59 | else return res.guessView({ data: data }, function couldNotGuessView () { 60 | return res.jsonx(data); 61 | }); 62 | 63 | }; 64 | 65 | -------------------------------------------------------------------------------- /api/api/responses/forbidden.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 403 (Forbidden) Handler 3 | * 4 | * Usage: 5 | * return res.forbidden(); 6 | * return res.forbidden(err); 7 | * return res.forbidden(err, 'some/specific/forbidden/view'); 8 | * 9 | * e.g.: 10 | * ``` 11 | * return res.forbidden('Access denied.'); 12 | * ``` 13 | */ 14 | 15 | module.exports = function forbidden (data, options) { 16 | 17 | // Get access to `req`, `res`, & `sails` 18 | var req = this.req; 19 | var res = this.res; 20 | var sails = req._sails; 21 | 22 | // Set status code 23 | res.status(403); 24 | 25 | // Log error to console 26 | if (data !== undefined) { 27 | sails.log.verbose('Sending 403 ("Forbidden") response: \n',data); 28 | } 29 | else sails.log.verbose('Sending 403 ("Forbidden") response'); 30 | 31 | // Only include errors in response if application environment 32 | // is not set to 'production'. In production, we shouldn't 33 | // send back any identifying information about errors. 34 | if (sails.config.environment === 'production') { 35 | data = undefined; 36 | } 37 | 38 | // If the user-agent wants JSON, always respond with JSON 39 | if (req.wantsJSON) { 40 | return res.jsonx(data); 41 | } 42 | 43 | // If second argument is a string, we take that to mean it refers to a view. 44 | // If it was omitted, use an empty object (`{}`) 45 | options = (typeof options === 'string') ? { view: options } : options || {}; 46 | 47 | // If a view was provided in options, serve it. 48 | // Otherwise try to guess an appropriate view, or if that doesn't 49 | // work, just send JSON. 50 | if (options.view) { 51 | return res.view(options.view, { data: data }); 52 | } 53 | 54 | // If no second argument provided, try to serve the default view, 55 | // but fall back to sending JSON(P) if any errors occur. 56 | else return res.view('403', { data: data }, function (err, html) { 57 | 58 | // If a view error occured, fall back to JSON(P). 59 | if (err) { 60 | // 61 | // Additionally: 62 | // • If the view was missing, ignore the error but provide a verbose log. 63 | if (err.code === 'E_VIEW_FAILED') { 64 | sails.log.verbose('res.forbidden() :: Could not locate view for error page (sending JSON instead). Details: ',err); 65 | } 66 | // Otherwise, if this was a more serious error, log to the console with the details. 67 | else { 68 | sails.log.warn('res.forbidden() :: When attempting to render error page view, an error occured (sending JSON instead). Details: ', err); 69 | } 70 | return res.jsonx(data); 71 | } 72 | 73 | return res.send(html); 74 | }); 75 | 76 | }; 77 | 78 | -------------------------------------------------------------------------------- /api/api/responses/found.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 302 (Not Found) Handler 3 | * 4 | * Usage: 5 | * return res.notFound(); 6 | * return res.notFound(err); 7 | * return res.notFound(err, 'some/specific/notfound/view'); 8 | * 9 | * e.g.: 10 | * ``` 11 | * return res.notFound(); 12 | * ``` 13 | * 14 | * NOTE: 15 | * If a request doesn't match any explicit routes (i.e. `config/routes.js`) 16 | * or route blueprints (i.e. "shadow routes", Sails will call `res.notFound()` 17 | * automatically. 18 | */ 19 | 20 | module.exports = function notFound (data, options) { 21 | 22 | // Get access to `req`, `res`, & `sails` 23 | var req = this.req; 24 | var res = this.res; 25 | var sails = req._sails; 26 | 27 | // Set status code 28 | res.status(302); 29 | 30 | // Log error to console 31 | if (data !== undefined) { 32 | sails.log.verbose('Sending 302 ("Not Found") response: \n',data); 33 | } 34 | else sails.log.verbose('Sending 302 ("Not Found") response'); 35 | 36 | // Only include errors in response if application environment 37 | // is not set to 'production'. In production, we shouldn't 38 | // send back any identifying information about errors. 39 | if (sails.config.environment === 'production') { 40 | data = undefined; 41 | } 42 | 43 | // If the user-agent wants JSON, always respond with JSON 44 | if (req.wantsJSON) { 45 | return res.jsonx(data); 46 | } 47 | 48 | // If second argument is a string, we take that to mean it refers to a view. 49 | // If it was omitted, use an empty object (`{}`) 50 | options = (typeof options === 'string') ? { view: options } : options || {}; 51 | 52 | // If a view was provided in options, serve it. 53 | // Otherwise try to guess an appropriate view, or if that doesn't 54 | // work, just send JSON. 55 | if (options.view) { 56 | return res.view(options.view, { data: data }); 57 | } 58 | 59 | // If no second argument provided, try to serve the default view, 60 | // but fall back to sending JSON(P) if any errors occur. 61 | else return res.view('302', { data: data }, function (err, html) { 62 | 63 | // If a view error occured, fall back to JSON(P). 64 | if (err) { 65 | // 66 | // Additionally: 67 | // • If the view was missing, ignore the error but provide a verbose log. 68 | if (err.code === 'E_VIEW_FAILED') { 69 | sails.log.verbose('res.notFound() :: Could not locate view for error page (sending JSON instead). Details: ',err); 70 | } 71 | // Otherwise, if this was a more serious error, log to the console with the details. 72 | else { 73 | sails.log.warn('res.notFound() :: When attempting to render error page view, an error occured (sending JSON instead). Details: ', err); 74 | } 75 | return res.jsonx(data); 76 | } 77 | 78 | return res.send(html); 79 | }); 80 | 81 | }; 82 | -------------------------------------------------------------------------------- /api/api/responses/ok.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 200 (OK) Response 3 | * 4 | * Usage: 5 | * return res.ok(); 6 | * return res.ok(data); 7 | * return res.ok(data, 'auth/login'); 8 | * 9 | * @param {Object} data 10 | * @param {String|Object} options 11 | * - pass string to render specified view 12 | */ 13 | 14 | module.exports = function sendOK (data, options) { 15 | 16 | // Get access to `req`, `res`, & `sails` 17 | var req = this.req; 18 | var res = this.res; 19 | var sails = req._sails; 20 | 21 | sails.log.silly('res.ok() :: Sending 200 ("OK") response'); 22 | 23 | // Set status code 24 | res.status(200); 25 | 26 | // If appropriate, serve data as JSON(P) 27 | if (req.wantsJSON) { 28 | return res.jsonx(data); 29 | } 30 | 31 | // If second argument is a string, we take that to mean it refers to a view. 32 | // If it was omitted, use an empty object (`{}`) 33 | options = (typeof options === 'string') ? { view: options } : options || {}; 34 | 35 | // If a view was provided in options, serve it. 36 | // Otherwise try to guess an appropriate view, or if that doesn't 37 | // work, just send JSON. 38 | if (options.view) { 39 | return res.view(options.view, { data: data }); 40 | } 41 | 42 | // If no second argument provided, try to serve the implied view, 43 | // but fall back to sending JSON(P) if no view can be inferred. 44 | else return res.guessView({ data: data }, function couldNotGuessView () { 45 | return res.jsonx(data); 46 | }); 47 | 48 | }; 49 | -------------------------------------------------------------------------------- /api/api/responses/serverError.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 500 (Server Error) Response 3 | * 4 | * Usage: 5 | * return res.serverError(); 6 | * return res.serverError(err); 7 | * return res.serverError(err, 'some/specific/error/view'); 8 | * 9 | * NOTE: 10 | * If something throws in a policy or controller, or an internal 11 | * error is encountered, Sails will call `res.serverError()` 12 | * automatically. 13 | */ 14 | 15 | module.exports = function serverError (data, options) { 16 | 17 | // Get access to `req`, `res`, & `sails` 18 | var req = this.req; 19 | var res = this.res; 20 | var sails = req._sails; 21 | 22 | // Set status code 23 | res.status(500); 24 | 25 | // Log error to console 26 | if (data !== undefined) { 27 | sails.log.error('Sending 500 ("Server Error") response: \n',data); 28 | } 29 | else sails.log.error('Sending empty 500 ("Server Error") response'); 30 | 31 | // Only include errors in response if application environment 32 | // is not set to 'production'. In production, we shouldn't 33 | // send back any identifying information about errors. 34 | if (sails.config.environment === 'production') { 35 | data = undefined; 36 | } 37 | 38 | // If the user-agent wants JSON, always respond with JSON 39 | if (req.wantsJSON) { 40 | return res.jsonx(data); 41 | } 42 | 43 | // If second argument is a string, we take that to mean it refers to a view. 44 | // If it was omitted, use an empty object (`{}`) 45 | options = (typeof options === 'string') ? { view: options } : options || {}; 46 | 47 | // If a view was provided in options, serve it. 48 | // Otherwise try to guess an appropriate view, or if that doesn't 49 | // work, just send JSON. 50 | if (options.view) { 51 | return res.view(options.view, { data: data }); 52 | } 53 | 54 | // If no second argument provided, try to serve the default view, 55 | // but fall back to sending JSON(P) if any errors occur. 56 | else return res.view('500', { data: data }, function (err, html) { 57 | 58 | // If a view error occured, fall back to JSON(P). 59 | if (err) { 60 | // 61 | // Additionally: 62 | // • If the view was missing, ignore the error but provide a verbose log. 63 | if (err.code === 'E_VIEW_FAILED') { 64 | sails.log.verbose('res.serverError() :: Could not locate view for error page (sending JSON instead). Details: ',err); 65 | } 66 | // Otherwise, if this was a more serious error, log to the console with the details. 67 | else { 68 | sails.log.warn('res.serverError() :: When attempting to render error page view, an error occured (sending JSON instead). Details: ', err); 69 | } 70 | return res.jsonx(data); 71 | } 72 | 73 | return res.send(html); 74 | }); 75 | 76 | }; 77 | 78 | -------------------------------------------------------------------------------- /api/api/services/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modulr/sails-angularjs/c99442dc9fa2402d71832fd44b793c009fdbebd9/api/api/services/.gitkeep -------------------------------------------------------------------------------- /api/api/services/EmailService.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 3 | /** 4 | * @param template {String} 5 | * @param options {Object} 6 | */ 7 | send: function(template, options){ 8 | sails.hooks.email.send(template, options, 9 | { 10 | to: options.to, 11 | subject: options.subject, 12 | }, 13 | function(err) {console.log(err || "It worked!");} 14 | // function(err) { 15 | // if(err) return err; 16 | // } 17 | ); 18 | }, 19 | 20 | sendSimple: function(template, options, req){ 21 | 22 | sails.models.user.findOne({ id: options.to }) 23 | .exec(function(err, user){ 24 | 25 | req.setLocale(user.lang); 26 | 27 | options.email = user.email; 28 | options.name = user.fullName || user.username; 29 | options.data.hi = req.__('hi', options.name); 30 | options.data.team = req.__('team'); 31 | 32 | options.data.paragraph2 = (options.data.paragraph2) ? options.data.paragraph2 : ''; 33 | options.data.paragraph3 = (options.data.paragraph3) ? options.data.paragraph3 : ''; 34 | options.data.paragraph4 = (options.data.paragraph4) ? options.data.paragraph4 : ''; 35 | 36 | sails.hooks.email.send(template, options, 37 | { 38 | to: options.email, 39 | subject: options.subject 40 | }, 41 | function(err) {console.log(err || "It worked!");} 42 | // function(err) { 43 | // if(err) return err; 44 | // } 45 | ); 46 | }); 47 | } 48 | 49 | }; 50 | -------------------------------------------------------------------------------- /api/api/services/EncryptService.js: -------------------------------------------------------------------------------- 1 | var bcrypt = require('bcrypt'); 2 | 3 | module.exports = { 4 | encrypt: function(value, cb){ 5 | bcrypt.genSalt(10, function(err, salt) { 6 | bcrypt.hash(value, salt, function(err, hash){ 7 | if(err) return cb(err); 8 | cb(null, hash); 9 | }); 10 | }); 11 | }, 12 | compare: function(password1, password2, cb){ 13 | bcrypt.compare( password1, password2, function(err, valid){ 14 | if(err) return cb(err); 15 | cb(null, valid); 16 | }); 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /api/api/services/FileService.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 3 | getHumanFileSize: function(fileSizeInBytes) { 4 | var i = -1; 5 | var byteUnits = [' kB', ' MB', ' GB', ' TB', ' PB', ' EB', ' ZB', ' YB']; 6 | do { 7 | fileSizeInBytes = fileSizeInBytes / 1024; 8 | i++; 9 | } while (fileSizeInBytes > 1024); 10 | 11 | return Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i]; 12 | }, 13 | 14 | getRealFileName: function(file) { 15 | var array = file.fd.split("/"); 16 | return array[array.length - 1]; 17 | } 18 | 19 | }; 20 | -------------------------------------------------------------------------------- /api/api/services/JWTService.js: -------------------------------------------------------------------------------- 1 | var jwt = require('jsonwebtoken'); 2 | 3 | module.exports = { 4 | issue: function(payload, expires){ 5 | return jwt.sign({ id: payload }, sails.config.settings.TOKEN_SECRET, { expiresInMinutes: expires }); 6 | }, 7 | verify: function(token, verified){ 8 | return jwt.verify(token, sails.config.settings.TOKEN_SECRET || 'shhhhh', {}, verified); 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /api/api/services/LogService.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 3 | login: function(user, req) 4 | { 5 | // Parse detailed information from user-agent string 6 | var r = require('ua-parser').parse(req.headers['user-agent']); 7 | // Create new UserLogin row to database 8 | sails.models.loglogin.create({ 9 | ip: req.ip, 10 | host: req.host, 11 | agent: req.headers['user-agent'], 12 | browser: r.ua.toString(), 13 | browserVersion: r.ua.toVersionString(), 14 | browserFamily: r.ua.family, 15 | os: r.os.toString(), 16 | osVersion: r.os.toVersionString(), 17 | osFamily: r.os.family, 18 | device: r.device.family, 19 | user: user.id 20 | }) 21 | .exec(function(err, created) { 22 | if(err) sails.log(err); 23 | 24 | created.user = user; 25 | sails.models.loglogin.publishCreate(created); 26 | }); 27 | }, 28 | 29 | request: function(log, req, resp) 30 | { 31 | //var userId = -1; 32 | 33 | // if (req.token) { 34 | // userId = req.token; 35 | // } else { 36 | // userId = -1; 37 | // } 38 | 39 | sails.models.logrequest.create({ 40 | ip: log.ip, 41 | protocol: log.protocol, 42 | method: log.method, 43 | url: log.diagnostic.url, 44 | headers: req.headers || {}, 45 | parameters: log.diagnostic.routeParams, 46 | body: log.diagnostic.bodyParams, 47 | query: log.diagnostic.queryParams, 48 | responseTime: log.responseTime || 0, 49 | middlewareLatency: log.diagnostic.middlewareLatency || 0, 50 | user: req.token || 0 51 | }) 52 | .exec(function(err, created) { 53 | if(err) sails.log(err); 54 | 55 | sails.models.logrequest.publishCreate(created); 56 | }); 57 | } 58 | 59 | }; 60 | -------------------------------------------------------------------------------- /api/api/services/RandTokenService.js: -------------------------------------------------------------------------------- 1 | var randtoken = require('rand-token'); 2 | 3 | module.exports = { 4 | generate: function(){ 5 | return randtoken.generate(16); 6 | } 7 | }; 8 | -------------------------------------------------------------------------------- /api/app.js: -------------------------------------------------------------------------------- 1 | /** 2 | * app.js 3 | * 4 | * Use `app.js` to run your app without `sails lift`. 5 | * To start the server, run: `node app.js`. 6 | * 7 | * This is handy in situations where the sails CLI is not relevant or useful. 8 | * 9 | * For example: 10 | * => `node app.js` 11 | * => `forever start app.js` 12 | * => `node debug app.js` 13 | * => `modulus deploy` 14 | * => `heroku scale` 15 | * 16 | * 17 | * The same command-line arguments are supported, e.g.: 18 | * `node app.js --silent --port=80 --prod` 19 | */ 20 | 21 | // Ensure we're in the project directory, so relative paths work as expected 22 | // no matter where we actually lift from. 23 | process.chdir(__dirname); 24 | 25 | // Ensure a "sails" can be located: 26 | (function() { 27 | var sails; 28 | try { 29 | sails = require('sails'); 30 | } catch (e) { 31 | console.error('To run an app using `node app.js`, you usually need to have a version of `sails` installed in the same directory as your app.'); 32 | console.error('To do that, run `npm install sails`'); 33 | console.error(''); 34 | console.error('Alternatively, if you have sails installed globally (i.e. you did `npm install -g sails`), you can use `sails lift`.'); 35 | console.error('When you run `sails lift`, your app will still use a local `./node_modules/sails` dependency if it exists,'); 36 | console.error('but if it doesn\'t, the app will run with the global sails instead!'); 37 | return; 38 | } 39 | 40 | // Try to get `rc` dependency 41 | var rc; 42 | try { 43 | rc = require('rc'); 44 | } catch (e0) { 45 | try { 46 | rc = require('sails/node_modules/rc'); 47 | } catch (e1) { 48 | console.error('Could not find dependency: `rc`.'); 49 | console.error('Your `.sailsrc` file(s) will be ignored.'); 50 | console.error('To resolve this, run:'); 51 | console.error('npm install rc --save'); 52 | rc = function () { return {}; }; 53 | } 54 | } 55 | 56 | 57 | // Start server 58 | sails.lift(rc('sails')); 59 | })(); 60 | -------------------------------------------------------------------------------- /api/config/apianalytics.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | apianalytics: { 3 | /** 4 | * The types of requests to log 5 | * (e.g. ["get /foo/bar", "post /foo", "/*"]) 6 | * Defaults to all routes. 7 | */ 8 | routesToLog: [ 9 | '/*' 10 | ], 11 | 12 | /** 13 | * Parameters which should NEVER be logged 14 | * (e.g. "password") 15 | * If seen, they will be replaced with "*PROTECTED*" 16 | */ 17 | dontLogParams: ['password', 'token'], 18 | 19 | // When request starts 20 | onRequest: function onRequest(log, req, res) { 21 | // Defaults to doing nothing 22 | }, 23 | 24 | // When request is done 25 | onResponse: function onResponse(log, req, res) { 26 | // Defaults to logging request metadata to the console in a vaguely attractive way 27 | LogService.request(log, req, res); 28 | } 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /api/config/bootstrap.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Bootstrap 3 | * (sails.config.bootstrap) 4 | * 5 | * An asynchronous bootstrap function that runs before your Sails app gets lifted. 6 | * This gives you an opportunity to set up your data model, run jobs, or perform some special logic. 7 | * 8 | * For more information on bootstrapping your app, check out: 9 | * http://sailsjs.org/#/documentation/reference/sails.config/sails.config.bootstrap.html 10 | */ 11 | 12 | module.exports.bootstrap = function(cb) { 13 | 14 | // It's very important to trigger this callback method when you are finished 15 | // with the bootstrap! (otherwise your server will never lift, since it's waiting on the bootstrap) 16 | cb(); 17 | }; 18 | -------------------------------------------------------------------------------- /api/config/email.js: -------------------------------------------------------------------------------- 1 | module.exports.email = { 2 | 3 | }; 4 | -------------------------------------------------------------------------------- /api/config/env/development.example.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Development environment settings 3 | * 4 | * This file can include shared settings for a development team, 5 | * such as API keys or remote database passwords. If you're using 6 | * a version control solution for your Sails app, this file will 7 | * be committed to your repository unless you add it to your .gitignore 8 | * file. If your repository will be publicly viewable, don't add 9 | * any private information to this file! 10 | * 11 | */ 12 | 13 | module.exports = { 14 | 15 | /*************************************************************************** 16 | * Set the default database connection for models in the development * 17 | * environment (see config/connections.js and config/models.js ) * 18 | ***************************************************************************/ 19 | 20 | settings: { 21 | APP_URL: 'http://localhost:3000', 22 | STORAGE: '../app/storage', 23 | TOKEN_SECRET: 'shhhhh', 24 | TOKEN_EXPIRES_IN_MINUTES: 1440, // 1 dia 25 | REMEMBER_TOKEN_EXPIRES_IN_MINUTES: 43200, // 30 dias 26 | }, 27 | 28 | email: { 29 | transporter: { 30 | host: 'localhost', 31 | port: 465, 32 | secure: true, // use SSL 33 | auth: { 34 | user: 'email@example.com', 35 | pass: 'password' 36 | } 37 | }, 38 | from: 'Modulr ', 39 | testMode: true 40 | }, 41 | 42 | connections: { 43 | mongo: { 44 | adapter: 'sails-mongo', 45 | host: 'localhost', 46 | port: 27017, 47 | // user: 'username', 48 | // password: 'password', 49 | database: 'modulr', 50 | socketOptions: { 51 | noDelay: true, 52 | connectTimeoutMS: 0, 53 | socketTimeoutMS: 0 54 | } 55 | } 56 | }, 57 | 58 | models: { 59 | connection: 'mongo', 60 | migrate: 'alter' 61 | }, 62 | 63 | cors: { 64 | allRoutes: true, 65 | headers: 'content-type, access-control-allow-origin, authorization' 66 | }, 67 | 68 | globals: { 69 | models: false 70 | }, 71 | 72 | sockets: { 73 | transports: [ 74 | 'websocket' 75 | // 'htmlfile', 76 | // 'polling' 77 | ] 78 | // origins: '*:*' 79 | } 80 | 81 | }; 82 | -------------------------------------------------------------------------------- /api/config/env/production.example.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Production environment settings 3 | * 4 | * This file can include shared settings for a production environment, 5 | * such as API keys or remote database passwords. If you're using 6 | * a version control solution for your Sails app, this file will 7 | * be committed to your repository unless you add it to your .gitignore 8 | * file. If your repository will be publicly viewable, don't add 9 | * any private information to this file! 10 | * 11 | */ 12 | 13 | module.exports = { 14 | 15 | /*************************************************************************** 16 | * Set the default database connection for models in the production * 17 | * environment (see config/connections.js and config/models.js ) * 18 | ***************************************************************************/ 19 | 20 | settings: { 21 | APP_URL: 'http://localhost', 22 | STORAGE: '../app/storage', 23 | TOKEN_SECRET: 'shhhhh', 24 | TOKEN_EXPIRES_IN_MINUTES: 1440, // 1 dia 25 | REMEMBER_TOKEN_EXPIRES_IN_MINUTES: 43200, // 30 dias 26 | }, 27 | 28 | email: { 29 | transporter: { 30 | host: 'localhost', 31 | port: 465, 32 | secure: true, // use SSL 33 | auth: { 34 | user: 'email@example.com', 35 | pass: 'password' 36 | } 37 | }, 38 | from: 'Modulr ', 39 | testMode: false 40 | }, 41 | 42 | connections: { 43 | mongo: { 44 | adapter: 'sails-mongo', 45 | host: 'localhost', 46 | port: 27017, 47 | // user: 'username', 48 | // password: 'password', 49 | database: 'modulr', 50 | socketOptions: { 51 | noDelay: true, 52 | connectTimeoutMS: 0, 53 | socketTimeoutMS: 0 54 | } 55 | } 56 | }, 57 | 58 | session: { 59 | adapter: 'mongo', 60 | host: 'localhost', 61 | port: 27017, 62 | db: 'modulr', 63 | collection: 'sessions' 64 | }, 65 | 66 | models: { 67 | connection: 'mongo', 68 | migrate: 'alter' 69 | }, 70 | 71 | cors: { 72 | allRoutes: true, 73 | headers: 'content-type, access-control-allow-origin, authorization' 74 | }, 75 | 76 | globals: { 77 | models: false 78 | }, 79 | 80 | sockets: { 81 | transports: [ 82 | 'websocket' 83 | // 'htmlfile', 84 | // 'polling' 85 | ] 86 | // origins: '*:*' 87 | } 88 | 89 | }; 90 | -------------------------------------------------------------------------------- /api/config/locales/_README.md: -------------------------------------------------------------------------------- 1 | # Internationalization / Localization Settings 2 | 3 | > Also see the official docs on internationalization/localization: 4 | > http://links.sailsjs.org/docs/config/locales 5 | 6 | ## Locales 7 | All locale files live under `config/locales`. Here is where you can add translations 8 | as JSON key-value pairs. The name of the file should match the language that you are supporting, which allows for automatic language detection based on request headers. 9 | 10 | Here is an example locale stringfile for the Spanish language (`config/locales/es.json`): 11 | ```json 12 | { 13 | "Hello!": "Hola!", 14 | "Hello %s, how are you today?": "¿Hola %s, como estas?", 15 | } 16 | ``` 17 | ## Usage 18 | Locales can be accessed in controllers/policies through `res.i18n()`, or in views through the `__(key)` or `i18n(key)` functions. 19 | Remember that the keys are case sensitive and require exact key matches, e.g. 20 | 21 | ```ejs 22 |

<%= __('Welcome to PencilPals!') %>

23 |

<%= i18n('Hello %s, how are you today?', 'Pencil Maven') %>

24 |

<%= i18n('That\'s right-- you can use either i18n() or __()') %>

25 | ``` 26 | 27 | ## Configuration 28 | Localization/internationalization config can be found in `config/i18n.js`, from where you can set your supported locales. 29 | -------------------------------------------------------------------------------- /api/config/locales/de.json: -------------------------------------------------------------------------------- 1 | { 2 | "Welcome": "Willkommen", 3 | "A brand new app.": "Eine neue App." 4 | } 5 | -------------------------------------------------------------------------------- /api/config/locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "hi": "Hi %s,", 3 | "link-duration": "The link has a duration of 24 hours.", 4 | "team": "Team Modulr", 5 | 6 | "signup.subject": "Confirm your email address - Modulr", 7 | "signup.paragraph": "Welcome to Modulr! Before you begin, you must confirm your email address.", 8 | "signup.btn": "Confirm email", 9 | 10 | "welcome.subject": "Welcome to Modulr", 11 | "welcome.paragraph": "Welcome to Modulr! You have completed your registration and your account is active.", 12 | 13 | "password-reset.subject": "Reset your password - Modulr", 14 | "password-reset.paragraph": "We received a request to reset the password for your account.", 15 | "password-reset.paragraph2": "If you requested a reset the password for %s, click the button below. If you didn’t make this request, please ignore this email.", 16 | "password-reset.btn": "Reset password", 17 | 18 | "password-update.subject": "Password updated - Modulr", 19 | "password-update.paragraph": "You have successfully changed the password.", 20 | 21 | "send-user-data.subject": "Your account details - Modulr", 22 | "send-user-data.paragraph": "These are the details of your account Modulr, you need to establish your password to access.", 23 | 24 | "email-change.subject": "Change your email address - Modulr", 25 | "email-change.paragraph": "We received a request to change the email address for your account.", 26 | "email-change.paragraph2": "If you requested a change the email address associated with this account %s, you must confirm your email address. If you didn’t make this request, please ignore this email.", 27 | "email-change.btn": "Confirm email", 28 | 29 | "email-change-update.subject": "Email updated - Modulr", 30 | "email-change-update.paragraph": "You have successfully changed the email associated with your account." 31 | } 32 | -------------------------------------------------------------------------------- /api/config/locales/es.json: -------------------------------------------------------------------------------- 1 | { 2 | "hi": "Hola %s,", 3 | "link-duration": "El enlace tiene una duración de 24 horas", 4 | "team": "El equipo de Modulr", 5 | 6 | "signup.subject": "Confirma tu dirección de correo electrónico - Modulr", 7 | "signup.paragraph": "¡Te damos la bienvenida a Modulr! Antes de empezar, debes confirmar tu dirección de correo electrónico.", 8 | "signup.btn": "Confirmar correo", 9 | 10 | "welcome.subject": "Bienvenido a Modulr", 11 | "welcome.paragraph": "¡Te damos la bienvenida a Modulr! Haz completado tu registro y tu cuenta se encuentra activa.", 12 | 13 | "password-reset.subject": "Restablece tu contraseña - Modulr", 14 | "password-reset.paragraph": "Hemos recibido una solicitud para restablecer la contraseña de tu cuenta.", 15 | "password-reset.paragraph2": "Si tu solicitaste restablecer la contraseña para esta cuenta %s, haz clic en el botón de abajo. Si tu no hiciste este pedido, por favor, ignora este mensaje.", 16 | "password-reset.btn": "Restablecer contraseña", 17 | 18 | "password-update.subject": "Contraseña actualizada - Modulr", 19 | "password-update.paragraph": "Haz cambiado correctamente la contraseña.", 20 | 21 | "send-user-data.subject": "Datos de tu cuenta - Modulr", 22 | "send-user-data.paragraph": "Estos son los datos de tu cuenta en Modulr, es necesario que establezcas tu contraseña para poder acceder.", 23 | 24 | "email-change.subject": "Cambia tu correo electrónico - Modulr", 25 | "email-change.paragraph": "Hemos recibido una solicitud para cambiar el correo electrónico de tu cuenta.", 26 | "email-change.paragraph2": "Si tu solicitaste cambiar el correo electrónico asociado a esta cuenta %s, debes confirmar tu dirección de correo electrónico. Si tu no hiciste este pedido, por favor, ignora este mensaje.", 27 | "email-change.btn": "Confirmar correo", 28 | 29 | "email-change-update.subject": "Correo electrónico actualizado - Modulr", 30 | "email-change-update.paragraph": "Haz cambiado correctamente el correo electrónico asociado a tu cuenta." 31 | } 32 | -------------------------------------------------------------------------------- /api/config/locales/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "Welcome": "Bienvenue", 3 | "A brand new app.": "Une toute nouvelle application." 4 | } 5 | -------------------------------------------------------------------------------- /api/config/log.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Built-in Log Configuration 3 | * (sails.config.log) 4 | * 5 | * Configure the log level for your app, as well as the transport 6 | * (Underneath the covers, Sails uses Winston for logging, which 7 | * allows for some pretty neat custom transports/adapters for log messages) 8 | * 9 | * For more information on the Sails logger, check out: 10 | * http://sailsjs.org/#/documentation/concepts/Logging 11 | */ 12 | 13 | module.exports.log = { 14 | 15 | /*************************************************************************** 16 | * * 17 | * Valid `level` configs: i.e. the minimum log level to capture with * 18 | * sails.log.*() * 19 | * * 20 | * The order of precedence for log levels from lowest to highest is: * 21 | * silly, verbose, info, debug, warn, error * 22 | * * 23 | * You may also set the level to "silent" to suppress all logs. * 24 | * * 25 | ***************************************************************************/ 26 | 27 | // level: 'info' 28 | 29 | }; 30 | -------------------------------------------------------------------------------- /api/config/models.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Default model configuration 3 | * (sails.config.models) 4 | * 5 | * Unless you override them, the following properties will be included 6 | * in each of your models. 7 | * 8 | * For more info on Sails models, see: 9 | * http://sailsjs.org/#/documentation/concepts/ORM 10 | */ 11 | 12 | module.exports.models = { 13 | 14 | /*************************************************************************** 15 | * * 16 | * Your app's default connection. i.e. the name of one of your app's * 17 | * connections (see `config/connections.js`) * 18 | * * 19 | ***************************************************************************/ 20 | // connection: 'localDiskDb', 21 | 22 | /*************************************************************************** 23 | * * 24 | * How and whether Sails will attempt to automatically rebuild the * 25 | * tables/collections/etc. in your schema. * 26 | * * 27 | * See http://sailsjs.org/#/documentation/concepts/ORM/model-settings.html * 28 | * * 29 | ***************************************************************************/ 30 | // migrate: 'alter' 31 | 32 | }; 33 | -------------------------------------------------------------------------------- /api/config/passport.js: -------------------------------------------------------------------------------- 1 | var passport = require('passport'); 2 | var LocalStrategy = require('passport-local').Strategy; 3 | 4 | passport.serializeUser(function(user, done) { 5 | done(null, user.id); 6 | }); 7 | 8 | passport.deserializeUser(function(id, done) { 9 | User.findOne({ id: id } , function (err, user) { 10 | done(err, user); 11 | }); 12 | }); 13 | 14 | passport.use(new LocalStrategy({ 15 | usernameField: 'emailOrUsername', 16 | passwordField: 'password' 17 | },function(username, password, done) { 18 | // Se busca el userName o el email 19 | sails.models.user.findOne({ 20 | or : [{email: username}, {username: username}], 21 | active: true, deletedAt: null 22 | }).populate('role').exec(function (err, user) { 23 | if (err) return done(err); 24 | 25 | // Si el userName o el email no existen o la cuenta esta desactivada 26 | if (!user) { 27 | return done(null, false, { status: 404 }); 28 | } 29 | 30 | // Se comparan los passwords 31 | EncryptService.compare(password, user.password, function (err, valid) { 32 | // Si los passwords no son iguales 33 | if(!valid) return done(null, false, { status: 400 }); 34 | 35 | return done(null, user, { status: 200 }); 36 | }); 37 | 38 | }); 39 | } 40 | )); 41 | -------------------------------------------------------------------------------- /api/config/policies.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Policy Mappings 3 | * (sails.config.policies) 4 | * 5 | * Policies are simple functions which run **before** your controllers. 6 | * You can apply one or more policies to a given controller, or protect 7 | * its actions individually. 8 | * 9 | * Any policy file (e.g. `api/policies/authenticated.js`) can be accessed 10 | * below by its filename, minus the extension, (e.g. "authenticated") 11 | * 12 | * For more information on how policies work, see: 13 | * http://sailsjs.org/#/documentation/concepts/Policies 14 | * 15 | * For more information on configuring policies, check out: 16 | * http://sailsjs.org/#/documentation/reference/sails.config/sails.config.policies.html 17 | */ 18 | 19 | 20 | module.exports.policies = { 21 | 22 | /*************************************************************************** 23 | * * 24 | * Default policy for all controllers and actions (`true` allows public * 25 | * access) * 26 | * * 27 | ***************************************************************************/ 28 | 29 | // '*': true, 30 | '*': 'isAuthenticated', 31 | 32 | Language: { 33 | '*': true 34 | }, 35 | 36 | AuthController: { 37 | login: true, 38 | signup: true, 39 | confirmEmail: true, 40 | findAccount: true, 41 | createPasswordReset: true, 42 | findPasswordReset: true, 43 | passwordReset: true 44 | } 45 | 46 | /*************************************************************************** 47 | * * 48 | * Here's an example of mapping some policies to run before a controller * 49 | * and its actions * 50 | * * 51 | ***************************************************************************/ 52 | // RabbitController: { 53 | 54 | // Apply the `false` policy as the default for all of RabbitController's actions 55 | // (`false` prevents all access, which ensures that nothing bad happens to our rabbits) 56 | // '*': false, 57 | 58 | // For the action `nurture`, apply the 'isRabbitMother' policy 59 | // (this overrides `false` above) 60 | // nurture : 'isRabbitMother', 61 | 62 | // Apply the `isNiceToAnimals` AND `hasRabbitFood` policies 63 | // before letting any users feed our rabbits 64 | // feed : ['isNiceToAnimals', 'hasRabbitFood'] 65 | // } 66 | }; 67 | -------------------------------------------------------------------------------- /api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "modulr-api", 3 | "scripts": { 4 | "test": "echo \"Error: no test specified\" && exit 1", 5 | "start": "sails lift" 6 | }, 7 | "dependencies": { 8 | "bcrypt": "^0.8.5", 9 | "connect-mongo": "^0.8.2", 10 | "ejs": "~0.8.4", 11 | "glob": "^7.0.0", 12 | "grunt": "0.4.2", 13 | "grunt-contrib-clean": "~0.5.0", 14 | "grunt-contrib-coffee": "~0.10.1", 15 | "grunt-contrib-concat": "~0.3.0", 16 | "grunt-contrib-copy": "~0.5.0", 17 | "grunt-contrib-cssmin": "~0.9.0", 18 | "grunt-contrib-jst": "~0.6.0", 19 | "grunt-contrib-less": "0.11.1", 20 | "grunt-contrib-uglify": "~0.4.0", 21 | "grunt-contrib-watch": "~0.5.3", 22 | "grunt-sails-linker": "~0.9.5", 23 | "grunt-sync": "~0.0.4", 24 | "include-all": "~0.1.3", 25 | "jsonwebtoken": "^5.0.5", 26 | "lodash": "^3.10.1", 27 | "lwip": "0.0.8", 28 | "moment": "^2.10.6", 29 | "passport": "^0.3.0", 30 | "passport-local": "^1.0.0", 31 | "rand-token": "^0.2.1", 32 | "rc": "~0.5.0", 33 | "sails": "~0.11.0", 34 | "sails-disk": "~0.10.0", 35 | "sails-hook-apianalytics": "^1.0.0", 36 | "sails-hook-email": "^0.12.0", 37 | "sails-mongo": "^0.11.1", 38 | "skipper-s3": "^0.5.6", 39 | "ua-parser": "^0.3.5" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /api/seeds/development/company.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "company" : "Modulr" 4 | }, 5 | { 6 | "company" : "Other1" 7 | }, 8 | { 9 | "company" : "Other2" 10 | }, 11 | { 12 | "company" : "Other3" 13 | }, 14 | { 15 | "company" : "Other4" 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /api/seeds/development/contacttype.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type" : "PHONE" 4 | }, 5 | { 6 | "type" : "EMAIL" 7 | } 8 | ] 9 | -------------------------------------------------------------------------------- /api/seeds/development/department.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "department" : "Systems" 4 | }, 5 | { 6 | "department" : "Admin" 7 | } 8 | ] 9 | -------------------------------------------------------------------------------- /api/seeds/development/folder.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id" : "5798c4e2bb2c73dcba6d9906", 4 | "name" : "Home", 5 | "url" : "files" 6 | } 7 | ] 8 | -------------------------------------------------------------------------------- /api/seeds/development/gender.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "gender" : "MALE" 4 | }, 5 | { 6 | "gender" : "FEMALE" 7 | } 8 | ] 9 | -------------------------------------------------------------------------------- /api/seeds/development/hello.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "greeting" : "Hola mundo" 4 | } 5 | ] 6 | -------------------------------------------------------------------------------- /api/seeds/development/job.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "job" : "Developer" 4 | }, 5 | { 6 | "job" : "Design" 7 | } 8 | ] 9 | -------------------------------------------------------------------------------- /api/seeds/development/language.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "language" : "ENGLISH", 4 | "lang" : "en" 5 | }, 6 | { 7 | "language" : "SPANISH", 8 | "lang" : "es" 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /api/seeds/development/module.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "title": "dashboard", 4 | "icon": "fa-home", 5 | "state": "dashboard", 6 | "url": "/dashboard", 7 | "order": 1, 8 | "active": true, 9 | "lock": true 10 | }, 11 | { 12 | "title": "files", 13 | "icon": "fa-folder-o", 14 | "state": "files", 15 | "url": "/files", 16 | "order": 2, 17 | "active": true 18 | }, 19 | { 20 | "title": "log", 21 | "icon": "fa-exchange", 22 | "state": "logLogin", 23 | "url": "/log/login", 24 | "order": 3, 25 | "active": true, 26 | "lock": true, 27 | "submodules": [ 28 | { 29 | "title": "login", 30 | "state": "logLogin" 31 | }, 32 | { 33 | "title": "request", 34 | "state": "logRequest" 35 | } 36 | ] 37 | }, 38 | { 39 | "title": "users", 40 | "icon": "fa-users", 41 | "state": "users", 42 | "url": "/users", 43 | "order": 4, 44 | "active": true, 45 | "lock": true, 46 | "submodules": [ 47 | { 48 | "title": "users", 49 | "state": "users" 50 | }, 51 | { 52 | "title": "roles", 53 | "state": "roles" 54 | }, 55 | { 56 | "title": "access", 57 | "state": "access" 58 | } 59 | ] 60 | }, 61 | { 62 | "title": "profile", 63 | "icon": "fa-user", 64 | "state": "profile", 65 | "url": "/profile", 66 | "order": 6, 67 | "active": true, 68 | "lock": true, 69 | "submodules": [ 70 | { 71 | "title": "information", 72 | "state": "information" 73 | }, 74 | { 75 | "title": "work", 76 | "state": "work" 77 | }, 78 | { 79 | "title": "settings", 80 | "state": "settings" 81 | }, 82 | { 83 | "title": "permissions", 84 | "state": "permissions" 85 | } 86 | ] 87 | }, 88 | { 89 | "title": "settings", 90 | "icon": "fa-cogs", 91 | "state": "modules", 92 | "url": "/settings/modules", 93 | "order": 5, 94 | "active": true, 95 | "lock": true, 96 | "submodules": [ 97 | { 98 | "title": "modules", 99 | "state": "modules" 100 | } 101 | ] 102 | } 103 | ] 104 | -------------------------------------------------------------------------------- /api/seeds/development/profile.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id" : "56b607d6a92a603f89e0119c", 4 | "user" : "56610cabc13eee247069f9ab" 5 | }, 6 | { 7 | "id" : "5785267a20ff93001a7b96e0", 8 | "user" : "5785267a20ff93001a7b96df" 9 | }, 10 | { 11 | "id" : "5785269320ff93001a7b96e3", 12 | "user" : "5785269320ff93001a7b96e2" 13 | } 14 | ] 15 | -------------------------------------------------------------------------------- /api/seeds/development/relation.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "relation" : "father" 4 | }, 5 | { 6 | "relation" : "mother" 7 | }, 8 | { 9 | "relation" : "son" 10 | }, 11 | { 12 | "relation" : "daughter" 13 | }, 14 | { 15 | "relation" : "brother" 16 | }, 17 | { 18 | "relation" : "sister" 19 | }, 20 | { 21 | "relation" : "wife" 22 | }, 23 | { 24 | "relation" : "husband" 25 | } 26 | ] 27 | -------------------------------------------------------------------------------- /api/seeds/development/relationship.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "relationship" : "SINGLE" 4 | }, 5 | { 6 | "relationship" : "MARRIED" 7 | }, 8 | { 9 | "relationship" : "COMMITTED" 10 | }, 11 | { 12 | "relationship" : "SEPARATE" 13 | }, 14 | { 15 | "relationship" : "DIVORCED" 16 | }, 17 | { 18 | "relationship" : "WIDOWER" 19 | } 20 | ] 21 | -------------------------------------------------------------------------------- /api/seeds/development/user.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id" : "56610cabc13eee247069f9ab", 4 | "email" : "admin@modulr.io", 5 | "username" : "admin", 6 | "password" : "Admin123", 7 | "lang" : "en", 8 | "language" : "ENGLISH", 9 | "photo" : "avatar.jpg", 10 | "logged" : false, 11 | "active" : true, 12 | "lock" : true, 13 | "profile" : "56b607d6a92a603f89e0119c", 14 | "role" : "56f964859093205f3a5fedb6" 15 | }, 16 | { 17 | "id" : "5785267a20ff93001a7b96df", 18 | "email" : "user@modulr.io", 19 | "username" : "user", 20 | "password" : "User123", 21 | "lang" : "en", 22 | "language" : "ENGLISH", 23 | "photo" : "avatar.jpg", 24 | "logged" : false, 25 | "active" : true, 26 | "profile" : "5785267a20ff93001a7b96e0", 27 | "role" : "56f964859093205f3a5fedb7" 28 | }, 29 | { 30 | "id" : "5785269320ff93001a7b96e2", 31 | "email" : "guest@modulr.io", 32 | "username" : "guest", 33 | "password" : "Guest123", 34 | "lang" : "en", 35 | "language" : "ENGLISH", 36 | "photo" : "avatar.jpg", 37 | "logged" : false, 38 | "active" : true, 39 | "profile" : "5785269320ff93001a7b96e3", 40 | "role" : "56f964859093205f3a5fedb8" 41 | } 42 | ] 43 | -------------------------------------------------------------------------------- /api/views/transactional-email-templates-master/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Mailgun 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /api/views/transactional-email-templates-master/README.md: -------------------------------------------------------------------------------- 1 | # Responsive transactional HTML email templates 2 | 3 | Transactional HTML emails often get neglected. **Styling HTML email is painful**. Tables, inline CSS, unsupported CSS, desktop clients, web clients, mobile clients, various devices, various providers. 4 | 5 | We’ve tried to remove some of the pain for you and open-sourced a collection of common templates for transactional email. 6 | 7 |

8 | 9 | * [Action email](http://mailgun.github.io/transactional-email-templates/action.html) 10 | * [Email alert](http://mailgun.github.io/transactional-email-templates/alert.html) 11 | * [Billing email](http://mailgun.github.io/transactional-email-templates/billing.html) 12 | 13 | Each template is **responsive** and each has been **tested** in all the **popular email clients**. 14 | 15 | ## How to use 16 | 17 | * Use these email templates for your transactional emails 18 | * Use them as is or think of them as boilerplates for more detailed emails 19 | * Ensure you [inline the CSS](#inline-the-css) before sending the email out 20 | 21 | ## What are transactional emails? 22 | 23 | Typically any email that is triggered by or sent automatically from your application. 24 | 25 | * Welcome emails 26 | * Actionable emails 27 | * Password resets 28 | * Receipts 29 | * Monthly invoices 30 | * Support requests 31 | * App error alerts 32 | * Reminders 33 | * etc. 34 | 35 | ## Inline the CSS 36 | 37 | Before sending HTML emails **you should inline your CSS**. 38 | 39 | We recommend using [Premailer](http://premailer.dialect.ca/) to accomplish this. 40 | 41 | Our repo contains both the original templates with a separate CSS stylesheet, as well as templates with CSS already inlined for you to preview. See the `/templates/inlined` folder. 42 | 43 | ## Tested and verified 44 | 45 | We’ve tested these email templates across all the major desktop, web and mobile clients, using Litmus. [See the test results.](https://litmus.com/pub/3a573b5/screenshots) 46 | 47 | 48 | 49 | ## Email design workflow with Grunt 50 | 51 | You also might be interested in this [Grunt task](https://github.com/leemunroe/grunt-email-design) for compiling and testing html emails. We used this to help design and test our transactional emails. 52 | -------------------------------------------------------------------------------- /api/views/transactional-email-templates-master/templates/action.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Actionable emails e.g. reset password 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 54 | 55 | 56 |
16 |
17 | 18 | 19 | 44 | 45 |
20 | 21 | 22 | 23 | 26 | 27 | 28 | 31 | 32 | 33 | 36 | 37 | 38 | 41 | 42 |
24 | Please confirm your email address by clicking the link below. 25 |
29 | We may need to send you critical information about our service and it is important that we have an accurate email address. 30 |
34 | 35 |
39 | — The Mailgunners 40 |
43 |
46 |
53 |
57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /api/views/transactional-email-templates-master/templates/alert.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Alerts e.g. approaching your limit 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 58 | 59 | 60 |
16 |
17 | 18 | 19 | 22 | 23 | 24 | 48 | 49 |
20 | Warning: You're approaching your limit. Please upgrade. 21 |
25 | 26 | 27 | 30 | 31 | 32 | 35 | 36 | 37 | 40 | 41 | 42 | 45 | 46 |
28 | You have 1 free report remaining. 29 |
33 | Add your credit card now to upgrade your account to a premium plan to ensure you don't miss out on any reports. 34 |
38 | Upgrade my account 39 |
43 | Thanks for choosing Acme Inc. 44 |
47 |
50 |
57 |
61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /app/app/app.config.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('config',[]) 6 | .constant( 7 | 'config', { 8 | 'urlAPI': window.io.sails.url, 9 | 'storageUrl': window.storageUrl, 10 | } 11 | ) 12 | .config(['$stateProvider', '$httpProvider', '$sailsSocketProvider', '$locationProvider', '$urlRouterProvider', '$translateProvider', function($stateProvider, $httpProvider, $sailsSocketProvider, $locationProvider, $urlRouterProvider, $translateProvider){ 13 | 14 | /* 15 | |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 16 | | Interceptor 17 | |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 18 | */ 19 | $httpProvider.interceptors.push('interceptorService'); 20 | // Iterate $httpProvider interceptors and add those to $sailsSocketProvider 21 | angular.forEach($httpProvider.interceptors, function iterator(interceptor) { 22 | $sailsSocketProvider.interceptors.push(interceptor); 23 | }); 24 | 25 | $urlRouterProvider.deferIntercept(); 26 | /* 27 | |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 28 | | Translate 29 | |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 30 | */ 31 | $translateProvider.useStaticFilesLoader({ 32 | prefix: 'locales/', 33 | suffix: '.min.json' 34 | }); 35 | $translateProvider.preferredLanguage('en'); 36 | 37 | $translateProvider.useSanitizeValueStrategy('escaped'); 38 | 39 | $translateProvider.useLocalStorage(); 40 | 41 | /* 42 | |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 43 | | HTML5 History API 44 | |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 45 | */ 46 | $locationProvider.html5Mode({enabled: true}); 47 | // $locationProvider 48 | // .html5Mode({ 49 | // enabled: true, 50 | // requireBase: false 51 | // }) 52 | // .hashPrefix('!'); 53 | 54 | }]); 55 | 56 | }()); 57 | -------------------------------------------------------------------------------- /app/app/helpers/comments/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modulr/sails-angularjs/c99442dc9fa2402d71832fd44b793c009fdbebd9/app/app/helpers/comments/.DS_Store -------------------------------------------------------------------------------- /app/app/helpers/comments/comments.html: -------------------------------------------------------------------------------- 1 |
2 |
    3 |
  • 4 |
    5 | 6 |
    7 |
    8 | {{item.user.fullName}} 9 |

    {{item.comment}}

    10 |
    11 |
  • 12 |
13 |
14 |
15 | 16 | 17 | 18 | 19 |
20 |
21 | 22 |
23 |
24 |
25 | -------------------------------------------------------------------------------- /app/app/helpers/events/enter.directive.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('helpers') 6 | .directive('enter', enter); 7 | 8 | function enter($timeout) { 9 | 10 | var KEY = 13; 11 | 12 | return function (scope, elem, attrs) { 13 | elem.bind('keydown', function (event) { 14 | if (event.keyCode === KEY) { 15 | scope.$apply(attrs.enter); 16 | } 17 | }); 18 | 19 | scope.$on('$destroy', function () { 20 | elem.unbind('keydown'); 21 | }); 22 | }; 23 | } 24 | 25 | })(); 26 | -------------------------------------------------------------------------------- /app/app/helpers/events/escape.directive.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('helpers') 6 | .directive('escape', escape); 7 | 8 | function escape($timeout) { 9 | 10 | var KEY = 27; 11 | 12 | return function (scope, elem, attrs) { 13 | elem.bind('keydown', function (event) { 14 | if (event.keyCode === KEY) { 15 | scope.$apply(attrs.escape); 16 | } 17 | }); 18 | 19 | scope.$on('$destroy', function () { 20 | elem.unbind('keydown'); 21 | }); 22 | }; 23 | } 24 | 25 | })(); 26 | -------------------------------------------------------------------------------- /app/app/helpers/events/focus.directive.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('helpers') 6 | .directive('focus', focus); 7 | 8 | function focus($timeout) { 9 | 10 | return function (scope, elem, attrs) { 11 | scope.$watch(attrs.focus, function (newVal) { 12 | if (newVal) { 13 | $timeout(function () { 14 | elem[0].focus(); 15 | }, 0, false); 16 | } 17 | }); 18 | }; 19 | } 20 | 21 | })(); 22 | -------------------------------------------------------------------------------- /app/app/helpers/events/scrollToBottom.directive.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('helpers') 6 | .directive('scrollToBottom', [function(){ 7 | 8 | function linker(scope, element, attrs){ 9 | 10 | if (scope.$last){ 11 | var parent = element.parent(); 12 | parent.animate({scrollTop: parent[0].scrollHeight}, 'slow'); 13 | } 14 | 15 | } 16 | 17 | return { 18 | restrict: 'A', 19 | link: linker 20 | }; 21 | 22 | }]); 23 | 24 | })(); 25 | -------------------------------------------------------------------------------- /app/app/helpers/events/scrollToTop.directive.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('helpers') 6 | .directive('scrollToTop', [function(){ 7 | 8 | function linker(scope, element, attrs){ 9 | 10 | if (scope.$first){ 11 | var parent = element.parent(); 12 | parent.animate({scrollTop: 0}, 'slow'); 13 | } 14 | 15 | } 16 | 17 | return { 18 | restrict: 'A', 19 | link: linker 20 | }; 21 | 22 | }]); 23 | 24 | })(); 25 | -------------------------------------------------------------------------------- /app/app/helpers/files/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modulr/sails-angularjs/c99442dc9fa2402d71832fd44b793c009fdbebd9/app/app/helpers/files/.DS_Store -------------------------------------------------------------------------------- /app/app/helpers/files/grid.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 19 | 20 | 21 | 22 | {{item.name}} 23 | 24 | 25 |
26 |

{{item.name | limitTo : 12}}...

27 |

28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 |

39 |
40 | 41 |
42 |
43 |
44 |
45 | -------------------------------------------------------------------------------- /app/app/helpers/helpers.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | angular.module('helpers', [ 4 | 5 | ]); 6 | 7 | }()); 8 | -------------------------------------------------------------------------------- /app/app/helpers/loading-panel.directive.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('helpers') 6 | .directive('loading', loading); 7 | 8 | function loading() { 9 | return { 10 | restrict: 'A', 11 | link: function (scope, element, attrs) { 12 | 13 | var loadingSpinner = '
Loading...
'; 14 | 15 | scope.$watch(attrs.loading, function (val) { 16 | if(val) { 17 | element.parent().css('position', 'relative'); 18 | element.append(angular.element(loadingSpinner)); 19 | } else { 20 | element.parent().css('position', 'initial'); 21 | element.children('div.loading-panel').remove(); 22 | } 23 | }); 24 | 25 | } 26 | }; 27 | } 28 | })(); 29 | -------------------------------------------------------------------------------- /app/app/helpers/panel/panel.directive.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('helpers') 6 | .directive('panel', panel); 7 | 8 | function panel() { 9 | return function($scope, elem, attrs) { 10 | $(elem).smkPanel(); 11 | }; 12 | } 13 | 14 | })(); 15 | -------------------------------------------------------------------------------- /app/app/helpers/restFul/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modulr/sails-angularjs/c99442dc9fa2402d71832fd44b793c009fdbebd9/app/app/helpers/restFul/.DS_Store -------------------------------------------------------------------------------- /app/app/helpers/restFul/restFul.service.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('helpers') 6 | .factory('restFulService', ['$http', '$q', 'config', function($http, $q, config){ 7 | 8 | return{ 9 | get:function(model, params){ 10 | var deferred = $q.defer(); 11 | 12 | $http.get(config.urlAPI +'/'+ model, params) 13 | .success(function(response){ 14 | deferred.resolve(response); 15 | }) 16 | .error(function(error, status){ 17 | var err = { 18 | error: error, 19 | status: status 20 | }; 21 | deferred.reject(err); 22 | }); 23 | 24 | return deferred.promise; 25 | }, 26 | post:function(model, params){ 27 | var deferred = $q.defer(); 28 | 29 | $http.post(config.urlAPI +'/'+ model, params) 30 | .success(function(response){ 31 | deferred.resolve(response); 32 | }) 33 | .error(function(error, status){ 34 | var err = { 35 | error: error, 36 | status: status 37 | }; 38 | deferred.reject(err); 39 | }); 40 | 41 | return deferred.promise; 42 | }, 43 | put:function(model, params){ 44 | var deferred = $q.defer(); 45 | 46 | $http.put(config.urlAPI +'/'+ model, params) 47 | .success(function(response){ 48 | deferred.resolve(response); 49 | }) 50 | .error(function(error, status){ 51 | var err = { 52 | error: error, 53 | status: status 54 | }; 55 | deferred.reject(err); 56 | }); 57 | 58 | return deferred.promise; 59 | }, 60 | delete:function(model, params){ 61 | var deferred = $q.defer(); 62 | 63 | $http.delete(config.urlAPI +'/'+ model, params) 64 | .success(function(response){ 65 | deferred.resolve(response); 66 | }) 67 | .error(function(error, status){ 68 | var err = { 69 | error: error, 70 | status: status 71 | }; 72 | deferred.reject(err); 73 | }); 74 | 75 | return deferred.promise; 76 | } 77 | }; 78 | 79 | }]); 80 | 81 | }()); 82 | -------------------------------------------------------------------------------- /app/app/helpers/sanitize/sanitize.service.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('helpers') 6 | .factory('sanitizeService', sanitizeService); 7 | 8 | sanitizeService.$inject = ['$sanitize']; 9 | function sanitizeService($sanitize){ 10 | 11 | return{ 12 | array:function(array){ 13 | var data = {}; 14 | $.each(array, function(key, val) { 15 | data[key] = $sanitize(val); 16 | }); 17 | return data; 18 | }, 19 | value:function(value){ 20 | return $sanitize(value); 21 | } 22 | }; 23 | 24 | } 25 | 26 | }()); 27 | -------------------------------------------------------------------------------- /app/app/helpers/tooltip.directive.js: -------------------------------------------------------------------------------- 1 | /** 2 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3 | * UsersCtrl 4 | * 5 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 6 | */ 7 | (function(){ 8 | 'use strict'; 9 | 10 | angular 11 | .module('helpers') 12 | .directive('tooltip', tooltip); 13 | 14 | function tooltip() { 15 | return { 16 | restrict: 'A', 17 | link: function (scope, elem, attrs) { 18 | $(elem).tooltip({ 19 | container: 'body', 20 | title : attrs.title, 21 | placement : attrs.placement, 22 | html: true 23 | }); 24 | } 25 | }; 26 | } 27 | 28 | })(); 29 | -------------------------------------------------------------------------------- /app/app/images/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modulr/sails-angularjs/c99442dc9fa2402d71832fd44b793c009fdbebd9/app/app/images/avatar.jpg -------------------------------------------------------------------------------- /app/app/images/icon-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 8 | 10 | 12 | 14 | 16 | 18 | 20 | 21 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/app/images/modulr-orange.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 8 | 11 | 14 | 16 | 17 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/app/images/modulr-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 8 | 11 | 13 | 15 | 16 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/app/modules/auth/auth.module.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('auth', []) 6 | .config(['$stateProvider', function($stateProvider){ 7 | 8 | $stateProvider 9 | .state('login', { 10 | parent: 'layoutAuth', 11 | url: '/', 12 | templateUrl: 'app/modules/auth/login.html', 13 | controller: 'LoginCtrl' 14 | }) 15 | .state('signup', { 16 | parent: 'layoutAuth', 17 | url: '/signup', 18 | templateUrl: 'app/modules/auth/signup.html', 19 | controller: 'SignupCtrl' 20 | }) 21 | .state('confirmEmail', { 22 | parent: 'layoutAuth', 23 | url: '/confirm_email/:token/:tokenId/:userId', 24 | templateUrl: 'app/modules/auth/confirmEmail.html', 25 | controller: 'ConfirmEmailCtrl' 26 | }) 27 | .state('beginPasswordReset', { 28 | parent: 'layoutAuth', 29 | url: '/begin_password_reset', 30 | templateUrl: 'app/modules/auth/beginPasswordReset.html', 31 | controller: 'BeginPasswordResetCtrl' 32 | }) 33 | .state('sendPasswordReset', { 34 | parent: 'layoutAuth', 35 | url: '/send_password_reset', 36 | templateUrl: 'app/modules/auth/sendPasswordReset.html', 37 | controller: 'SendPasswordResetCtrl' 38 | }) 39 | .state('passwordReset', { 40 | parent: 'layoutAuth', 41 | url: '/password_reset/:token/:tokenId/:userId', 42 | templateUrl: 'app/modules/auth/passwordReset.html', 43 | controller: 'PasswordResetCtrl' 44 | }); 45 | 46 | }]); 47 | 48 | }()); 49 | -------------------------------------------------------------------------------- /app/app/modules/auth/auth.service.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('auth') 6 | .factory('authService', [function(){ 7 | 8 | return{ 9 | 10 | isAuthenticated: function(){ 11 | 12 | if (localStorage.getItem('token')) { 13 | return true; 14 | } 15 | return false; 16 | 17 | } 18 | 19 | }; 20 | 21 | }]); 22 | 23 | }()); 24 | -------------------------------------------------------------------------------- /app/app/modules/auth/beginPasswordReset.controller.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('auth') 6 | .controller('BeginPasswordResetCtrl', ['$rootScope', '$scope', '$state', '$translate', 'sanitizeService', 'restFulService', function($rootScope, $scope, $state, $translate, sanitizeService, restFulService){ 7 | 8 | $scope.formBeginPasswordReset = {}; 9 | $rootScope.account = undefined; 10 | 11 | $scope.findAccount = function(event){ 12 | 13 | $('#formBeginPasswordReset').removeClass('animated shake'); 14 | 15 | if ($('#formBeginPasswordReset').smkValidate()) { 16 | 17 | var btn = $(event.target); 18 | btn.button('loading'); 19 | 20 | var data = sanitizeService.array($scope.formBeginPasswordReset); 21 | 22 | restFulService.get('auth/findAccount/' + data.emailOrUsername) 23 | .then(function(response){ 24 | 25 | $rootScope.account = response; 26 | $rootScope.account.email = $.smkHideEmail(response.email); 27 | $state.go('sendPasswordReset'); 28 | 29 | }) 30 | .catch(function(err){ 31 | $('#formBeginPasswordReset').addClass('animated shake'); 32 | 33 | $translate('BEGIN-PASSWORD-RESET.MESSAGES.ERROR').then(function (translate) { 34 | $.smkAlert({ 35 | text: translate, 36 | type: 'warning' 37 | }); 38 | }); 39 | }) 40 | .finally(function(){ 41 | btn.button('reset'); 42 | }); 43 | 44 | } 45 | }; 46 | 47 | }]); 48 | 49 | }()); 50 | -------------------------------------------------------------------------------- /app/app/modules/auth/beginPasswordReset.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |

{{'BEGIN-PASSWORD-RESET.HEADLINE' | translate}}

6 |

{{'BEGIN-PASSWORD-RESET.PARAGRAPH' | translate}}

7 | 8 |
9 |
10 | 11 | 12 | 13 | 15 |
16 |
17 | 18 | 21 | 22 | 23 | {{'SIGNUP.SIGNUP' | translate}} 24 | 25 | 26 | 27 | {{'LOGIN.LOGIN' | translate}} 28 | 29 | 30 |
31 | 32 |
33 | -------------------------------------------------------------------------------- /app/app/modules/auth/confirmEmail.controller.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('auth') 6 | .controller('ConfirmEmailCtrl', ['$scope', '$state', '$location', 'restFulService', function($scope, $state, $location, restFulService){ 7 | 8 | $scope.show = { 9 | message: false 10 | }; 11 | 12 | // Si falta alguno de los 3 parametros 13 | if ($state.params.token === '' || $state.params.tokenId === '' || $state.params.userId === '') 14 | $location.path('error'); 15 | 16 | // Se valida que el token exista en la DB 17 | restFulService.get('auth/confirmEmail/' + $state.params.token +'/'+ $state.params.tokenId +'/'+ $state.params.userId) 18 | .then(function(response){ 19 | $scope.show.message = true; 20 | }) 21 | .catch(function(err){ 22 | if (err.status != 302) { 23 | $location.path('error/' + err.status); 24 | } else { 25 | $location.path('/'); 26 | } 27 | //$state.go('error', { errorId: err.status }); 28 | }); 29 | 30 | }]); 31 | 32 | }()); 33 | -------------------------------------------------------------------------------- /app/app/modules/auth/confirmEmail.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |
6 | 7 |

{{'CONFIRM-EMAIL.MESSAGES.SUCCESS.HEADLINE' | translate}}

8 |

{{'CONFIRM-EMAIL.MESSAGES.SUCCESS.PARAGRAPH' | translate}}

9 | 10 | {{'LOGIN.LOGIN' | translate}} 11 | 12 |
13 | 14 |
15 | 16 |
17 | -------------------------------------------------------------------------------- /app/app/modules/auth/interceptor.service.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('auth') 6 | .factory('interceptorService', ['$rootScope', '$q', '$injector', function($rootScope, $q, $injector){ 7 | 8 | return { 9 | 10 | request: function(config) { 11 | // Si el request es de tipo text/html se muestra el progressbar 12 | //if (config.headers.Accept == "text/html") { 13 | $rootScope.$broadcast( 14 | $.smkProgressBar({ 15 | status:'start', 16 | bgColor: '', 17 | barColor: '#fff' 18 | //content:'

Loading...

' 19 | }) 20 | ); 21 | //} 22 | // Se obtiene el token de localStorage 23 | var token = localStorage.getItem('token'); 24 | // Si existe el token se envia por el header 25 | if (token) { 26 | config.headers.authorization = token; 27 | } 28 | return config; 29 | }, 30 | 31 | requestError: function(rejection){ 32 | console.log(rejection); 33 | return $q.reject(rejection); 34 | }, 35 | 36 | response: function(response) { 37 | //if (response.config.headers.Accept == "text/html") { 38 | $rootScope.$broadcast( 39 | $.smkProgressBar({status:'end'}) 40 | ); 41 | //} 42 | return response; 43 | }, 44 | 45 | responseError: function(rejection) { 46 | console.log(rejection); 47 | // Si no esta autenticado o no se tiene acceso se remueve el token y se envia al login 48 | if (rejection.status === 401 || rejection.status === 403) { 49 | localStorage.removeItem('token'); 50 | $injector.get('$state').go('login'); 51 | }else{ 52 | var message = $injector.get('errorService').getStatusCodeText(rejection.status); 53 | if (message) { 54 | console.log(message); 55 | } 56 | } 57 | 58 | $rootScope.$broadcast( 59 | $.smkProgressBar({status:'end'}) 60 | ); 61 | 62 | return $q.reject(rejection); 63 | } 64 | 65 | }; 66 | 67 | }]); 68 | 69 | }()); 70 | -------------------------------------------------------------------------------- /app/app/modules/auth/login.controller.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('auth') 6 | .controller('LoginCtrl', ['$rootScope', '$scope', '$state', '$translate', 'sanitizeService', 'restFulService', function($rootScope, $scope, $state, $translate, sanitizeService, restFulService){ 7 | 8 | $scope.formLogin = { 9 | // emailOrUsername: 'admin', 10 | // password: 'Admin123', 11 | // rememberMe: false 12 | }; 13 | 14 | $scope.login = function(event){ 15 | 16 | $('#formLogin').removeClass('animated shake'); 17 | 18 | if ($('#formLogin').smkValidate()) { 19 | 20 | var btn = $(event.target); 21 | btn.button('loading'); 22 | 23 | var data = sanitizeService.array($scope.formLogin); 24 | 25 | restFulService.post('auth/login', data) 26 | .then(function(response) { 27 | 28 | $rootScope.user = response.user; 29 | 30 | localStorage.setItem('token', response.token); 31 | $translate.use(response.user.lang); 32 | 33 | $state.go('dashboard'); 34 | 35 | // // Se redirecciona a la ruta indicada 36 | // if ($rootScope.url.state !== null) { 37 | // $state.go($rootScope.url.state, $rootScope.url.params); 38 | // } else{ 39 | // 40 | //} 41 | }) 42 | .catch(function(err){ 43 | 44 | $('#formLogin').addClass('animated shake'); 45 | 46 | if (err.status == 404) { 47 | $translate('LOGIN.MESSAGES.ERROR404').then(function (translate) { 48 | $.smkAlert({ 49 | text: translate, 50 | type: 'warning' 51 | }); 52 | }); 53 | }else if (err.status == 400) { 54 | $translate('LOGIN.MESSAGES.ERROR400').then(function (translate) { 55 | $.smkAlert({ 56 | text: translate, 57 | type: 'warning' 58 | }); 59 | }); 60 | } 61 | 62 | }) 63 | .finally(function(){ 64 | btn.button('reset'); 65 | }); 66 | 67 | } 68 | 69 | }; 70 | 71 | 72 | }]); 73 | 74 | }()); 75 | -------------------------------------------------------------------------------- /app/app/modules/auth/login.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |

{{'LOGIN.LOGIN' | translate}}

6 | 7 |
8 |
9 | 10 | 11 | 12 | 13 |
14 |
15 | 16 |
17 |
18 | 19 | 20 | 21 | 22 |
23 |
24 | 25 |
26 |
27 | 31 |
32 |
33 | 34 | 37 | 38 |
39 | 40 | {{'LOGIN.FORGOTPASSWORD' | translate}} 41 | 42 | 43 | 44 | {{'SIGNUP.SIGNUP' | translate}} 45 | 46 |
47 |
48 | 49 | 50 | 51 |
52 | 53 |
54 |
55 |

Admin

56 |

57 | user: admin
58 | pass: Admin123 59 |

60 |
61 |
62 |

User

63 |

64 | user: user
65 | pass: User123 66 |

67 |
68 |
69 |

Guest

70 |

71 | user: guest
72 | pass: Guest123 73 |

74 |
75 |
76 | 77 |
78 | 79 | 80 | 81 |
82 | -------------------------------------------------------------------------------- /app/app/modules/auth/passwordReset.controller.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('auth') 6 | .controller('PasswordResetCtrl', ['$scope', '$state', '$location', 'sanitizeService', 'restFulService', function($scope, $state, $location, sanitizeService, restFulService){ 7 | 8 | $scope.formPasswordReset = {}; 9 | $scope.show = { 10 | form: false, 11 | message: false 12 | }; 13 | 14 | // Si falta alguno de los 3 parametros 15 | if ($state.params.token === '' || $state.params.tokenId === '' || $state.params.userId === '') 16 | $location.path('error'); 17 | 18 | // Se valida que el token exista en la DB 19 | restFulService.get('auth/findPasswordReset/' + $state.params.token +'/'+ $state.params.tokenId +'/'+ $state.params.userId) 20 | .then(function(response){ 21 | 22 | $scope.show.form = true; 23 | 24 | }) 25 | .catch(function(err){ 26 | if (err.status != 302) { 27 | $location.path('error/' + err.status); 28 | } else { 29 | $location.path('/'); 30 | } 31 | }); 32 | 33 | $scope.passwordReset = function(event) { 34 | 35 | if ($('#formPasswordReset').smkValidate()) { 36 | if( $.smkEqualPass('#formPasswordReset #password', '#formPasswordReset #rePassword') ){ 37 | 38 | var btn = $(event.target); 39 | btn.button('loading'); 40 | 41 | var data = sanitizeService.array($scope.formPasswordReset); 42 | 43 | console.log(data); 44 | 45 | restFulService.put('auth/passwordReset/' + $state.params.userId, data) 46 | .then(function(response){ 47 | 48 | $scope.show.form = false; 49 | $scope.show.message = true; 50 | 51 | }) 52 | .finally(function(){ 53 | btn.button('reset'); 54 | }); 55 | 56 | } 57 | } 58 | 59 | }; 60 | 61 | }]); 62 | 63 | }()); 64 | -------------------------------------------------------------------------------- /app/app/modules/auth/passwordReset.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |

{{'PASSWORD-RESET.HEADLINE' | translate}}

6 | 7 |
8 |
9 | 10 | 11 | 12 | 13 |
14 |
15 | 16 |
17 |
18 | 19 | 20 | 21 | 22 |
23 |
24 | 25 | 28 | 29 |
30 | 31 |
32 | 33 |
34 | 35 |

{{'PASSWORD-RESET.MESSAGES.SUCCESS.HEADLINE' | translate}}

36 |

{{'PASSWORD-RESET.MESSAGES.SUCCESS.PARAGRAPH' | translate}}

37 |
38 | 39 |
40 | 41 |
42 | -------------------------------------------------------------------------------- /app/app/modules/auth/sendPasswordReset.controller.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('auth') 6 | .controller('SendPasswordResetCtrl', ['$rootScope', '$scope', '$state', 'restFulService', function($rootScope, $scope, $state, restFulService){ 7 | 8 | $scope.formSendPasswordReset = {}; 9 | $scope.show = { 10 | message: false 11 | }; 12 | 13 | if ($rootScope.account === undefined) 14 | $state.go('beginPasswordReset'); 15 | 16 | $scope.sendPasswordReset = function(event){ 17 | 18 | var btn = $(event.target); 19 | btn.button('loading'); 20 | 21 | var userId = $rootScope.account.id; 22 | 23 | restFulService.get('auth/createPasswordReset/' + userId) 24 | .then(function(response){ 25 | 26 | $scope.show.message = true; 27 | 28 | }) 29 | .finally(function(){ 30 | btn.button('reset'); 31 | }); 32 | 33 | }; 34 | 35 | }]); 36 | 37 | }()); 38 | -------------------------------------------------------------------------------- /app/app/modules/auth/sendPasswordReset.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |

{{'SEND-PASSWORD-RESET.HEADLINE' | translate}}

6 | 7 |
8 |
9 | 10 |
11 |
12 |

{{account.profile.fullName}}

13 |

{{account.username}}

14 |
15 |
16 | 17 |

{{'SEND-PASSWORD-RESET.PARAGRAPH' | translate}}

18 | 19 |

{{'SEND-PASSWORD-RESET.PARAGRAPH2' | translate}}{{account.email}}

20 | 21 | 24 | 25 |
26 | 27 |
28 | 29 |
30 | 31 |

{{'SEND-PASSWORD-RESET.MESSAGES.SUCCESS.HEADLINE' | translate}}

32 |

{{'SEND-PASSWORD-RESET.MESSAGES.SUCCESS.PARAGRAPH' | translate}}

33 | 34 |

35 | 36 | {{'SEND-PASSWORD-RESET.MESSAGES.SUCCESS.LINK'| translate}} 37 | 38 |

39 |
40 | 41 | 44 | 45 |
46 | 47 |
48 | -------------------------------------------------------------------------------- /app/app/modules/auth/signup.controller.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('auth') 6 | .controller('SignupCtrl', ['$scope', '$translate', 'sanitizeService', 'restFulService', 'errorService', function($scope, $translate, sanitizeService, restFulService, errorService){ 7 | 8 | $scope.formSignup = {}; 9 | $scope.show = { 10 | message: false 11 | }; 12 | 13 | $scope.signup = function(event){ 14 | 15 | $('#formSignup').removeClass('animated shake'); 16 | 17 | if ($('#formSignup').smkValidate()) { 18 | if( $.smkEqualPass('#formSignup #password', '#formSignup #rePassword') ){ 19 | 20 | var btn = $(event.target); 21 | btn.button('loading'); 22 | 23 | var data = sanitizeService.array($scope.formSignup); 24 | 25 | data.lang = localStorage.getItem('NG_TRANSLATE_LANG_KEY'); 26 | 27 | restFulService.post('auth/signup', data) 28 | .then(function(response){ 29 | 30 | $scope.show.message = true; 31 | 32 | }) 33 | .catch(function(err){ 34 | console.log(err); 35 | if (err.status == 500) { 36 | $('#formSignup').addClass('animated shake'); 37 | 38 | var value = errorService.getRawMessageValue(err.error.raw.message); 39 | 40 | $translate('SIGNUP.MESSAGES.ERROR', { emailOrUsername: value }).then(function (translate) { 41 | $.smkAlert({ 42 | text: translate, 43 | type: 'warning' 44 | }); 45 | }); 46 | } 47 | }) 48 | .finally(function(){ 49 | btn.button('reset'); 50 | }); 51 | } 52 | } 53 | 54 | }; 55 | 56 | }]); 57 | 58 | }()); 59 | -------------------------------------------------------------------------------- /app/app/modules/dashboard/dashboard.controller.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('dashboard') 6 | .controller('DashboardCtrl', ['$scope', function($scope){ 7 | 8 | 9 | }]); 10 | 11 | }()); 12 | -------------------------------------------------------------------------------- /app/app/modules/dashboard/dashboard.module.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('dashboard', []) 6 | .config(['$stateProvider', function($stateProvider){ 7 | 8 | $stateProvider 9 | .state('dashboard', { 10 | parent: 'layout', 11 | url: '/dashboard', 12 | templateUrl: 'app/modules/dashboard/dashboard.html', 13 | controller: 'DashboardCtrl' 14 | }); 15 | 16 | }]); 17 | 18 | }()); 19 | -------------------------------------------------------------------------------- /app/app/modules/errors/error.controller.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('errors') 6 | .controller('ErrorCtrl', ['$scope', '$state', 'errorService', function($scope, $state, errorService){ 7 | 8 | if ($state.params.errorId === '') { 9 | $scope.errorId = 404; 10 | }else{ 11 | $scope.errorId = $state.params.errorId; 12 | } 13 | 14 | $scope.error = errorService.getStatusCodeText($scope.errorId); 15 | 16 | }]); 17 | 18 | }()); 19 | -------------------------------------------------------------------------------- /app/app/modules/errors/error.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | {{errorId}} 4 |

{{error}}

5 |
6 | -------------------------------------------------------------------------------- /app/app/modules/errors/errors.module.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('errors', []) 6 | .config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider){ 7 | 8 | $urlRouterProvider.otherwise('/error/'); 9 | 10 | $stateProvider 11 | .state('error', { 12 | parent: 'layoutAuth', 13 | url: '/error/:errorId', 14 | templateUrl: 'app/modules/errors/error.html', 15 | controller: 'ErrorCtrl' 16 | }); 17 | 18 | }]); 19 | 20 | }()); 21 | -------------------------------------------------------------------------------- /app/app/modules/files/files.controller.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('files') 6 | .controller('FilesCtrl', ['$scope', function($scope){ 7 | 8 | }]); 9 | 10 | }()); 11 | -------------------------------------------------------------------------------- /app/app/modules/files/files.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 | 10 | 11 |
12 |
13 | 14 |
15 | -------------------------------------------------------------------------------- /app/app/modules/files/files.module.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('files', []) 6 | .config(['$stateProvider', function($stateProvider){ 7 | 8 | // Create routes 9 | $stateProvider 10 | .state('files', { 11 | parent: 'layout', 12 | url: '/files', 13 | templateUrl: 'app/modules/files/files.html', 14 | controller: 'FilesCtrl' 15 | }); 16 | 17 | }]); 18 | 19 | }()); 20 | -------------------------------------------------------------------------------- /app/app/modules/helloWorld/hello.controller.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('helloWorld') 6 | .controller('HelloCtrl', ['$scope', 'restFulService', function($scope, restFulService){ 7 | 8 | $scope.greeting = []; 9 | 10 | // Events 11 | 12 | // Methods 13 | function getGreeting() 14 | { 15 | restFulService.get('hello') 16 | .then(function(response){ 17 | $scope.greeting = response[0]; 18 | }); 19 | } 20 | 21 | // Watch 22 | getGreeting(); 23 | 24 | }]); 25 | 26 | }()); 27 | -------------------------------------------------------------------------------- /app/app/modules/helloWorld/hello.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 |
6 |
7 |

Hello World 2

8 |
9 |
10 | {{greeting}} 11 |
12 |
13 |
14 |
15 | 16 |
17 | -------------------------------------------------------------------------------- /app/app/modules/helloWorld/hello.module.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('helloWorld', []) 6 | .config(['$stateProvider', function($stateProvider){ 7 | 8 | // Create routes 9 | $stateProvider 10 | .state('hello', { 11 | parent: 'layout', 12 | url: '/hello', 13 | templateUrl: 'app/modules/helloWorld/hello.html', 14 | controller: 'HelloCtrl' 15 | }); 16 | 17 | }]); 18 | 19 | }()); 20 | -------------------------------------------------------------------------------- /app/app/modules/layout/layout.module.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('layout', []) 6 | .config(['$stateProvider', function($stateProvider){ 7 | 8 | $stateProvider 9 | .state('layoutAuth', { 10 | abstract: true, 11 | templateUrl: 'app/modules/layout/layoutAuth.html', 12 | controller: 'LayoutAuthCtrl' 13 | }) 14 | .state('layout', { 15 | abstract: true, 16 | templateUrl: 'app/modules/layout/layout.html', 17 | controller: 'LayoutCtrl' 18 | }); 19 | 20 | }]); 21 | 22 | }()); 23 | -------------------------------------------------------------------------------- /app/app/modules/layout/layoutAuth.controller.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('layout') 6 | .controller('LayoutAuthCtrl', ['$scope', '$translate', 'restFulService', function($scope, $translate, restFulService){ 7 | 8 | $scope.languages = {}; 9 | // Se obtiene la colleccion de lenguajes 10 | getLanguage(); 11 | 12 | /** 13 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 14 | * Events 15 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 16 | */ 17 | $scope.changeLanguage = function(lang) { 18 | $translate.use(lang); 19 | }; 20 | 21 | /* 22 | |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 23 | | Methods 24 | |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 25 | */ 26 | function getLanguage() 27 | { 28 | restFulService.get('language') 29 | .then(function(response){ 30 | $scope.languages = response; 31 | }); 32 | } 33 | 34 | }]); 35 | 36 | }()); 37 | -------------------------------------------------------------------------------- /app/app/modules/layout/layoutAuth.html: -------------------------------------------------------------------------------- 1 |
2 | 42 |
43 | 44 |
45 | -------------------------------------------------------------------------------- /app/app/modules/log/log.module.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('log', []) 6 | .config(['$stateProvider', function($stateProvider){ 7 | 8 | $stateProvider 9 | .state('logLogin', { 10 | parent: 'layout', 11 | url: '/log/login', 12 | templateUrl: 'app/modules/log/logLogin.html', 13 | controller: 'LogLoginCtrl' 14 | }) 15 | .state('logRequest', { 16 | parent: 'layout', 17 | url: '/log/request', 18 | templateUrl: 'app/modules/log/logRequest.html', 19 | controller: 'LogRequestCtrl' 20 | }); 21 | 22 | }]); 23 | 24 | }()); 25 | -------------------------------------------------------------------------------- /app/app/modules/log/log.service.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('log') 6 | .factory('logService', [function(){ 7 | 8 | return{ 9 | 10 | makeDataChart: function(data, label, value) 11 | { 12 | var res = { 13 | labels: [], 14 | data: [], 15 | values: [] 16 | }; 17 | 18 | data.forEach(function(v) { 19 | res.labels.push(v[label]); 20 | res.values.push(v[value]); 21 | }); 22 | 23 | res.data = this.percentage(res.values); 24 | 25 | return res; 26 | }, 27 | 28 | updateDataChart: function(collection, model, label, value) 29 | { 30 | var pos = collection.labels.indexOf(model[label]); 31 | 32 | if ( pos != -1 ){ 33 | collection.values[pos] = collection.values[pos] + model[value]; 34 | } else { 35 | collection.labels.push(model[label]); 36 | collection.values.push(model[value]); 37 | } 38 | 39 | collection.data = this.percentage(collection.values); 40 | }, 41 | 42 | percentage: function(array) 43 | { 44 | var res = []; 45 | 46 | var total = array.reduce(function(a, b) { 47 | return a + b; 48 | }); 49 | 50 | array.forEach(function(v){ 51 | res.push(parseFloat(((v / total) * 100).toFixed(2))); 52 | }); 53 | 54 | return res; 55 | } 56 | 57 | }; 58 | 59 | }]); 60 | 61 | }()); 62 | -------------------------------------------------------------------------------- /app/app/modules/log/logLogin.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 |
6 |
7 |

{{ 'LOG.BROWSER' | translate }}

8 |
9 |
10 | 12 |
13 |
14 |
15 |
16 |
17 |
18 |

{{ 'LOG.OS' | translate }}

19 |
20 |
21 | 23 |
24 |
25 |
26 |
27 |
28 |
29 |

{{ 'LOG.USERS' | translate }}

30 |
31 |
32 |
33 |
34 | 35 | 36 | 37 | 38 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 |
39 | {{row.user.username}} 40 | {{row.ip | filterIp}}{{row.device}}{{row.os}}{{row.browser}}{{row.createdAt | amDateFormat:'llll'}}
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | 57 |
58 | -------------------------------------------------------------------------------- /app/app/modules/log/logRequest.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 |
6 |
7 |

{{ 'LOG.RESPONSETIME' | translate }}

8 |
9 |
10 |
11 |
12 | 14 |
15 |
16 | 17 |
18 |
19 |
20 | 31 |
32 |
33 |
34 |

{{ 'LOG.USERS' | translate }}

35 |
36 |
37 |
38 |
39 | 40 | 41 | 42 | 43 | 46 | 47 | 51 | 52 | 53 | 54 | 55 |
44 | {{row.user.username}} 45 | {{row.method}} 48 | {{row.url}}
49 | {{row.parameters}} 50 |
{{row.responseTime}} / {{row.middlewareLatency}}{{row.createdAt | amDateFormat:'lll'}}
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 | 64 |
65 | -------------------------------------------------------------------------------- /app/app/modules/profile/emailChange.controller.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('users') 6 | .controller('EmailChangeCtrl', ['$rootScope', '$scope', '$state', '$location', '$translate', 'restFulService', 'config', 'errorService', function($rootScope, $scope, $state, $location, $translate, restFulService, config, errorService){ 7 | 8 | $scope.show = { 9 | message: false 10 | }; 11 | 12 | // Si falta alguno de los 3 parametros 13 | if ($state.params.token === '' || $state.params.tokenId === '' || $state.params.userId === '') 14 | $location.path('error'); 15 | 16 | // Se valida que el token exista en la DB 17 | restFulService.get('emailChange/validate/' + $state.params.token +'/'+ $state.params.tokenId +'/'+ $state.params.userId) 18 | .then(function(response){ 19 | $scope.email = response.email; 20 | $rootScope.user.email = response.email; 21 | $scope.show.message = true; 22 | }) 23 | .catch(function(err){ 24 | $location.path('error/' + err.status); 25 | }); 26 | 27 | }]); 28 | 29 | }()); 30 | -------------------------------------------------------------------------------- /app/app/modules/profile/emailChange.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 | 6 | 7 |

{{'PROFILE.MESSAGES.EMAIL-CHANGE.SUCCESS.HEADLINE' | translate}}

8 | 9 |

{{'PROFILE.MESSAGES.EMAIL-CHANGE.SUCCESS.PARAGRAPH' | translate}} {{email}}

10 |
11 | 12 |
13 |
14 | -------------------------------------------------------------------------------- /app/app/modules/profile/permissions.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 | 6 |
7 |
8 |
9 | 10 | 11 |
12 | 13 |
14 | 19 |
20 | 21 |
22 |
23 | 24 |
25 | -------------------------------------------------------------------------------- /app/app/modules/profile/profile.module.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('profile', []) 6 | .config(['$stateProvider', function($stateProvider){ 7 | 8 | $stateProvider 9 | .state('profile', { 10 | parent: 'layout', 11 | url: '/profile/:id', 12 | templateUrl: 'app/modules/profile/profile.html', 13 | controller: 'ProfileCtrl', 14 | }) 15 | .state('email_change', { 16 | parent: 'layoutAuth', 17 | url: '/email_change/:token/:tokenId/:userId', 18 | templateUrl: 'app/modules/profile/emailchange.html', 19 | controller: 'EmailChangeCtrl' 20 | }); 21 | 22 | }]); 23 | 24 | }()); 25 | -------------------------------------------------------------------------------- /app/app/modules/profile/profilePermissions.controller.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('users') 6 | .controller('ProfilePermissionsCtrl', ['$scope', '$translate', 'restFulService', ProfilePermissionsCtrl]); 7 | 8 | function ProfilePermissionsCtrl($scope, $translate, restFulService) { 9 | 10 | 11 | $scope.formPermissions = {}; 12 | 13 | 14 | /* 15 | |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 16 | | Events 17 | |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 18 | */ 19 | $scope.savePermissions = function(event) { 20 | 21 | var btn = $(event.target); 22 | btn.button('loading'); 23 | 24 | var data = { 25 | role: $scope.formPermissions.role 26 | }; 27 | 28 | restFulService.put('user/' + $scope.user.id, data) 29 | .then(function(response){ 30 | 31 | $scope.user.role = response.role; 32 | 33 | $translate('MESSAGES.SUCCESS').then(function (translate) { 34 | $.smkAlert({ 35 | text: translate, 36 | type: 'success', 37 | position: 'bottom-left' 38 | }); 39 | }); 40 | }) 41 | .finally(function(){ 42 | btn.button('reset'); 43 | }); 44 | 45 | }; 46 | 47 | /** 48 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 49 | * watch & calls 50 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 51 | */ 52 | $scope.$watch('user.role', function(nv, ov) { 53 | if(nv !== undefined && nv !== ''){ 54 | $scope.formPermissions.permissions = nv.permissions; 55 | } 56 | }); 57 | 58 | $scope.$watch('formPermissions.role', function(nv, ov) { 59 | if(nv !== undefined && nv !== ''){ 60 | $scope.formPermissions.permissions = nv.permissions; 61 | } 62 | }); 63 | 64 | 65 | } 66 | 67 | }()); 68 | -------------------------------------------------------------------------------- /app/app/modules/profile/profileWork.controller.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('users') 6 | .controller('ProfileWorkCtrl', ['$scope', '$translate', 'restFulService', ProfileWorkCtrl]); 7 | 8 | function ProfileWorkCtrl($scope, $translate, restFulService) { 9 | 10 | $scope.formWork = {}; 11 | 12 | 13 | /* 14 | |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 15 | | Events 16 | |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 17 | */ 18 | $scope.saveWork = function(event) 19 | { 20 | var btn = $(event.target); 21 | btn.button('loading'); 22 | 23 | var data = { 24 | job: $scope.formWork.job.job, 25 | department: $scope.formWork.department.department, 26 | company: $scope.formWork.company.company 27 | }; 28 | 29 | restFulService.put('profile/' + $scope.user.profile.id, data) 30 | .then(function(response){ 31 | 32 | $scope.user.profile.job = response.job; 33 | $scope.user.profile.department = response.department; 34 | $scope.user.profile.company = response.company; 35 | 36 | $translate('MESSAGES.SUCCESS').then(function (translate) { 37 | $.smkAlert({ 38 | text: translate, 39 | type: 'success', 40 | position: 'bottom-left' 41 | }); 42 | }); 43 | }) 44 | .finally(function(){ 45 | btn.button('reset'); 46 | }); 47 | }; 48 | 49 | } 50 | 51 | }()); 52 | -------------------------------------------------------------------------------- /app/app/modules/profile/work.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 | 6 |
7 |
8 |

{{ 'PROFILE.WORK' | translate }}

9 |
10 |
11 |
12 |
13 | 14 |
15 | 16 |
17 |
18 |
19 | 20 |
21 | 22 |
23 |
24 |
25 | 26 |
27 | 28 |
29 |
30 |
31 |
32 | 35 |
36 | 37 |
38 |
39 |

fecha que ingreso a trabajar, inventarios(compu, celular, automovil) Archivos(comp. estudios, acta de nacimiento, cedula, etc)

40 |
41 |
42 | 43 |
44 | -------------------------------------------------------------------------------- /app/app/modules/settings/modules/modules.controller.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('settings') 6 | .controller('ModulesCtrl', ['$rootScope', '$scope', 'restFulService', '$translate', ModulesCtrl]); 7 | 8 | function ModulesCtrl($rootScope, $scope, restFulService, $translate){ 9 | 10 | $scope.modules = []; 11 | 12 | /** 13 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 14 | * Methods 15 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 16 | */ 17 | function getModules() 18 | { 19 | restFulService.get('module/all') 20 | .then(function(response){ 21 | $scope.modules = response; 22 | }); 23 | } 24 | 25 | /** 26 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 27 | * Events 28 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 29 | */ 30 | $scope.treeOptions = { 31 | beforeDrop: function(e) { 32 | restFulService.put('module/saveOrder', $scope.modules) 33 | .then(function(response){ 34 | $scope.modules = response; 35 | $rootScope.modules = response; 36 | $translate('MESSAGES.SUCCESS').then(function (translate) { 37 | $.smkAlert({ 38 | text: translate, 39 | type: 'success', 40 | position: 'bottom-left' 41 | }); 42 | }); 43 | }); 44 | return true; 45 | }, 46 | }; 47 | 48 | $scope.toggleModule = function(item) 49 | { 50 | item.active = !item.active; 51 | restFulService.put('module/update/'+ item.id, {'active':item.active} ) 52 | .then(function(response){ 53 | $rootScope.modules = response; 54 | $translate('MESSAGES.SUCCESS').then(function (translate) { 55 | $.smkAlert({ 56 | text: translate, 57 | type: 'success', 58 | position: 'bottom-left' 59 | }); 60 | }); 61 | }); 62 | }; 63 | 64 | /** 65 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 66 | * Watch end Calls 67 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 68 | */ 69 | getModules(); 70 | 71 | } 72 | 73 | })(); 74 | -------------------------------------------------------------------------------- /app/app/modules/settings/modules/modules.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
    11 |
  1. 12 |
    13 | | {{item.title}} 14 | 18 |
    19 |
  2. 20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | 29 |
30 | -------------------------------------------------------------------------------- /app/app/modules/settings/settings.module.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('settings', []) 6 | .config(['$stateProvider', function($stateProvider){ 7 | 8 | $stateProvider 9 | .state('modules', { 10 | parent: 'layout', 11 | url: '/settings/modules', 12 | templateUrl: 'app/modules/settings/modules/modules.html', 13 | controller: 'ModulesCtrl' 14 | }); 15 | 16 | }]); 17 | 18 | }()); 19 | -------------------------------------------------------------------------------- /app/app/modules/users/roles/roleAuthorizations.html: -------------------------------------------------------------------------------- 1 |
2 |
    3 |
  1. 4 |
    5 | 9 | | {{item.title}} 10 | 14 | 18 |
    19 |
      20 |
    1. 21 |
      22 | {{subItem.title}} 23 | 27 | 31 |
      32 |
    2. 33 |
    34 |
  2. 35 |
36 |
37 | -------------------------------------------------------------------------------- /app/app/modules/users/roles/rolePermissions.html: -------------------------------------------------------------------------------- 1 |
2 |
    3 |
  1. 4 |
    5 | 9 | | {{item.title}} 10 | 14 | 18 |
    19 |
      20 |
    1. 21 |
      22 | {{subItem.title}} 23 | 27 | 31 |
      32 |
    2. 33 |
    34 |
  2. 35 |
36 |
37 | -------------------------------------------------------------------------------- /app/app/modules/users/users.module.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 'use strict'; 3 | 4 | angular 5 | .module('users', []) 6 | .config(['$stateProvider', function($stateProvider){ 7 | 8 | $stateProvider 9 | .state('users', { 10 | parent: 'layout', 11 | url: '/users', 12 | templateUrl: 'app/modules/users/users/users.html', 13 | controller: 'UsersCtrl' 14 | }) 15 | .state('roles', { 16 | parent: 'layout', 17 | url: '/users/roles', 18 | templateUrl: 'app/modules/users/roles/roles.html', 19 | controller: 'RolesCtrl' 20 | }) 21 | .state('access', { 22 | parent: 'layout', 23 | url: '/users/access', 24 | templateUrl: 'app/modules/users/access/access.html', 25 | controller: 'AccessCtrl' 26 | }); 27 | 28 | }]); 29 | 30 | }()); 31 | -------------------------------------------------------------------------------- /app/app/sass/main.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3 | * mixins 4 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 | */ 6 | @import "mixins/animation"; 7 | @import "mixins/box-shadow"; 8 | @import "mixins/opacity"; 9 | @import "mixins/placeholder"; 10 | @import "mixins/transition"; 11 | /** 12 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 13 | * base 14 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 15 | */ 16 | @import "partials/variables"; 17 | @import "partials/normalize"; 18 | @import "partials/margin"; 19 | /** 20 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 21 | * components 22 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 23 | */ 24 | @import "partials/alerts"; 25 | @import "partials/animations"; 26 | @import "partials/badges"; 27 | @import "partials/breadcrumb"; 28 | @import "partials/dropdowns"; 29 | @import "partials/buttons"; 30 | @import "partials/forms"; 31 | @import "partials/labels"; 32 | @import "partials/lists"; 33 | @import "partials/media"; 34 | @import "partials/modals"; 35 | @import "partials/pagination"; 36 | @import "partials/panels"; 37 | @import "partials/tables"; 38 | @import "partials/tabs"; 39 | @import "partials/tooltips"; 40 | 41 | @import "partials/tree"; 42 | @import "partials/intro"; 43 | 44 | 45 | @import "partials/header"; 46 | @import "partials/nav"; 47 | @import "partials/aside"; 48 | @import "partials/section"; 49 | @import "partials/footer"; 50 | @import "partials/loading"; 51 | @import "partials/loading-panel"; 52 | /** 53 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 54 | * Modules 55 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 56 | */ 57 | @import "modules/auth"; 58 | @import "modules/error"; 59 | @import "modules/profile"; 60 | @import "modules/comments"; 61 | -------------------------------------------------------------------------------- /app/app/sass/mixins/_animation.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3 | * @include animation(all .5s); 4 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 | */ 6 | @mixin animation($args) { 7 | -webkit-animation: $args; 8 | -moz-animation: $args; 9 | -ms-animation: $args; 10 | -o-animation: $args; 11 | animation: $args; 12 | } 13 | -------------------------------------------------------------------------------- /app/app/sass/mixins/_box-shadow.scss: -------------------------------------------------------------------------------- 1 | @mixin box-shadow($args) { 2 | -webkit-box-shadow: $args; 3 | -moz-box-shadow: $args; 4 | box-shadow: $args; 5 | } 6 | -------------------------------------------------------------------------------- /app/app/sass/mixins/_opacity.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3 | * opacity 4 | * usage @include opacity(0.8); 5 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 6 | */ 7 | @mixin opacity($opacity) { 8 | opacity: $opacity; 9 | $opacity-ie: $opacity * 100; 10 | filter: alpha(opacity=$opacity-ie); //IE8 11 | } 12 | -------------------------------------------------------------------------------- /app/app/sass/mixins/_placeholder.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3 | * Placeholder 4 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 | */ 6 | @mixin placeholder { 7 | ::-webkit-input-placeholder {@content} 8 | :-moz-placeholder {@content} 9 | ::-moz-placeholder {@content} 10 | :-ms-input-placeholder {@content} 11 | } 12 | -------------------------------------------------------------------------------- /app/app/sass/mixins/_transition.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3 | * @include transition(all .5s); 4 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 | */ 6 | @mixin transition($args) { 7 | -webkit-transition: $args; 8 | -moz-transition: $args; 9 | -ms-transition: $args; 10 | -o-transition: $args; 11 | transition: $args; 12 | } 13 | -------------------------------------------------------------------------------- /app/app/sass/modules/_auth.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3 | * form-auth 4 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 | */ 6 | .auth-form { 7 | margin: 100px auto; 8 | max-width: 600px; 9 | padding: 30px 35px; 10 | 11 | h2 { 12 | font-weight: lighter !important; 13 | margin: 0 0 15px 0; 14 | padding: 0 0 15px 0; 15 | } 16 | 17 | .btn-block { 18 | margin: 10px 0 20px 0; 19 | font-size: 24px; 20 | height: 56px; 21 | } 22 | 23 | .btn-link { 24 | font-size: 16px; 25 | padding: 0; 26 | 27 | &:hover{ 28 | text-decoration: none; 29 | } 30 | } 31 | 32 | .form-group { 33 | margin-bottom: 20px; 34 | 35 | .input-group { 36 | 37 | .input-group-addon { 38 | background-color: $white; 39 | border-radius: 0; 40 | } 41 | 42 | .form-control { 43 | background-color: $white; 44 | height: 56px; 45 | } 46 | 47 | } 48 | 49 | .form-control-feedback { 50 | width: 56px; 51 | height: 56px; 52 | line-height: 56px; 53 | font-size: 20px; 54 | } 55 | } 56 | 57 | .media{ 58 | margin-bottom: 30px; 59 | 60 | .media-left { 61 | img { 62 | width: 60px; 63 | height: 60px; 64 | } 65 | } 66 | .media-body { 67 | p:first-child { 68 | margin: 8px 0 0 0; 69 | } 70 | } 71 | 72 | } 73 | 74 | } 75 | 76 | .auth-content { 77 | margin: 100px auto; 78 | max-width: 600px; 79 | text-align: center; 80 | 81 | .fa-6 { 82 | font-size: 7em; 83 | } 84 | 85 | h1 { 86 | font-weight: lighter !important; 87 | } 88 | 89 | .auth-content-body { 90 | background-color: $white; 91 | padding: 55px 25px; 92 | } 93 | 94 | .auth-content-footer { 95 | padding: 25px; 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /app/app/sass/modules/_comments.scss: -------------------------------------------------------------------------------- 1 | .comments .media-list { 2 | max-height: 300px; 3 | overflow-y: scroll; 4 | overflow-x: hidden; 5 | 6 | &::-webkit-scrollbar { 7 | width: 5px; 8 | } 9 | &::-webkit-scrollbar-thumb { 10 | background: $gray; 11 | } 12 | &::-webkit-scrollbar-thumb:window-inactive { 13 | background: rgba($black, 0.4); 14 | } 15 | } 16 | 17 | .comments form .input-group .input-group-addon { 18 | border: none; 19 | vertical-align: top; 20 | padding: 0 12px 0 0; 21 | } 22 | 23 | .comments form .input-group textarea { 24 | resize: none; 25 | } 26 | -------------------------------------------------------------------------------- /app/app/sass/modules/_error.scss: -------------------------------------------------------------------------------- 1 | .error { 2 | position: relative; 3 | margin: 12% auto 0 auto; 4 | max-width: 500px; 5 | //padding: 30px 45px 65px 45px; 6 | 7 | span { 8 | position: absolute; 9 | top: 17%; 10 | left: 36%; 11 | font-size: 8em; 12 | font-weight: bold; 13 | color: $black; 14 | } 15 | 16 | h4 { 17 | margin-bottom: 100px; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/app/sass/partials/_alerts.scss: -------------------------------------------------------------------------------- 1 | 2 | .smk-alert-content { 3 | 4 | .alert { 5 | border-radius: 0; 6 | // margin-bottom: 10px; 7 | } 8 | } 9 | 10 | .smk-confirm-back { 11 | z-index: 1050; 12 | } 13 | // .smk-alert-content-top-right{ 14 | // top: 5px; 15 | // right: 5px; 16 | // } 17 | // .smk-alert-content-top-left{ 18 | // top: 5px; 19 | // left: 10px; 20 | // } 21 | // .smk-alert-content-bottom-right{ 22 | // bottom: 0; 23 | // right: 10px; 24 | // } 25 | // .smk-alert-content-bottom-left{ 26 | // bottom: 0; 27 | // left: 10px; 28 | // } 29 | -------------------------------------------------------------------------------- /app/app/sass/partials/_animations.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3 | * content and container-fluid 4 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 | */ 6 | .content { 7 | @include animation(all .5s); 8 | } 9 | 10 | .content.ng-enter, 11 | .content.ng-enter-active { 12 | footer, 13 | header{ 14 | @include animation(fadeInDown .5s); 15 | } 16 | nav{ 17 | @include animation(fadeInLeft .5s); 18 | } 19 | .container-fluid { 20 | @include animation(fadeIn .5s); 21 | } 22 | } 23 | 24 | .content.ng-leave, 25 | .content.ng-leave-active { 26 | footer, 27 | header{ 28 | @include animation(fadeOutUp .5s); 29 | } 30 | nav{ 31 | @include animation(fadeOutLeft .5s); 32 | } 33 | .container-fluid { 34 | @include animation(fadeOut .5s); 35 | } 36 | } 37 | 38 | /* 39 | |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 40 | | Buttons 41 | |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 42 | */ 43 | .btn.ng-animate { 44 | transition:0s none !important; 45 | -webkit-transition:0s none !important; 46 | animation: 0s none !important; 47 | -webkit-animation: 0s none !important; 48 | } 49 | -------------------------------------------------------------------------------- /app/app/sass/partials/_badges.scss: -------------------------------------------------------------------------------- 1 | .badge { 2 | &.badge-danger { 3 | background-color: $red; 4 | } 5 | &.badge-success { 6 | background-color: $green; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /app/app/sass/partials/_breadcrumb.scss: -------------------------------------------------------------------------------- 1 | .breadcrumb { 2 | margin-bottom: 0; 3 | background-color: transparent; 4 | 5 | & > li + li:before { 6 | color: #aaa; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /app/app/sass/partials/_dropdowns.scss: -------------------------------------------------------------------------------- 1 | .dropdown-menu{ 2 | border-radius: 0; 3 | padding: 0; 4 | border: none; 5 | 6 | li { 7 | a{ 8 | padding: 8px 20px; 9 | } 10 | } 11 | li.divider{ 12 | margin: 0 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/app/sass/partials/_footer.scss: -------------------------------------------------------------------------------- 1 | footer { 2 | position: fixed; 3 | top: 0; 4 | left: 0; 5 | right: 0; 6 | padding: 20px 0; 7 | background-color: red; 8 | 9 | .logo { 10 | text-decoration: none; 11 | 12 | svg { 13 | width: 36px; 14 | margin-bottom: -9px; 15 | 16 | path{ 17 | @include transition(all .2s ease); 18 | } 19 | 20 | path:hover { 21 | fill: lighten($orange, 20%); 22 | } 23 | } 24 | // img:first-child { 25 | // margin-top: 6px; 26 | // height: 20px; 27 | // } 28 | img { //img:last-child 29 | margin-top: 0; 30 | } 31 | } 32 | 33 | img { 34 | width: 110px; 35 | margin-top: 5px; 36 | } 37 | 38 | .btn-group{ 39 | .btn-link { 40 | text-decoration: none; 41 | } 42 | ul.dropdown-menu{ 43 | background: rgba($white, 0.9); 44 | padding: 0; 45 | border: none; 46 | border-radius: 0; 47 | a { 48 | color: $gray-dark-10; 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/app/sass/partials/_intro.scss: -------------------------------------------------------------------------------- 1 | .introjs-tooltip { 2 | background-color: rgba(000, 0, 0, 0.5); 3 | color: #fff; 4 | } 5 | 6 | .introjs-tooltiptext { 7 | text-align: center; 8 | } 9 | 10 | .introjs-button, 11 | .introjs-button:hover, .introjs-button:focus, .introjs-button:active, 12 | .introjs-disabled, .introjs-disabled:focus, .introjs-disabled:hover { 13 | outline: none; 14 | background-image: none; 15 | background-color: transparent; 16 | color: #fff; 17 | border: 1px solid transparent; 18 | border-radius: 50px; 19 | box-shadow: none; 20 | border-shadow: none; 21 | text-shadow: none; 22 | } 23 | 24 | .introjs-button:hover, .introjs-button:focus, .introjs-button:active { 25 | border: 1px solid #fff 26 | } 27 | .introjs-disabled, .introjs-disabled:focus, .introjs-disabled:hover { 28 | color: #ccc; 29 | border: 1px solid transparent; 30 | } 31 | 32 | .introjs-button span { 33 | font-size: 14px; 34 | } 35 | 36 | .introjs-arrow { 37 | border: 10px solid #fff; 38 | } 39 | .introjs-arrow.top, .introjs-arrow.top-middle, .introjs-arrow.top-right { 40 | border-color: transparent transparent rgba(000, 0, 0, 0.5); 41 | top: -20px; 42 | left: 20px; 43 | } 44 | .introjs-arrow.bottom, .introjs-arrow.bottom-middle, .introjs-arrow.bottom-right { 45 | border-color: rgba(000, 0, 0, 0.5) transparent transparent; 46 | bottom: -20px; 47 | left: 20px; 48 | } 49 | .introjs-arrow.left, .introjs-arrow.right { 50 | top: 20px; 51 | } 52 | .introjs-arrow.left-bottom, .introjs-arrow.right-bottom { 53 | bottom: 20px; 54 | } 55 | 56 | .introjs-arrow.left, .introjs-arrow.left-bottom { 57 | left: -20px; 58 | border-color: rgba(000, 0, 0, 0.5) transparent transparent transparent; 59 | } 60 | .introjs-arrow.right, .introjs-arrow.right-bottom { 61 | right: -20px; 62 | border-color: transparent transparent transparent rgba(000, 0, 0, 0.5); 63 | } 64 | -------------------------------------------------------------------------------- /app/app/sass/partials/_labels.scss: -------------------------------------------------------------------------------- 1 | .label { 2 | &.label-danger { 3 | background-color: $red; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /app/app/sass/partials/_lists.scss: -------------------------------------------------------------------------------- 1 | .list-group{ 2 | .list-group-item { 3 | 4 | &:first-child { 5 | border-top-left-radius: 0; 6 | border-top-right-radius: 0; 7 | }; 8 | 9 | &:last-child { 10 | border-bottom-right-radius: 0; 11 | border-bottom-left-radius: 0; 12 | } 13 | 14 | &.active { 15 | background-color: $blue; 16 | border-color: $blue; 17 | } 18 | 19 | } 20 | } 21 | 22 | .list-img, 23 | .list-text { 24 | display: inline-block; 25 | &+ul { 26 | margin-left: 10px; 27 | } 28 | } 29 | 30 | .list-img { 31 | li { 32 | padding: 0; 33 | img { 34 | height: 25px; 35 | width: 25px; 36 | } 37 | } 38 | } 39 | 40 | .list-text { 41 | li { 42 | padding: 0; 43 | &+li:before { 44 | content: ','; 45 | padding-right: 5px; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/app/sass/partials/_loading-panel.scss: -------------------------------------------------------------------------------- 1 | .loading-panel { 2 | position: absolute; 3 | top: 0; 4 | left: 0; 5 | width: 100%; 6 | background: #fff; 7 | text-align: center; 8 | padding: 50px 0; 9 | } 10 | -------------------------------------------------------------------------------- /app/app/sass/partials/_loading.scss: -------------------------------------------------------------------------------- 1 | .loading{ 2 | position: absolute; 3 | top: 0; 4 | bottom: 0; 5 | left: 0; 6 | right: 0; 7 | background-color: $gray-light-35; 8 | color: $gray; 9 | z-index: 10001; 10 | display:-webkit-flex; 11 | display:flex; 12 | -webkit-justify-content:center; 13 | justify-content:center; 14 | -webkit-align-items:center; 15 | align-items:center; 16 | 17 | > div { 18 | width: 150px; 19 | text-align: center; 20 | > p { 21 | margin: 20px 0; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/app/sass/partials/_margin.scss: -------------------------------------------------------------------------------- 1 | .margin-top-0 { 2 | margin-top: 0px; 3 | } 4 | .margin-top-5 { 5 | margin-top: 5px; 6 | } 7 | .margin-top-10 { 8 | margin-top: 10px; 9 | } 10 | .margin-top-20 { 11 | margin-top: 20px; 12 | } 13 | .margin-top-30 { 14 | margin-top: 30px; 15 | } 16 | .margin-top-40 { 17 | margin-top: 40px; 18 | } 19 | .margin-top-50 { 20 | margin-top: 50px; 21 | } 22 | 23 | .margin-right-0 { 24 | margin-right: 0px; 25 | } 26 | .margin-right-5 { 27 | margin-right: 5px; 28 | } 29 | .margin-right-10 { 30 | margin-right: 10px; 31 | } 32 | .margin-right-20 { 33 | margin-right: 20px; 34 | } 35 | .margin-right-30 { 36 | margin-right: 30px; 37 | } 38 | .margin-right-40 { 39 | margin-right: 40px; 40 | } 41 | .margin-right-50 { 42 | margin-right: 50px; 43 | } 44 | 45 | .margin-bottom-0 { 46 | margin-bottom: 0px; 47 | } 48 | .margin-bottom-5 { 49 | margin-bottom: 5px; 50 | } 51 | .margin-bottom-10 { 52 | margin-bottom: 10px; 53 | } 54 | .margin-bottom-20 { 55 | margin-bottom: 20px; 56 | } 57 | .margin-bottom-30 { 58 | margin-bottom: 30px; 59 | } 60 | .margin-bottom-40 { 61 | margin-bottom: 40px; 62 | } 63 | .margin-bottom-50 { 64 | margin-bottom: 50px; 65 | } 66 | 67 | .margin-left-0 { 68 | margin-left: 0px; 69 | } 70 | .margin-left-5 { 71 | margin-left: 5px; 72 | } 73 | .margin-left-10 { 74 | margin-left: 10px; 75 | } 76 | .margin-left-20 { 77 | margin-left: 20px; 78 | } 79 | .margin-left-30 { 80 | margin-left: 30px; 81 | } 82 | .margin-left-40 { 83 | margin-left: 40px; 84 | } 85 | .margin-left-50 { 86 | margin-left: 50px; 87 | } 88 | -------------------------------------------------------------------------------- /app/app/sass/partials/_media.scss: -------------------------------------------------------------------------------- 1 | @media (max-width: 768px) { 2 | nav{ 3 | left:0 !important; 4 | background-color: $white; 5 | border-right: 1px solid $gray-light-30; 6 | } 7 | nav.min{ 8 | left:-230px !important; 9 | } 10 | section{ 11 | left: 0 !important; 12 | } 13 | section.min{ 14 | left: 0 !important; 15 | } 16 | .error{ 17 | max-width: 300px !important; 18 | 19 | span { 20 | top: 15% !important; 21 | left: 36% !important; 22 | font-size: 5em !important 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/app/sass/partials/_modals.scss: -------------------------------------------------------------------------------- 1 | .modal{ 2 | .modal-dialog{ 3 | //margin: 80px auto; 4 | 5 | .modal-content{ 6 | border-radius: 0; 7 | 8 | .modal-body { 9 | min-height: 200px 10 | } 11 | 12 | .modal-footer { 13 | // .btn-delete { 14 | // float: left; 15 | // margin-right: 20px; 16 | // } 17 | small { 18 | margin-left: 10px; 19 | line-height: 33px; 20 | } 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/app/sass/partials/_nav.scss: -------------------------------------------------------------------------------- 1 | nav { 2 | position: fixed; 3 | top: 60px; 4 | bottom: 0; 5 | left: 0; 6 | width: 230px; 7 | overflow-x: hidden; 8 | overflow-y: scroll; 9 | z-index: 998; 10 | @include transition(all .2s ease); 11 | 12 | &::-webkit-scrollbar { 13 | width: 0; 14 | } 15 | 16 | &.min { 17 | width: 60px; 18 | @include transition(all .2s ease); 19 | 20 | ul.nav li a .text-capitalize{ 21 | margin-left: 20px; 22 | } 23 | } 24 | 25 | ul.nav{ 26 | margin-bottom: 0; 27 | width: 230px; 28 | padding-top: 20px; 29 | //@include transition(all .2s ease); 30 | 31 | li{ 32 | margin-top: 0 !important; 33 | 34 | 35 | a { 36 | color: $gray-dark-10; 37 | border-radius: 0; 38 | 39 | &.active, 40 | &:hover, 41 | &:focus { 42 | background-color: transparent; 43 | } 44 | 45 | &:hover .fa-stack .fa-circle{ 46 | color: $gray-light-30; 47 | } 48 | 49 | .fa-stack { 50 | @include transition(all .2s ease); 51 | .fa-circle { 52 | color: transparent; 53 | } 54 | } 55 | 56 | .text-capitalize{ 57 | font-size: 14px; 58 | margin-left: 5px; 59 | @include transition(all .2s ease); 60 | } 61 | 62 | } 63 | 64 | &.active a, 65 | &.active a:hover, 66 | &.active a:focus{ 67 | background-color: transparent; 68 | color: $gray-dark-10; 69 | .fa-stack .fa-circle { 70 | color: $orange; 71 | }; 72 | .fa-stack .fa-stack-1x { 73 | color: $gray-light-35; 74 | } 75 | } 76 | } 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /app/app/sass/partials/_normalize.scss: -------------------------------------------------------------------------------- 1 | /* 2 | |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3 | | html & body 4 | |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 | */ 6 | html, 7 | body { 8 | height: 100%; 9 | //overflow: hidden; 10 | font-family: $font; 11 | color: $gray-dark-30; 12 | } 13 | body { 14 | background-color: $gray-light-35; 15 | } 16 | /* 17 | |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 18 | | a 19 | |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 20 | */ 21 | a { 22 | color: $gray-dark-10; 23 | //@include transition(all .2s ease); 24 | 25 | &:hover, &:focus{ 26 | color: $blue; 27 | text-decoration: none; 28 | } 29 | } 30 | /** 31 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 32 | * text-color 33 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 34 | */ 35 | .text-success{ 36 | color: $green; 37 | } 38 | .text-primary{ 39 | color: $blue; 40 | } 41 | .text-danger{ 42 | color: $red; 43 | } 44 | .text-warning{ 45 | color: $yellow; 46 | } 47 | /** 48 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 49 | * bg-color 50 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 51 | */ 52 | .bg-success{ 53 | background-color: $green; 54 | } 55 | .bg-primary{ 56 | background-color: $blue; 57 | } 58 | .bg-danger{ 59 | background-color: $red; 60 | } 61 | .bg-warning{ 62 | background-color: $yellow; 63 | } 64 | // .bg-primary, .bg-success, .bg-info, .bg-warning, .bg-danger{ 65 | // padding: 15px; 66 | // } 67 | 68 | 69 | /** 70 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 71 | * Avatar 72 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 73 | */ 74 | .avatar-sm { 75 | width: 25px; 76 | height: 25px; 77 | } 78 | 79 | .avatar-md { 80 | width: 33px; 81 | height: 33px; 82 | } 83 | -------------------------------------------------------------------------------- /app/app/sass/partials/_pagination.scss: -------------------------------------------------------------------------------- 1 | .pagination{ 2 | margin: 0; 3 | 4 | > .active { 5 | > a { 6 | background-color: $blue; 7 | border-color: $blue; 8 | &:hover, 9 | &:focus { 10 | background-color: $blue-dark-10; 11 | border-color: $blue-dark-10; 12 | } 13 | } 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /app/app/sass/partials/_panels.scss: -------------------------------------------------------------------------------- 1 | .page{ 2 | .panel{ 3 | border-radius: 0; 4 | border-top: 1px solid $gray-light-30; 5 | @include box-shadow(0 1px 2px 0 rgba($gray, 0.5)); 6 | 7 | .panel-heading { 8 | border-radius: 0; 9 | border-bottom: 1px solid $gray-light-30; 10 | 11 | &.no-border { 12 | border-bottom: 1px solid transparent; 13 | } 14 | 15 | h3{ 16 | font-weight: lighter; 17 | font-size: 16px; 18 | color: $gray-dark-30; 19 | } 20 | .btn-group{ 21 | } 22 | } 23 | 24 | .panel-body { 25 | padding: 20px; 26 | } 27 | 28 | .panel-footer{ 29 | background-color: $white; 30 | border-top: 1px solid transparent; 31 | } 32 | 33 | &.min-box { 34 | padding: 10px; 35 | .fa-stack{ 36 | margin-right: 10px; 37 | float: left; 38 | } 39 | .min-box-text{ 40 | display: inline; 41 | vertical-align: top; 42 | 43 | h2{ 44 | margin: 15px 0 5px 0; 45 | } 46 | } 47 | } 48 | 49 | &.panel-box { 50 | display: table; 51 | //table-layout: fixed; 52 | width: 100%; 53 | height: 100%; 54 | text-align: center; 55 | //border: none; 56 | 57 | .panel-item { 58 | display: table-cell; 59 | padding: 25px; 60 | width: 1%; 61 | vertical-align: top; 62 | 63 | p { 64 | margin: 0; 65 | 66 | &.lead { 67 | font-size: 32px; 68 | line-height: 32px; 69 | font-weight: bold; 70 | } 71 | } 72 | } 73 | } 74 | } 75 | } 76 | 77 | /* 78 | |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 79 | | Sortable 80 | |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 81 | */ 82 | .sortable-placeholder { 83 | border: 2px dashed #CCC; 84 | background: none; 85 | } 86 | /*.sortable-dragging{ 87 | 88 | }*/ 89 | .sortable { 90 | .panel { 91 | .panel-heading{ 92 | cursor: move; 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /app/app/sass/partials/_section.scss: -------------------------------------------------------------------------------- 1 | section{ 2 | position: absolute; 3 | top: 60px; 4 | right: 0; 5 | bottom: 0; 6 | left: 230px; 7 | background: $gray-light-35; 8 | overflow-y: scroll; 9 | overflow-x: hidden; 10 | @include transition(all .2s ease); 11 | 12 | &.min{ 13 | left: 60px; 14 | } 15 | 16 | &::-webkit-scrollbar { 17 | width: 5px; 18 | } 19 | &::-webkit-scrollbar-thumb { 20 | background: $gray; 21 | } 22 | &::-webkit-scrollbar-thumb:window-inactive { 23 | background: rgba($black, 0.4); 24 | } 25 | 26 | .page > .row:first-child { 27 | margin-top: 20px; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/app/sass/partials/_tables.scss: -------------------------------------------------------------------------------- 1 | .table{ 2 | thead{ 3 | tr{ 4 | &.active{ 5 | td, th{ 6 | background-color: inherit; 7 | } 8 | } 9 | td, th{ 10 | &.active{ 11 | background-color: inherit; 12 | } 13 | } 14 | } 15 | } 16 | tbody{ 17 | tr{ 18 | position: relative; 19 | td{ 20 | &.avatar{ 21 | padding: 5px 8px; 22 | img{ 23 | width: 25px; 24 | height: 25px; 25 | } 26 | } 27 | &.btn-edit { 28 | position: absolute; 29 | border: none; 30 | right: 35px; 31 | padding: 0; 32 | margin: 2px; 33 | 34 | > div { 35 | background-color: #f5f5f5; 36 | @include opacity(0); 37 | //color: $gray; 38 | 39 | a:hover { 40 | color: $blue; 41 | } 42 | } 43 | } 44 | } 45 | &:hover .btn-edit > div { 46 | @include opacity(1); 47 | } 48 | &.selected{ 49 | background-color: $blue-light-10; 50 | color: $white; 51 | } 52 | } 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/app/sass/partials/_tabs.scss: -------------------------------------------------------------------------------- 1 | .nav-tabs, 2 | .nav-tabs.nav-justified { 3 | border-bottom-color: transparent; 4 | padding-bottom: 1px; 5 | 6 | &.submodules { 7 | margin-left: 15px; 8 | border-bottom: 1px solid $gray-light-30; 9 | 10 | a { 11 | padding: 20px 35px 10px; 12 | } 13 | } 14 | 15 | > li { 16 | 17 | > a, 18 | a:hover, 19 | a:focus { 20 | background-color: transparent; 21 | border-radius: 0; 22 | border-left: none; 23 | border-top: none; 24 | border-right: none; 25 | border-bottom: 4px solid transparent; 26 | margin-bottom: 0; 27 | 28 | &:hover, 29 | &:focus { 30 | 31 | color: $gray-dark-30; 32 | } 33 | } 34 | 35 | &.active { 36 | > a, 37 | a:hover, 38 | a:focus { 39 | background-color: transparent; 40 | border-radius: 0; 41 | border-left: none; 42 | border-top: none; 43 | border-right: none; 44 | border-bottom: 4px solid $blue; 45 | } 46 | } 47 | 48 | 49 | 50 | } 51 | 52 | } 53 | 54 | // responsive 55 | .nav-justified { 56 | > li { 57 | display: table-cell; 58 | width: 1%; 59 | } 60 | } 61 | 62 | .nav-center { 63 | text-align: center; 64 | 65 | .nav-tabs { 66 | display: inline-block; 67 | } 68 | } 69 | 70 | .tab-content { 71 | margin-top: 20px; 72 | } 73 | -------------------------------------------------------------------------------- /app/app/sass/partials/_tooltips.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3 | * Tooltips 4 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 | */ 6 | .tooltip-inner { 7 | padding: 5px 8px; 8 | border-radius: 0; 9 | } 10 | -------------------------------------------------------------------------------- /app/app/sass/partials/_tree.scss: -------------------------------------------------------------------------------- 1 | .angular-ui-tree-handle, 2 | .tree-node-content { 3 | background-color: $white; 4 | border: 1px solid $gray-light-30; 5 | padding: 10px; 6 | margin-bottom: 10px; 7 | font-weight: normal; 8 | 9 | .toggle { 10 | margin-right: 10px; 11 | } 12 | 13 | label { 14 | margin-left: 15px; 15 | } 16 | } 17 | .angular-ui-tree-placeholder { 18 | border: 2px dashed $gray-light-20; 19 | background-color: $gray-light-35 20 | } 21 | -------------------------------------------------------------------------------- /app/app/sass/partials/_variables.scss: -------------------------------------------------------------------------------- 1 | @import url(http://fonts.googleapis.com/css?family=Open+Sans:400,300); 2 | $font : 'Open Sans', sans-serif; 3 | 4 | $orange: #FAAB4C; // #FAAB4C 5 | $green: #11B587; // 0DB0B5 6 | $blue: #45AFDC; 7 | $red: #F26C55; 8 | $yellow: #FFC107; 9 | //$orange-dark: #FA6A31; 10 | $white: #FEFEFE; 11 | $black: #212121; 12 | $gray: #9E9E9E; 13 | 14 | $green-dark-10: darken($green, 10%); 15 | 16 | $blue-light-10: lighten($blue, 10%); 17 | $blue-light-20: lighten($blue, 20%); 18 | $blue-dark-10: darken($blue, 10%); 19 | $blue-dark-20: darken($blue, 20%); 20 | 21 | $gray-light-10: lighten($gray, 10%); 22 | $gray-light-20: lighten($gray, 20%); 23 | // Border 24 | $gray-light-30: lighten($gray, 30%); 25 | // Background 26 | $gray-light-35: lighten($gray, 35%); 27 | // Font 28 | $gray-dark-10: darken($gray, 10%); 29 | $gray-dark-30: darken($gray, 30%); 30 | -------------------------------------------------------------------------------- /app/app/sounds/ios_notification.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modulr/sails-angularjs/c99442dc9fa2402d71832fd44b793c009fdbebd9/app/app/sounds/ios_notification.mp3 -------------------------------------------------------------------------------- /app/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "modulr-app", 3 | "dependencies": { 4 | "jquery": "~2.1.4", 5 | "angular": "~1.5.0", 6 | "angular-animate": "~1.5.0", 7 | "angular-cookies": "~1.5.0", 8 | "angular-sanitize": "~1.5.0", 9 | "angular-translate": "~2.9.0", 10 | "angular-translate-loader-static-files": "~2.9.0", 11 | "angular-translate-storage-local": "~2.9.0", 12 | "angular-ui-router": "~0.2.13", 13 | "angularSails": "~0.12.1", 14 | "bootstrap": "~3.3.6", 15 | "animate.css": "~3.2.0", 16 | "moment": "~2.10.3", 17 | "angular-moment": "~0.10.1", 18 | "password-generator": "~2.0.2", 19 | "Chart.js": "~1.0.2", 20 | "angular-chart.js": "~0.8.8", 21 | "ng-tags-input": "~3.0.0", 22 | "ng-tasty": "^0.6.1", 23 | "angular-ui-tree": "~2.13.0", 24 | "smoke": "~3.1.0", 25 | "select2": "~4.0.1", 26 | "mdr-angular-select2": "~1.0.6", 27 | "mdr-angular-file": "~1.0.5", 28 | "sails.io.js": "~0.13.5", 29 | "deep-diff": "^0.3.4", 30 | "angular-eonasdan-datetimepicker": "^0.3.3", 31 | "magnific-popup": "^1.1.0", 32 | "font-awesome": "^4.6.3", 33 | "angular-intro.js": "^2.1.1" 34 | }, 35 | "overrides": { 36 | "bootstrap": { 37 | "main": [ 38 | "dist/css/bootstrap.css", 39 | "dist/js/bootstrap.js" 40 | ] 41 | }, 42 | "font-awesome": { 43 | "main": [ 44 | "css/font-awesome.css" 45 | ] 46 | }, 47 | "select2": { 48 | "main": [ 49 | "dist/css/select2.css", 50 | "dist/js/select2.js" 51 | ] 52 | }, 53 | "sails.io.js": { 54 | "main": "**/*.js", 55 | "ignore": true 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/config/env/development.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "APP_PORT": "3000", 3 | "API_URL": "http://localhost:1337", 4 | "STORAGE_URL": "storage" 5 | } 6 | -------------------------------------------------------------------------------- /app/config/env/production.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "APP_PORT": "3000", 3 | "API_URL": "http://localhost:1337", 4 | "STORAGE_URL": "storage" 5 | } 6 | -------------------------------------------------------------------------------- /app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "modulr-app", 3 | "scripts": { 4 | "test": "echo \"Error: no test specified\" && exit 1", 5 | "start": "gulp" 6 | }, 7 | "devDependencies": { 8 | "bower": "^1.7.7", 9 | "fs": "0.0.2", 10 | "gulp": "^3.9.1", 11 | "gulp-clean-css": "^2.0.12", 12 | "gulp-concat": "^2.6.0", 13 | "gulp-imagemin": "^2.4.0", 14 | "gulp-inject": "^3.0.0", 15 | "gulp-jsonmin": "^1.0.2", 16 | "gulp-load-plugins": "^1.2.4", 17 | "gulp-ng-annotate": "^2.0.0", 18 | "gulp-nodemon": "^2.1.0", 19 | "gulp-preprocess": "^2.0.0", 20 | "gulp-rename": "^1.2.2", 21 | "gulp-sass": "^2.2.0", 22 | "gulp-sourcemaps": "^1.6.0", 23 | "gulp-uglify": "^1.5.3", 24 | "main-bower-files": "^2.11.1", 25 | "vinyl-fs": "^2.4.3" 26 | }, 27 | "dependencies": { 28 | "express": "^4.14.0" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/server.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | 3 | var app = express(); 4 | 5 | var port = 3000; 6 | 7 | app.use(express.static(__dirname + '/public')); 8 | 9 | app.get('*', function(req, res, next) { 10 | res.sendFile('index.html', { root: __dirname + '/public' }); 11 | }); 12 | 13 | app.listen(port, function(err) { 14 | if (err) return console.log(err), process.exit(1); 15 | 16 | console.log('modulr app listen port ' + port); 17 | }); 18 | -------------------------------------------------------------------------------- /app/storage/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "modulr", 3 | "version": "1.0.0-beta.2", 4 | "description": "The Base for Developing any Project", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "install": "cd api && npm install && cd ../app && npm install && bower install", 9 | "start": "cd api && npm start ; cd ../app && npm start" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/modulr/modulr.git" 14 | }, 15 | "keywords": [ 16 | "framework", 17 | "erp", 18 | "opensource" 19 | ], 20 | "author": "modulr", 21 | "license": "MIT", 22 | "bugs": { 23 | "url": "https://github.com/modulr/modulr/issues" 24 | }, 25 | "homepage": "https://github.com/modulr/modulr#readme" 26 | } 27 | --------------------------------------------------------------------------------