diff --git a/bower.json b/bower.json
index 73df375a6a..7c4b7aa8ba 100644
--- a/bower.json
+++ b/bower.json
@@ -1,46 +1,46 @@
{
- "name": "Phraseanet",
- "version": "3.9.0",
- "dependencies": {
- "bootstrap": "2.3.2",
- "jquery": "~1.8.3",
- "jquery-ui": "~1.10.0",
- "jquery-mobile-bower": "~1.3.0",
- "underscore": "~1.4.4",
- "font-awesome": "~3.0.2",
- "modernizr": "~2.6.2",
- "normalize-css": "~2.1.0",
- "json2": "latest",
- "humane-js": "~3.0.6",
- "jquery-file-upload": "~8.3.2",
- "blueimp-load-image": "latest",
- "requirejs": "~2.1",
- "backbone-amd": "~1.0",
- "underscore-amd": "~1.4",
- "i18next": "~1.6",
- "bootstrap-multiselect": "v0.9",
- "zxcvbn": "https://github.com/lowe/zxcvbn.git",
- "geonames-server-jquery-plugin": "~0.2",
- "swfobject": "latest",
- "tinymce": "~4.0",
- "jquery-galleria": "1.2.9",
- "jquery.cookie": "~1.4",
- "autobahn": "http://autobahn.s3.amazonaws.com/js/autobahn.min.js",
- "when": "~2.7.0",
- "jquery.treeview": "1.4.1",
- "fancytree": "~2.7",
- "joyride": "https://github.com/zurb/joyride/archive/v2.0.0.zip"
- },
- "devDependencies": {
- "mocha": "latest",
- "sinonjs": "~1.7.0",
- "chai": "~1.6",
- "squire": "~0",
- "sinon-chai": "~2.5",
- "qunit": "https://github.com/jquery/qunit.git#1.11.0",
- "js-fixtures": "https://github.com/badunk/js-fixtures/archive/master.zip"
- },
- "resolutions": {
- "jquery": "1.8.3"
- }
-}
\ No newline at end of file
+ "name": "Phraseanet",
+ "version": "3.9.0",
+ "dependencies": {
+ "jquery": "~1.8.3",
+ "jquery-ui": "~1.10.0",
+ "jquery-mobile-bower": "~1.3.0",
+ "underscore": "~1.4.4",
+ "font-awesome": "~3.0.2",
+ "modernizr": "~2.6.2",
+ "normalize-css": "~2.1.0",
+ "json2": "latest",
+ "humane-js": "~3.0.6",
+ "jquery-file-upload": "~8.3.2",
+ "blueimp-load-image": "latest",
+ "requirejs": "~2.1",
+ "backbone-amd": "~1.0",
+ "underscore-amd": "~1.4",
+ "i18next": "~1.6",
+ "bootstrap-multiselect": "v0.9",
+ "zxcvbn": "https://github.com/lowe/zxcvbn.git",
+ "geonames-server-jquery-plugin": "~0.2",
+ "swfobject": "latest",
+ "tinymce": "~4.0",
+ "jquery-galleria": "1.2.9",
+ "jquery.cookie": "~1.4",
+ "when": "~2.7.0",
+ "jquery.treeview": "1.4.1",
+ "fancytree": "~2.7",
+ "joyride": "https://github.com/zurb/joyride/archive/v2.0.0.zip",
+ "bootstrap-sass": "v2.3.2.2"
+ },
+ "devDependencies": {
+ "mocha": "latest",
+ "sinonjs": "~1.7.0",
+ "chai": "~1.6",
+ "squire": "~0",
+ "sinon-chai": "~2.5",
+ "qunit": "https://github.com/jquery/qunit.git#1.11.0",
+ "js-fixtures": "https://github.com/badunk/js-fixtures/archive/master.zip"
+ },
+ "resolutions": {
+ "jquery": "1.8.3",
+ "bootstrap-sass": "v2.3.2.2"
+ }
+}
diff --git a/gulpfile.js b/gulpfile.js
new file mode 100644
index 0000000000..985958edf8
--- /dev/null
+++ b/gulpfile.js
@@ -0,0 +1,260 @@
+// TODO: bower, tmp-assets
+// TODO: asset, www/assets
+var gulp = require('gulp');
+var rename = require('gulp-rename');
+var clean = require('gulp-clean');
+var concat = require('gulp-concat');
+var uglify = require('gulp-uglify');
+var qunit = require('gulp-qunit');
+var mochaPhantomjs = require('gulp-mocha-phantomjs');
+var cssmin = require('gulp-cssmin');
+var install = require('gulp-install');
+var sass = require('gulp-sass');
+var del = require('del');
+
+var paths = {
+ vendors: 'tmp-assets/',
+ dist: 'www/assets/'
+};
+
+
+gulp.task('mocha_phantomjs', function () {
+ return gulp.src('www/scripts/tests/*.html')
+ .pipe(mochaPhantomjs({
+ 'reporter': 'dot',
+ 'setting': [
+ 'loadImages=false'
+ ]
+ }));
+});
+
+gulp.task('qunit', function () {
+ return gulp.src('www/include/js/tests/*.html')
+ .pipe(qunit());
+});
+
+gulp.task('clean:vendor', function(done){
+ return del([paths.dist + '/**/*'], done);
+});
+
+
+var lib = require('bower-files')({
+ overrides: {
+ 'backbone-amd': {
+ main: ['./backbone.js', 'LICENSE']
+ },
+ 'font-awesome': {
+ main: ['css/*', 'font/*']
+ },
+ 'humane-js': {
+ main: ['humane.js', 'themes/libnotify.css']
+ },
+ 'jquery': {
+ main: 'jquery.js'
+ },
+ 'jquery.treeview': {
+ main: ['images/*',
+ 'jquery.treeview*']
+ },
+ 'jquery-mobile-bower': {
+ main: ['css/jquery.mobile-1.3.2.css', 'js/jquery.mobile-1.3.2.js']
+ },
+ 'json2': {
+ main: ['json2.js']
+ },
+ 'modernizr': {
+ main: 'modernizr.js'
+ },
+ 'tinymce': {
+ main: ['plugins/**',
+ 'skins/**',
+ 'themes/**',
+ '*.js',
+ 'changelog.txt',
+ 'license.txt']
+ },
+ 'underscore-amd': {
+ main:
+ 'underscore.js'
+ },
+ zxcvbn: {
+ main: [/* ignore, will be copied manually for legacy code compatibility */]
+ },
+ 'jquery-galleria': {
+ main: [/* ignore, will be copied manually for legacy code compatibility */]
+ },
+ 'bootstrap-multiselect': {
+ main: [/* ignore, will be copied manually for legacy code compatibility */]
+ },
+ 'fancytree': {
+ main: [/* ignore, will be copied manually for legacy code compatibility */]
+ },
+ 'jquery-ui': {
+ main: [/* ignore, will be copied manually for legacy code compatibility */]
+ },
+ 'swfobject': {
+ main: [/* ignore, will be copied manually for legacy code compatibility */]
+ },
+ 'blueimp-load-image': {
+ main: [/* ignore, will be copied manually for legacy code compatibility */]
+ },
+ 'jquery-file-upload': {
+ main: [/* ignore, will be copied manually for legacy code compatibility */]
+ },
+ 'i18next': {
+ main: [/* ignore, will be copied manually for legacy code compatibility */]
+ }
+ }
+});
+
+gulp.task('copy-dev-vendors', function(){
+ // @TODO copy:
+ // chai,js-fixtures, mocha sinon-chai, sinonjs, squire, qunit
+ gulp.src(paths.vendors + 'chai/chai.js')
+ .pipe(gulp.dest( paths.dist + 'chai/'));
+
+ gulp.src(paths.vendors + 'js-fixtures/fixtures.js')
+ .pipe(gulp.dest( paths.dist + 'js-fixtures/'));
+
+ gulp.src([paths.vendors + 'mocha/mocha.js', paths.vendors + 'mocha/mocha.css'])
+ .pipe(gulp.dest( paths.dist + 'mocha/'));
+
+ gulp.src(paths.vendors + 'sinon-chai/lib/sinon-chai.js')
+ .pipe(gulp.dest( paths.dist + 'sinon-chai/'));
+
+ gulp.src(paths.vendors + 'sinonjs/sinon.js')
+ .pipe(gulp.dest( paths.dist + 'sinonjs/'));
+
+ gulp.src(paths.vendors + 'squire/src/Squire.js')
+ .pipe(gulp.dest( paths.dist + 'squire/'));
+
+ gulp.src([paths.vendors + 'qunit/qunit/qunit.js', paths.vendors + 'qunit/qunit/qunit.css'])
+ .pipe(gulp.dest( paths.dist + 'qunit/'));
+
+ gulp.src(paths.vendors + 'qunit/addons/phantomjs/*')
+ .pipe(gulp.dest( paths.dist + 'qunit/addons/phantomjs'));
+});
+
+gulp.task('copy-vendor-via-bower', function () {
+ var vendorConfig = {
+ 'jquery-mobile-bower/css': {
+ dirname: 'jquery-mobile'
+ },
+ 'jquery-mobile-bower/js': {
+ dirname: 'jquery-mobile'
+ }
+ };
+
+ return gulp.src(lib.ext().files, { base: paths.vendors })
+ .pipe(rename(function (path) {
+ if( vendorConfig[path.dirname] !== undefined ) {
+ // console.log('reading path', path)
+ var cuConf = vendorConfig[path.dirname];
+ path.dirname = cuConf.dirname;
+ }
+ return path;
+ }))
+ .pipe(gulp.dest(paths.dist));
+});
+
+// copy additionnal assets from vendors to match old legacy assets:
+gulp.task('copy-vendors', ['copy-vendor-via-bower'],function () {
+ gulp.src([paths.vendors + 'fancytree/dist/skin-win8/**/*']) //, paths.vendors + 'fancytree/dist/jquery.fancytree-all.min
+ .pipe(gulp.dest( paths.dist + 'fancytree/dist/skin-win8'))
+
+ gulp.src(paths.vendors + 'jquery-ui/ui/jquery-ui.js')
+ .pipe(gulp.dest( paths.dist + 'jquery.ui/'));
+
+ gulp.src(paths.vendors + 'jquery-ui/themes/base/*.css')
+ .pipe(gulp.dest( paths.dist + 'jquery.ui/'));
+
+ gulp.src(paths.vendors + 'jquery-ui/ui/i18n/*')
+ .pipe(gulp.dest( paths.dist + 'jquery.ui/i18n'));
+
+ gulp.src(paths.vendors + 'jquery-ui/themes/base/images/*')
+ .pipe(gulp.dest( paths.dist + 'jquery.ui/images'));
+
+ gulp.src(paths.vendors + 'swfobject/swfobject/swfobject.js')
+ .pipe(gulp.dest( paths.dist + 'swfobject'));
+
+
+ gulp.src([paths.vendors + 'jquery-file-upload/js/*', paths.vendors + 'jquery-file-upload/js/vendor/*', paths.vendors + 'jquery-file-upload/css/*'])
+ .pipe(gulp.dest( paths.dist + 'jquery-file-upload'));
+
+ gulp.src(paths.vendors + 'blueimp-load-image/js/*.js')
+ .pipe(gulp.dest( paths.dist + 'blueimp-load-image'));
+
+ gulp.src(paths.vendors + 'i18next/release/i18next.amd-1.6.3.js')
+ .pipe(gulp.dest( paths.dist + 'i18next'));
+
+ gulp.src(paths.vendors + 'bootstrap-multiselect/dist/**/*')
+ .pipe(gulp.dest( paths.dist + 'bootstrap-multiselect'));
+
+ gulp.src([paths.vendors + 'jquery-galleria/src/galleria.js', paths.vendors + 'jquery-galleria/src/themes/classic/*'])
+ .pipe(gulp.dest( paths.dist + 'jquery-galleria'));
+
+ gulp.src(paths.vendors + 'zxcvbn/dist/zxcvbn.js')
+ .pipe(gulp.dest( paths.dist + 'zxcvbn'));
+
+ gulp.start('copy-dev-vendors');
+});
+
+gulp.task('bootstrap-js', function () {
+ var btSource = [
+ paths.vendors + 'bootstrap-sass/vendor/assets/javascripts/bootstrap-transition.js',
+ paths.vendors + 'bootstrap-sass/vendor/assets/javascripts/bootstrap-alert.js',
+ paths.vendors + 'bootstrap-sass/vendor/assets/javascripts/bootstrap-modal.js',
+ paths.vendors + 'bootstrap-sass/vendor/assets/javascripts/bootstrap-dropdown.js',
+ paths.vendors + 'bootstrap-sass/vendor/assets/javascripts/bootstrap-scrollspy.js',
+ paths.vendors + 'bootstrap-sass/vendor/assets/javascripts/bootstrap-tab.js',
+ paths.vendors + 'bootstrap-sass/vendor/assets/javascripts/bootstrap-tooltip.js',
+ paths.vendors + 'bootstrap-sass/vendor/assets/javascripts/bootstrap-popover.js',
+ paths.vendors + 'bootstrap-sass/vendor/assets/javascripts/bootstrap-button.js',
+ paths.vendors + 'bootstrap-sass/vendor/assets/javascripts/bootstrap-collapse.js',
+ paths.vendors + 'bootstrap-sass/vendor/assets/javascripts/bootstrap-carousel.js',
+ paths.vendors + 'bootstrap-sass/vendor/assets/javascripts/bootstrap-typeahead.js',
+ paths.vendors + 'bootstrap-sass/vendor/assets/javascripts/bootstrap-affix.js'];
+
+ gulp.src(btSource)
+ .pipe(concat('bootstrap.js'))
+ .pipe(gulp.dest( paths.dist + 'bootstrap/js'))
+ .pipe(uglify())
+ .pipe(rename({ extname: '.min.js' }))
+ .pipe(gulp.dest( paths.dist + 'bootstrap/js'))
+});
+gulp.task('bootstrap-assets', function () {
+ gulp.src([paths.vendors + 'bootstrap-sass/vendor/assets/images/**/*'])
+ .pipe(gulp.dest( paths.dist + 'bootstrap/img'));
+
+});
+gulp.task('build-bootstrap', ['bootstrap-assets', 'bootstrap-js'], function () {
+ gulp.src(paths.vendors + 'bootstrap-sass/vendor/assets/stylesheets/bootstrap.scss')
+ .pipe(sass({outputStyle: 'compressed'}).on('error', sass.logError))
+ .pipe(gulp.dest( paths.dist + 'bootstrap/css/'))
+ .pipe(cssmin())
+ .pipe(rename({ suffix: '.min' }))
+ .pipe(gulp.dest( paths.dist + 'bootstrap/css'));
+ gulp.src(paths.vendors + 'bootstrap-sass/vendor/assets/stylesheets/bootstrap-responsive.scss')
+ .pipe(sass({outputStyle: 'compressed'}).on('error', sass.logError))
+ .pipe(gulp.dest( paths.dist + 'bootstrap/css/'))
+ .pipe(cssmin())
+ .pipe(rename({ suffix: '.min' }))
+ .pipe(gulp.dest( paths.dist + 'bootstrap/css'));
+});
+
+gulp.task('install-dependencies', function(done){
+ return gulp.src(['./bower.json'])
+ .pipe(install());
+});
+
+gulp.task('copy-dependencies', ['install-dependencies'], function(){
+ gulp.start('copy-vendors');
+ gulp.start('build-bootstrap');
+});
+
+gulp.task('install-assets', ['clean:vendor'], function(){
+ gulp.start('copy-dependencies');
+});
+
+// js fixtures should be present (./bin/developer phraseanet:generate-js-fixtures)
+gulp.task('test', ['qunit','mocha_phantomjs']);
diff --git a/package.json b/package.json
index 6b68aa944e..ae738488b8 100644
--- a/package.json
+++ b/package.json
@@ -3,6 +3,8 @@
"version": "4.0.0",
"devDependencies": {
"bower": "~1.3",
+ "bower-files": "^3.11.3",
+ "del": "^2.0.2",
"grunt": "~0.4.1",
"grunt-bower-postinst": "~0.2.0",
"grunt-bower-task": "~0.4.0",
@@ -12,6 +14,13 @@
"grunt-contrib-qunit": "^0.7.0",
"grunt-mocha-phantomjs": "~0.3.0",
"grunt-shell": "~0.6",
+ "gulp-concat": "^2.6.0",
+ "gulp-cssmin": "^0.1.7",
+ "gulp-install": "^0.6.0",
+ "gulp-mocha-phantomjs": "^0.10.1",
+ "gulp-qunit": "^1.2.1",
+ "gulp-sass": "^2.1.0",
+ "gulp-uglify": "^1.4.2",
"jake": "latest",
"mocha-phantomjs": ">=2.0 <3.0",
"recess": ">=1.1.0 <1.1.7",
diff --git a/templates/web/prod/index.html.twig b/templates/web/prod/index.html.twig
index 3342d23f02..76c7b1e8f6 100644
--- a/templates/web/prod/index.html.twig
+++ b/templates/web/prod/index.html.twig
@@ -155,7 +155,7 @@
{% endblock %}
{% block javascript %}
-
+
{% include "common/templates.html.twig" %}
{% endblock %}