Commit 9c13e440 authored by Abdulkader BENCHI's avatar Abdulkader BENCHI

bootstrap the awesome seed module

parents
{
"directory": "frontend/components"
}
\ No newline at end of file
{
"extends": "linagora-esn",
"rules": {
"consistent-this": ["warn", "self"],
"no-unused-vars": ["error", { "vars": "all", "args": "after-used" }],
"no-console": ["error", { "allow": ["warn", "error"] }],
"no-process-env": "off",
"arrow-parens": ["error", "as-needed"]
}
}
\ No newline at end of file
node_modules
frontend/components
.idea
*.log
'use strict';
module.exports = function(grunt) {
const CI = grunt.option('ci');
let KARMA_REPORTERS = (grunt.option('reporter') || '').split(',').filter(Boolean);
if (!KARMA_REPORTERS.length) {
KARMA_REPORTERS = CI ? ['spec', 'coverage'] : ['dots'];
}
grunt.initConfig({
concat: {
options: {
separator: ';'
}
},
splitfiles: {
options: {
chunk: 10
},
backend: {
options: {
common: ['test/unit-backend/all.js'],
target: 'mochacli:backend'
},
files: {
src: ['test/unit-backend/**/*.js']
}
},
midway: {
options: {
common: ['test/midway-backend/all.js'],
target: 'mochacli:midway'
},
files: {
src: ['test/midway-backend/**/*.js']
}
}
},
mochacli: {
options: {
require: ['chai', 'mockery'],
reporter: 'spec',
timeout: process.env.TEST_TIMEOUT || 20000,
env: {
ESN_CUSTOM_TEMPLATES_FOLDER: 'testscustom'
}
},
backend: {
options: {
files: ['test/unit-backend/all.js', grunt.option('test') || 'test/unit-backend/**/*.js']
}
},
midway: {
options: {
files: ['test/midway-backend/all.js', grunt.option('test') || 'test/midway-backend/**/*.js']
}
}
},
karma: {
unit: {
configFile: './test/config/karma.conf.js',
browsers: ['PhantomJS'],
reporters: KARMA_REPORTERS
},
all: {
configFile: './test/config/karma.conf.js',
browsers: ['PhantomJS', 'Firefox', 'Chrome'],
reporters: KARMA_REPORTERS
}
}
});
grunt.loadNpmTasks('grunt-shell');
grunt.loadNpmTasks('grunt-mocha-cli');
grunt.loadNpmTasks('grunt-karma');
grunt.loadTasks('tasks');
grunt.registerTask('test-unit-backend', 'run the backend unit tests (to be used with .only)', ['splitfiles:backend']);
grunt.registerTask('test-midway-backend', 'run midway tests (to be used with .only)', ['splitfiles:midway']);
grunt.registerTask('test-backend', 'run both the unit & midway tests', ['test-unit-backend', 'test-midway-backend']);
grunt.registerTask('test-frontend', 'run the FrontEnd tests', ['karma:unit']);
grunt.registerTask('test-frontend-all', 'run the FrontEnd tests on all possible browsers', ['karma:all']);
grunt.registerTask('test', ['linters', 'test-backend', 'test-midway-backend']);
grunt.registerTask('default', ['test']);
};
'use strict';
const conf_path = './test/config/';
const servers = require(conf_path + 'servers-conf');
const GruntfileUtils = require('./tasks/utils/Gruntfile-utils');
const timeGrunt = require('time-grunt');
module.exports = function(grunt) {
timeGrunt(grunt);
const gruntfileUtils = new GruntfileUtils(grunt, servers);
const runGrunt = gruntfileUtils.runGrunt();
const shell = gruntfileUtils.shell();
const command = gruntfileUtils.command();
grunt.initConfig({
eslint: {
options: {
config: '.eslintrc'
},
quick: {
src: [],
options: {
quiet: true
}
},
all: {
src: ['Gruntfile.js', 'Gruntfile-tests.js', 'tasks/**/*.js', 'test/**/*.js', 'test/**/**/*.js', 'backend/**/*.js', 'frontend/app/**/*.js']
}
},
lint_pattern: {
options: {
rules: [
{ pattern: /(describe|it)\.only/, message: 'Must not use .only in tests' }
]
},
all: {
src: ['<%= eslint.all.src %>']
},
css: {
options: {
rules: [
{ pattern: /important;(\s*$|(?=\s+[^\/]))/, message: 'CSS important rules only allowed with explanatory comment' }
]
},
src: [
'frontend/app/**/*.less'
]
},
quick: {
src: ['<%= eslint.quick.src %>']
}
},
shell: {
mongo: shell.newShell(command.mongo(false), new RegExp('connections on port ' + servers.mongodb.port), 'MongoDB server is started.'),
redis: shell.newShell(command.redis, /on port/, 'Redis server is started')
},
run_grunt: {
midway_backend: runGrunt.newProcess(['test-midway-backend']),
unit_backend: runGrunt.newProcess(['test-unit-backend']),
unit_frontend: runGrunt.newProcess(['test-frontend'])
}
});
grunt.loadTasks('tasks');
grunt.loadNpmTasks('grunt-lint-pattern');
grunt.loadNpmTasks('grunt-eslint');
grunt.loadNpmTasks('grunt-mocha-cli');
grunt.loadNpmTasks('grunt-karma');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-shell');
grunt.loadNpmTasks('grunt-shell-spawn');
grunt.loadNpmTasks('grunt-continue');
grunt.loadNpmTasks('grunt-run-grunt');
grunt.loadNpmTasks('grunt-eslint');
grunt.loadNpmTasks('grunt-wait-server');
grunt.registerTask('linters', 'Check code for lint', ['eslint:all', 'lint_pattern:all', 'lint_pattern:css']);
grunt.registerTask('linters-dev', 'Check changed files for lint', ['prepare-quick-lint', 'eslint:quick', 'lint_pattern:quick']);
grunt.registerTask('spawn-servers', 'spawn servers', ['shell:mongo', 'shell:redis']);
grunt.registerTask('kill-servers', 'kill servers', ['shell:mongo:kill', 'shell:redis:kill']);
grunt.registerTask('setup-environment', 'create temp folders and files for tests', gruntfileUtils.setupEnvironment());
grunt.registerTask('clean-environment', 'remove temp folder for tests', gruntfileUtils.cleanEnvironment());
grunt.registerTask('setup-servers', ['spawn-servers', 'continue:on']);
grunt.registerTask('test-midway-backend', ['setup-environment', 'setup-servers', 'run_grunt:midway_backend', 'kill-servers', 'clean-environment']);
grunt.registerTask('test-unit-backend', 'Test backend code', ['run_grunt:unit_backend']);
grunt.registerTask('test-unit-frontend', 'Test frontend code', ['run_grunt:unit_frontend']);
grunt.registerTask('test', ['linters', 'test-unit-frontend', 'test-unit-backend', 'test-midway-backend']);
grunt.registerTask('default', ['test']);
};
# awesome.module.seed
Awesome.module.seed component for OpenPaaS ESN.
## Install
*Note: The following instructions assumes that you have already installed OpenPaaS ESN in the path referenced by $ESN below.*
While waiting for a npm-based dependency injection handler, you have to install the module in OpenPaaS ESN like this:
**1. Clone Awesome.module.seed**
```
git clone ssh://git@ci.open-paas.org:7999/om/awesome.module.seed.git
```
**2. Install it in OpenPaaS**
There is two way to install the model in OpenPaaS, so choose one of them:
- A. _Using symbolic links_
The modules must be available in the `$ESN/modules` folder:
```
cd $ESN/modules
ln -s path_to_module/awesome.module.seed
```
- B. _Using npm link_
Go inside the module repository:
```
npm link
```
Go inside OpenPaaS ESN repository:
```
cd $ESN
npm link awesome.module.seed
npm install
```
**2. Enable the module in the OpenPaaS ESN configuration file**
You must add the module in the modules section in `$ESN/config/default.NODE_ENV.json`. NODE_ENV is the environment variable used to define if the node application is running in 'production' or in 'development' (the default environment is 'development').
Copy the 'modules' array from `$ESN/config/default.json` into `$ESN/config/default.NODE_ENV.json` (`$ESN/config/default.development.json` or `$ESN/config/default.production.json`) and add the module name:
```
"modules": [
"linagora.esn.core.webserver",
"linagora.esn.core.wsserver",
"awesome.module.seed"
],
```
## Run
Once installed, you can start OpenPaaS ESN as usual. The **awesome module** is available in the application grid menu.
'use strict';
// arguments: dependencies
module.exports = function() {
// const model = require('./YOUR_MODEL')(dependencies);
return {
// model
};
};
'use strict';
module.exports = function(dependencies) {
const models = require('./db')(dependencies);
return {
models
};
};
'use strict';
module.exports = function(dependencies, lib, router) {
const authorizationMW = dependencies('authorizationMW');
const exampleController = require('../controllers/example')(dependencies, lib);
router.get('/example', authorizationMW.requiresAPILogin, exampleController.example);
};
'use strict';
const express = require('express');
module.exports = function(dependencies, lib) {
const router = express.Router();
require('./example')(dependencies, lib, router);
return router;
};
'use strict';
const express = require('express');
// This is you own express application
module.exports = function(dependencies) {
const application = express();
// Every express new configuration are appended here.
// This needs to be initialized before the body parser
require('./config/views')(dependencies, application);
return application;
};
'use strict';
const express = require('express');
const FRONTEND_PATH = require('../constants').FRONTEND_PATH;
const CORE_FRONTEND_PATH = require('../constants').CORE_FRONTEND_PATH;
module.exports = function(dependencies, application) {
application.use(express.static(FRONTEND_PATH));
application.set('views', FRONTEND_PATH + '/app');
application.get('/app/*', function(req, res) {
const templateName = req.params[0].replace(/\.html$/, '');
res.render(templateName, { basedir: CORE_FRONTEND_PATH + '/views' });
});
};
'use strict';
const path = require('path');
module.exports.FRONTEND_PATH = path.normalize(__dirname + '/../../frontend');
module.exports.CORE_FRONTEND_PATH = path.normalize(path.dirname(require.main.filename) + '/frontend');
'use strict';
// arguments: dependencies, lib
module.exports = function() {
function example(req, res) {
return res.status(200).json({ message: 'controller example' });
}
return {
example
};
};
'use strict';
module.exports = {
// define helpers that are shared by webserver file
// example:
// createErrorMessage: function(error, errDetail) {
// return {
// error: {
// code: 500,
// message: errDetail || 'Server Error',
// details: error.message
// }
// };
// }
};
'use strict';
//arguments: dependencies, lib
module.exports = function() {
// arguments: req, res, next, clientId
function example(req, res) {
return res.status(200).json({ message: 'middleware example' });
}
return {
example
};
};
{
"name": "awesome.module.seed",
"main": "index.js",
"version": "0.0.1",
"authors": [
"Linagora Folks <openpaas@linagora.com>"
],
"description": "OpenPaaS generic module template",
"keywords": [
"safe",
"openpaas",
"collaboration",
"linagora"
],
"license": "AGPLv3",
"homepage": "https://open-paas.org/",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"frontend/components",
"test",
"tests"
],
"dependencies": {},
"devDependencies": {
"angular": "1.3.20",
"angular-component": "https://github.com/toddmotto/angular-component.git#~0.1.2",
"angular-mocks": "1.3.20",
"angular-translate": "2.11.0",
"angular-translate-loader-static-files": "2.11.0",
"angular-ui-router": "0.2.18",
"chai": "3.0.0",
"dynamic-directive": "2.0.0",
"jquery": "2.1.1",
"restangular": "1.3.1",
"sinon-1.15.4": "http://sinonjs.org/releases/sinon-1.15.4.js",
"sinon-chai": "2.8.0"
}
}
(function() {
'use strict';
var MODULE_NAME = 'awesome.module.seed';
angular.module(MODULE_NAME)
.controller('seedHomeController', seedHomeController);
function seedHomeController() {
this.message = 'Seed home!';
}
})();
'use strict';
/* global chai: false */
var expect = chai.expect;
describe('the seedHomeController', function() {
var $rootScope, $scope, $controller;
beforeEach(function() {
angular.mock.module('awesome.module.seed');
angular.mock.inject(function(_$rootScope_, _$controller_) {
$rootScope = _$rootScope_;
$scope = $rootScope.$new();
$controller = _$controller_;
});
});
function initController() {
var bindings = {},
controller = $controller('seedHomeController',
{
$scope: $scope
},
bindings);
$scope.$digest();
return controller;
}
describe('the initialization', function() {
it('should set $scope.message on init', function() {
var ctrl = initController();
expect(ctrl.message).to.equal('Seed home!');
});
});
});
.seed-home
.col-md-3.seed-sidebar.hidden-xs.ui-view(name='sidebar')
.col-xs-12.col-md-8.seed-main.no-padding-xs.ui-view(name='main')
@seed-sidebar-width: 25%;
.seed-home {
.flex-shorthand(1);
position: relative;
top: 47px;
height: 70vh;
.seed-main {
.seed-main-content {
.flex-shorthand(1);
margin-left: 7px;
margin-right: 7px;
.seed-module-card {
.flex-horizontal-centered;
padding: 5px 10px;
background: @m-white;
box-shadow: 0 1px 1px @m-black-fade-15;
}
}
}
.seed-sidebar {
height: 100%;
border-right: 1px solid lighten(@m-gray, 0%);
width: @seed-sidebar-width;
margin-top: 15px;
.seed-sidebar-content {
.flex-horizontal-centered;
}
}
}
.seed-subheader-content {
.flex-horizontal-centered;
font-size: 1.2em;
color: @m-white;
}
@media(min-width: @screen-md-min) {
.seed-home > .seed-main {
margin-top: 15px;
}
}
sub-header
seed-subheader
.seed-main-content
.seed-module-card
h1 {{ 'Seed module' | translate }}
.seed-sidebar-content
.card-header
h1 {{ 'My sidebar' | translate }}
(function() {
'use strict';
var MODULE_NAME = 'awesome.module.seed';
var MODULE_DIR_NAME = '/awesome.module.seed';
angular.module(MODULE_NAME)
.component('seedSubheader', seedSubheader());
function seedSubheader() {
var component = {
templateUrl: MODULE_DIR_NAME + '/app/home/seed-subheader.html'
};
return component;
}
})();
extends /modules/subheader/responsive-subheader
block left
seed-burger-button.hidden-md
span.seed-subheader-content
| {{ 'Seed Module' | translate }}
block right
{
"Seed module" : "Seed module",
"My sidebar" : "My sidebar"
}
{
"Seed module" : "Le module seed",
"My sidebar" : "Ma barre latérale"
}
(function() {
'use strict';
var MODULE_NAME = 'awesome.module.seed';
angular.module(MODULE_NAME)
.directive('seedApplicationMenu', seedApplicationMenu);
function seedApplicationMenu(applicationMenuTemplateBuilder) {
var directive = {
restrict: 'E',
template: applicationMenuTemplateBuilder('/#/example', 'mdi-emoticon-happy', 'Seed'),
replace: true
};
return directive;
}
})();
/* define the common LESS variable
example:*/
@m-black-fade-15: fade(@m-black, 15%);
(function() {
'use strict';
var MODULE_NAME = 'awesome.module.seed';
var MODULE_PREFIX = 'seed';
angular.module(MODULE_NAME)
.config(seedApplicationMenu)
.config(translateProviderConfigure);
////////////////
function seedApplicationMenu(dynamicDirectiveServiceProvider) {
var home = new dynamicDirectiveServiceProvider.DynamicDirective(true, MODULE_PREFIX + '-application-menu');
dynamicDirectiveServiceProvider.addInjection('esn-application-menu', home);
}
function translateProviderConfigure($translateProvider) {
$translateProvider.useStaticFilesLoader({
files: [{
prefix: './' + MODULE_NAME + '/app/locales/web-',
suffix: '.json'
}]
});
$translateProvider.preferredLanguage('fr');
$translateProvider.useSanitizeValueStrategy('escape');
}
})();
(function() {
'use strict';
var MODULE_NAME = 'awesome.module.seed';
angular.module(MODULE_NAME, [
'ui.router',
'op.dynamicDirective',
'restangular',
'pascalprecht.translate'
]);
})();
(function() {
'use strict';
var MODULE_NAME = 'awesome.module.seed';
var MODULE_DIR_NAME = '/awesome.module.seed';
angular.module(MODULE_NAME)
.config(function($stateProvider) {
$stateProvider
.state('example', {
url: '/example',
views: {
'': {
templateUrl: MODULE_DIR_NAME + '/app/home/seed-home.html'
},
'sidebar@example': {
templateUrl: MODULE_DIR_NAME + '/app/home/seed-sidebar.html'
}
},
deepStateRedirect: {
default: 'example.home',
fn: function() {
return { state: 'example.home' };
}
}
})
.state('example.home', {
url: '/home',
controller: 'seedHomeController',
controllerAs: 'ctrl',
views: {