Commit 806255a3 authored by Tuan Tuan LE's avatar Tuan Tuan LE

Bootstrap module

parents
{
"directory": "frontend/components"
}
\ No newline at end of file
{
"extends": "linagora-esn",
"rules": {
"arrow-parens": ["error", "as-needed"],
"no-console": ["error", { "allow": ["warn", "error"] }]
}
}
node_modules
frontend/components
.idea
*.log
package-lock.json
yarn.lock
8
\ No newline at end of file
'use strict';
/* eslint-disable no-process-env */
const timeGrunt = require('time-grunt');
module.exports = function(grunt) {
timeGrunt(grunt);
grunt.initConfig({
eslint: {
options: {
config: '.eslintrc'
},
quick: {
src: [],
options: {
quiet: true
}
},
all: {
src: ['*.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 %>']
}
},
i18n_checker: {
all: {
options: {
baseDir: __dirname,
dirs: [{
localeDir: 'backend/lib/i18n/locales',
templateSrc: [
'frontend/app/**/*.pug'
],
core: true
}],
verifyOptions: {
defaultLocale: 'en',
locales: ['en', 'fr', 'vi'],
rules: [
'all-keys-translated',
'all-locales-present',
'default-locale-translate',
'key-trimmed',
'no-duplicate-among-modules',
'no-duplicate-with-core',
'no-untranslated-key',
'valid-json-file'
]
}
}
}
},
puglint: {
all: {
options: {
config: {
disallowAttributeInterpolation: true,
disallowLegacyMixinCall: true,
validateExtensions: true,
validateIndentation: 2
}
},
src: [
'frontend/**/*.pug'
]
}
},
splitfiles: {
options: {
chunk: 1
},
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 || 5000
},
backend: {
options: {
files: ['test/unit-backend/all.js', grunt.option('test') || 'test/unit-backend/**/*.js']
}
}
},
karma: {
unit: {
configFile: './test/config/karma.conf.js',
browsers: ['PhantomJS']
}
}
});
grunt.loadTasks('tasks');
grunt.loadNpmTasks('@linagora/grunt-lint-pattern');
grunt.loadNpmTasks('@linagora/grunt-i18n-checker');
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-puglint');
grunt.registerTask('i18n', 'Check the translation files', ['i18n_checker']);
grunt.registerTask('pug-linter', 'Check the pug/jade files', ['puglint:all']);
grunt.registerTask('linters', 'Check code for lint', ['eslint:all', 'lint_pattern:all', 'lint_pattern:css', 'i18n', 'pug-linter']);
grunt.registerTask('linters-dev', 'Check changed files for lint', ['prepare-quick-lint', 'eslint:quick', 'lint_pattern:quick']);
grunt.registerTask('test-midway-backend', ['splitfiles:midway']);
grunt.registerTask('test-unit-backend', 'Test backend code', ['mochacli:backend']);
grunt.registerTask('test-unit-frontend', 'Test frontend code', ['karma:unit']);
grunt.registerTask('test', ['linters', 'test-unit-frontend', 'test-unit-backend', 'test-midway-backend']);
grunt.registerTask('default', ['test']);
};
# linagora.esn.most
Vietnam ministry of science and technology project
'use strict';
// arguments: dependencies
module.exports = function() {
// const model = require('./YOUR_MODEL')(dependencies);
return {
// model
};
};
'use strict';
module.exports = function(dependencies) {
const i18n = dependencies('i18n');
i18n.setDefaultConfiguration({ directory: __dirname + '/locales' });
return i18n;
};
{
"My sidebar" : "My sidebar"
}
{
"My sidebar" : "Ma barre latérale"
}
{
"My sidebar" : "Thanh bên của tôi"
}
'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/i18n')(dependencies, application);
require('./config/views')(dependencies, application);
return application;
};
'use strict';
module.exports = function(dependencies, application) {
var i18n = require('../../lib/i18n')(dependencies);
application.use(i18n.init);
};
'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": "linagora.esn.most",
"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"
],
"devDependencies": {
"angular": "1.3.20",
"angular-component": "linagora/angular-component#0.1.4",
"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-chai": "2.8.0"
}
}
(function() {
'use strict';
var MODULE_NAME = 'linagora.esn.most';
var MODULE_PREFIX = 'most';
angular.module(MODULE_NAME)
.config(mostApplicationMenu);
function mostApplicationMenu(dynamicDirectiveServiceProvider) {
var home = new dynamicDirectiveServiceProvider.DynamicDirective(true, MODULE_PREFIX + '-application-menu');
dynamicDirectiveServiceProvider.addInjection('esn-application-menu', home);
}
})();
@import './home/most-home';
(function() {
'use strict';
var MODULE_NAME = 'linagora.esn.most';
angular.module(MODULE_NAME, [
'ui.router',
'op.dynamicDirective',
'restangular'
]);
})();
(function() {
'use strict';
var MODULE_NAME = 'linagora.esn.most';
var MODULE_DIR_NAME = '/linagora.esn.most';
angular.module(MODULE_NAME)
.config(function($stateProvider) {
$stateProvider
.state('example', {
url: '/example',
views: {
'': {
templateUrl: MODULE_DIR_NAME + '/app/home/most-home.html'
},
'sidebar@example': {
templateUrl: MODULE_DIR_NAME + '/app/home/most-sidebar.html'
}
},
deepStateRedirect: {
default: 'example.home',
fn: function() {
return { state: 'example.home' };
}
}
})
.state('example.home', {
url: '/home',
controller: 'mostHomeController',
controllerAs: 'ctrl',
views: {
'main@example': {
templateUrl: MODULE_DIR_NAME + '/app/home/most-main.html'
}
}
});
});
})();
(function() {
'use strict';
var MODULE_NAME = 'linagora.esn.most';
angular.module(MODULE_NAME)
.directive('mostApplicationMenu', mostApplicationMenu);
function mostApplicationMenu(applicationMenuTemplateBuilder) {
var directive = {
restrict: 'E',
template: applicationMenuTemplateBuilder('/#/example', 'mdi-emoticon-happy', 'Most'),
replace: true
};
return directive;
}
})();
(function() {
'use strict';
var MODULE_NAME = 'linagora.esn.most';
var MODULE_DIR_NAME = '/linagora.esn.most';
angular.module(MODULE_NAME)
.factory('mostRestangular', mostRestangular);
function mostRestangular(Restangular) {
return Restangular.withConfig(function(RestangularConfigurer) {
RestangularConfigurer.setBaseUrl(MODULE_DIR_NAME + '/api');
RestangularConfigurer.setFullResponse(true);
});
}
})();
(function() {
'use strict';
var MODULE_NAME = 'linagora.esn.most';
angular.module(MODULE_NAME)
.controller('mostHomeController', mostHomeController);
function mostHomeController() {
this.message = 'Most home!';
}
})();
'use strict';
/* global chai: false */
var expect = chai.expect;
describe('the mostHomeController', function() {
var $rootScope, $scope, $controller;
beforeEach(function() {
angular.mock.module('linagora.esn.most');
angular.mock.inject(function(_$rootScope_, _$controller_) {
$rootScope = _$rootScope_;
$scope = $rootScope.$new();
$controller = _$controller_;
});
});
function initController() {
var bindings = {},
controller = $controller('mostHomeController',
{
$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('Most home!');
});
});
});
@most-sidebar-width: 25%;
.most-home {
.flex-shorthand(1);
position: relative;
top: 47px;
height: 70vh;
.most-main {
.most-main-content {
.flex-shorthand(1);
margin-left: 7px;
margin-right: 7px;
.most-module-card {
.flex-horizontal-centered;
padding: 5px 10px;
background: @m-white;
}
}
}
.most-sidebar {
height: 100%;
border-right: 1px solid lighten(@m-gray, 0%);
width: @most-sidebar-width;
margin-top: 15px;
.most-sidebar-content {
.flex-horizontal-centered;
}
}
}
.most-subheader-content {
.flex-horizontal-centered;
font-size: 1.2em;
color: @m-white;
}
@media(min-width: @screen-md-min) {
.most-home > .most-main {
margin-top: 15px;
}
}
.most-home
.col-md-3.most-sidebar.hidden-xs.ui-view(name='sidebar')
.col-xs-12.col-md-8.most-main.no-padding-xs.ui-view(name='main')
sub-header
most-subheader
.most-main-content
.most-module-card
h1 #{__('Most module')}
.most-sidebar-content
.card-header
h1 #{__('My sidebar')}
(function() {
'use strict';
var MODULE_NAME = 'linagora.esn.most';
var MODULE_DIR_NAME = '/linagora.esn.most';
angular.module(MODULE_NAME)
.component('mostSubheader', mostSubheader());
function mostSubheader() {
var component = {
templateUrl: MODULE_DIR_NAME + '/app/home/most-subheader.html'
};
return component;
}
})();
extends /modules/subheader/responsive-subheader.pug
block left
most-burger-button.hidden-md
span.most-subheader-content
| #{__('Most module')}
block right
'use strict';
var MODULE_NAME = 'linagora.esn.most';
var MODULE_DIR_NAME = '/linagora.esn.most';
angular.module(MODULE_NAME)
.component('mostBurgerButton', {
templateUrl: MODULE_DIR_NAME + '/app/subheader/most-burger-button.html'
});
.most-button(contextual-sidebar, data-content-template="/linagora.esn.most/app/home/most-sidebar.html")
i.mdi.mdi-menu
'use strict';
var MODULE_NAME = 'linagora.esn.most';
var MODULE_DIR_NAME = '/linagora.esn.most';
angular.module(MODULE_NAME)
.component('mostSubheaderButton', {
templateUrl: MODULE_DIR_NAME + '/app/subheader/most-subheader-button.html',
bindings: {
mostDisabled: '<?',
mostClick: '&?',
mostIconClass: '@?',
mostIconText: '@?',
mostIconPosition: '@?'
},
controllerAs: 'ctrl'
});
button.btn.btn-link.most-button(ng-click= "ctrl.mostClick()", ng-disabled= "ctrl.mostDisabled", ng-switch = "ctrl.mostIconPosition")
.most-button-icon-and-text(ng-switch-when= "right")
span {{ ctrl.mostIconText | translate }}
i.mdi(ng-class= "ctrl.mostIconClass")
.most-button-icon-and-text(ng-switch-default)
i.mdi(ng-class= "ctrl.mostIconClass")
span {{ ctrl.mostIconText | translate }}
.most-button {
.flex-vertical-centered;
.clickable;
text-transform: uppercase;
color: @m-white;
font-size: 1.1em;
font-weight: 500;
text-align: left;
.most-button-icon-and-text {
.flex-vertical-centered;
span {
margin-right: 5px;
margin-left: 5px;
}
}
}
'use strict';
const AwesomeModule = require('awesome-module');
const Dependency = AwesomeModule.AwesomeModuleDependency;
const path = require(