Move to webpack

Signed-off-by: Julius Härtl <jus@bitgrid.net>
This commit is contained in:
Julius Härtl
2018-01-22 14:19:02 +01:00
parent e94986744d
commit 24f4f84eb6
43 changed files with 184 additions and 218 deletions

2
.gitignore vendored
View File

@@ -1,9 +1,11 @@
js/node_modules/*
js/vendor/
js/public/
js/build/
js/package-lock.json
build/
css/style.css
css/vendor.css
tests/integration/vendor/
tests/integration/composer.lock
vendor/

View File

@@ -19,19 +19,17 @@ clean-build:
clean-dist:
rm -rf js/node_modules
rm -rf js/vendor
install-deps:
cd js && npm install --deps
cd js && ./node_modules/.bin/bower install
cd js && npm install
build: build-js
build-js: install-deps
cd js && ./node_modules/.bin/grunt build
cd js && ./node_modules/.bin/webpack --config webpack.prod.config.js
watch:
cd js && ./node_modules/.bin/grunt watch
cd js && ./node_modules/.bin/webpack --config webpack.dev.config.js --watch
# appstore: clean install-deps
appstore: clean-build build

View File

@@ -1,3 +0,0 @@
{
"directory": "vendor"
}

View File

@@ -1,124 +0,0 @@
/*
* @copyright Copyright (c) 2016 Julius Härtl <jus@bitgrid.net>
*
* @author Julius Härtl <jus@bitgrid.net>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* global module */
module.exports = function(grunt) {
'use strict';
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-wrap');
grunt.loadNpmTasks('grunt-karma');
grunt.loadNpmTasks('grunt-phpunit');
grunt.initConfig({
meta: {
pkg: grunt.file.readJSON('package.json'),
version: '<%= meta.pkg.version %>',
configJS: 'config/',
buildJS: [
'app/**/*.js',
'controller/**/*.js',
'filters/**/*.js',
'directive/**/*.js',
'service/**/*.js'
],
productionJS: 'public/',
testsJS: '../tests/js/'
},
concat: {
options: {
stripBanners: true
},
dist: {
src: ['<%= meta.buildJS %>'],
dest: '<%= meta.productionJS %>app.js'
}
},
wrap: {
app: {
src: ['<%= meta.productionJS %>app.js'],
dest: '<%= meta.productionJS %>app.js',
option: {
wrapper: [
'(function(angular, $, oc_requesttoken, undefined){\n\n\'use strict\';\n\n',
'\n})(angular, jQuery, oc_requesttoken);'
]
}
}
},
jshint: {
files: [
'Gruntfile.js',
'<%= meta.buildJS %>**/*.js',
'<%= meta.testsJS %>**/*.js'
],
options: {
jshintrc: '.jshintrc',
reporter: require('jshint-stylish')
}
},
watch: {
concat: {
files: ['<%=meta.buildJS%>'],
options: {
livereload: true
},
tasks: ['build']
}
},
phpunit: {
classes: {
dir: '../tests/unit'
},
options: {
bootstrap: '../tests/bootstrap.php',
colors: true
}
},
karma: {
unit: {
configFile: '<%= meta.testsJS %>config/karma.js'
},
continuous: {
configFile: '<%= meta.testsJS %>config/karma.js',
browsers: ['Firefox'],
singleRun: true,
reporters: ['progress']
}
},
});
// make tasks available under simpler commands
grunt.registerTask('build', ['jshint', 'concat', 'wrap']);
grunt.registerTask('js-unit', ['karma:continuous']);
};

View File

@@ -41,13 +41,18 @@ angular.module('markdown', [])
};
}]);
import uirouter from '@uirouter/angularjs';
import ngsanitize from 'angular-sanitize';
import angularuiselect from 'ui-select';
import ngsortable from 'ng-sortable';
import md from 'angular-markdown-it';
import nganimate from 'angular-animate';
var app = angular.module('Deck', [
'ngRoute',
'ngSanitize',
'ui.router',
'ui.select',
'as.sortable',
'mdMarkdownIt',
'ngAnimate'
ngsanitize,
uirouter,
angularuiselect,
ngsortable, md, nganimate
]);
export default app;

View File

@@ -22,18 +22,21 @@
/* global app oc_requesttoken markdownitLinkTarget */
app.config(function ($provide, $routeProvider, $interpolateProvider, $httpProvider, $urlRouterProvider, $stateProvider, $compileProvider, markdownItConverterProvider) {
import app from './App.js';
import md from 'angular-markdown-it';
import markdownitLinkTarget from 'markdown-it-link-target';
app.config(function ($provide, $interpolateProvider, $httpProvider, $urlRouterProvider, $stateProvider, $compileProvider, markdownItConverterProvider) {
'use strict';
$httpProvider.defaults.headers.common.requesttoken = oc_requesttoken;
$compileProvider.debugInfoEnabled(true);
markdownItConverterProvider.config({
markdownItConverterProvider.use(markdownitLinkTarget, {
breaks: true,
linkify: true,
xhtmlOut: true
});
markdownItConverterProvider.use(markdownitLinkTarget);
$urlRouterProvider.otherwise('/');

View File

@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import app from './App.js';
/* global Snap */
app.run(function ($document, $rootScope, $transitions, BoardService) {

View File

@@ -1,29 +0,0 @@
{
"name": "deck",
"version": "0.0.1",
"dependencies": {
"angular": "~1.6.1",
"angular-route": "~1.6.1",
"angular-mocks": "~1.6.1",
"angular-sanitize": "~1.6.1",
"angular-animate": "~1.6.1",
"ng-sortable": "1.3.8",
"jquery": "3.2.x",
"es6-shim": "~0.*",
"js-url": "~2.*",
"angular-ui-select": "~0.19.6",
"angular-markdown-it": "~0.6.1",
"angular-ui-router": "~1.0.0",
"markdown-it-link-target": "~1.0.1",
"jquery-timepicker": "883bb2cd94"
},
"license": "AGPL-3.0",
"private": true,
"ignore": [
"'**/.*",
"node_modules",
"bower_components",
"test",
"tests"
]
}

View File

@@ -20,8 +20,10 @@
*
*/
import app from '../app/App.js';
/** global: OC */
app.controller('AppController', function ($scope, $location, $http, $route, $log, $rootScope) {
app.controller('AppController', function ($scope, $location, $http, $log, $rootScope) {
$rootScope.sidebar = {
show: false
};

View File

@@ -20,6 +20,7 @@
*
*/
import app from '../app/App.js';
/* global oc_defaults OC */
app.controller('BoardController', function ($rootScope, $scope, $stateParams, StatusService, BoardService, StackService, CardService, LabelService, $state, $transitions, $filter) {

View File

@@ -21,6 +21,7 @@
*/
/* global app moment */
import app from '../app/App.js';
app.controller('CardController', function ($scope, $rootScope, $routeParams, $location, $stateParams, $interval, $timeout, $filter, BoardService, CardService, StackService, StatusService) {
$scope.sidebar = $rootScope.sidebar;

View File

@@ -22,7 +22,7 @@
/* global app angular */
app.controller('ListController', function ($scope, $location, $filter, BoardService, $element, $timeout, $stateParams, $state, StatusService) {
var ListController = function ($scope, $location, $filter, BoardService, $element, $timeout, $stateParams, $state, StatusService) {
function calculateNewColor() {
var boards = BoardService.getAll();
@@ -193,5 +193,6 @@ app.controller('ListController', function ($scope, $location, $filter, BoardServ
});
};
});
};
export default ListController;

View File

@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import app from '../app/App.js';
app.directive('appPopoverMenuUtils', function () {
'use strict';

View File

@@ -20,6 +20,7 @@
*
*/
import app from '../app/App.js';
// OwnCloud Click Handling
// https://doc.owncloud.org/server/8.0/developer_manual/app/css.html
app.directive('appNavigationEntryUtils', function () {

View File

@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import app from '../app/App.js';
app.directive('autofocusOnInsert', function () {
'use strict';

View File

@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import app from '../app/App.js';
app.directive('avatar', function() {
'use strict';

View File

@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import app from '../app/App.js';
app.directive('contactsmenudelete', function() {
'use strict';

View File

@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import app from '../app/App.js';
/* global app */
/* gloabl t */

View File

@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import app from '../app/App.js';
// original idea from blockloop: http://stackoverflow.com/a/24090733
app.directive('elastic', [

View File

@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import app from '../app/App.js';
app.directive('search', function ($document, $location) {
'use strict';

View File

@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import app from '../app/App.js';
/* global app */
/* global t */

View File

@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import app from '../app/App.js';
app.filter('boardFilterAcl', function() {
return function(boards) {

View File

@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import app from '../app/App.js';
// usage | cardFilter({ member: 'admin'})

View File

@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import app from '../app/App.js';
app.filter('cardSearchFilter', function() {
return function(cards, searchString) {

View File

@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import app from '../app/App.js';
/* global app */
/* global OC */

View File

@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import app from '../app/App.js';
app.filter('iconWhiteFilter', function () {
return function (hex) {

View File

@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import app from '../app/App.js';
app.filter('lightenColorFilter', function() {
return function (hex) {

View File

@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import app from '../app/App.js';
app.filter('orderObjectBy', function(){
return function(input, attribute) {

View File

@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import app from '../app/App.js';
app.filter('textColorFilter', function () {
return function (hex) {

View File

@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import app from '../app/App.js';
/* global app */
/* global angular */

25
js/init.js Normal file
View File

@@ -0,0 +1,25 @@
'use strict';
// used for building a vendor stylesheet
import 'jquery-timepicker/jquery.timepicker.css';
import 'ng-sortable/dist/ng-sortable.css';
import angular from 'angular';
import app from './app/App.js';
import './app/Config.js';
import './app/Run.js';
import ListController from 'controller/ListController.js';
app.controller('ListController', ListController)
// require all the js files from subdirectories
var context = require.context(".", true, /(controller|service|filters|directive)\/(.*)\.js$/);
context.keys().forEach(function (key) {
context(key);
});

View File

@@ -5,19 +5,30 @@
"directories": {
"test": "tests"
},
"dependencies": {},
"dependencies": {
"@uirouter/angularjs": "^1.0.13",
"angular": "^1.6.8",
"angular-animate": "^1.6.8",
"angular-markdown-it": "^0.6.1",
"angular-sanitize": "^1.6.8",
"jquery": "^3.3.1",
"jquery-timepicker": "^1.3.3",
"markdown-it-link-target": "^1.0.2",
"ng-sortable": "^1.3.8",
"ui-select": "^0.19.8"
},
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"bower": "^1.8.0",
"grunt": "^1.0.1",
"grunt-contrib-concat": "^1.0.1",
"grunt-contrib-jshint": "^1.1.0",
"grunt-contrib-watch": "^1.0.0",
"grunt-karma": "^2.0.0",
"grunt-phpunit": "^0.3.6",
"grunt-wrap": "^0.3.0",
"css-loader": "^0.28.9",
"extract-text-webpack-plugin": "^3.0.2",
"jshint-stylish": "^2.2.1",
"karma": "^1.4.1",
"node-sass": "^4.5.3"
"node-sass": "^4.5.3",
"style-loader": "^0.19.1",
"webpack": "^3.10.0",
"webpack-merge": "^4.1.1"
},
"scripts": {
"test": "echo \"Warning: no test specified\" && exit 0"

View File

@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import app from '../app/App.js';
/** global: oc_defaults */
app.factory('ApiService', function ($http, $q) {

View File

@@ -19,7 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import app from '../app/App.js';
/* global app OC */
app.factory('BoardService', function (ApiService, $http, $q) {
var BoardService = function ($http, ep, $q) {

View File

@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import app from '../app/App.js';
app.factory('CardService', function (ApiService, $http, $q) {
var CardService = function ($http, ep, $q) {

View File

@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import app from '../app/App.js';
app.factory('LabelService', function (ApiService, $http, $q) {
var LabelService = function ($http, ep, $q) {

View File

@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import app from '../app/App.js';
app.factory('StackService', function (ApiService, $http, $q) {
var StackService = function ($http, ep, $q) {

View File

@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import app from '../app/App.js';
app.factory('StatusService', function () {
// Status Helper

54
js/webpack.config.js Normal file
View File

@@ -0,0 +1,54 @@
const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
entry: {
deck: './init.js',
},
output: {
filename: '[name].js',
path: __dirname + '/build'
},
resolve: {
modules: [path.resolve(__dirname), 'node_modules'],
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: {
loader: 'css-loader',
options: {
minimize: true,
}
},
})
}
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin({
test: /(vendor\.js)+/i,
}),
// we do not uglify deck.js since there are no proper dependency annotations
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
filename: 'vendor.js',
minChunks(module, count) {
var context = module.context;
return context && context.indexOf('node_modules') >= 0;
},
}),
new ExtractTextPlugin({
filename: "../../css/vendor.css",
allChunks: true
}),
]
};

6
js/webpack.dev.config.js Normal file
View File

@@ -0,0 +1,6 @@
const merge = require('webpack-merge');
const baseConfig = require('./webpack.config.js');
module.exports = merge(baseConfig, {
devtool: 'eval'
});

13
js/webpack.prod.config.js Normal file
View File

@@ -0,0 +1,13 @@
const webpack = require('webpack');
const merge = require('webpack-merge');
const baseConfig = require('./webpack.config.js');
module.exports = merge(baseConfig, {
plugins: [
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
}),
]
});

View File

@@ -4,6 +4,10 @@ exclude = [
".git",
"js/node_modules",
"js/tests",
"js/controller",
"js/directive",
"js/filters",
"js/service",
"js/bower.json",
"js/.bowerrc",
"js/.jshintrc",

View File

@@ -23,39 +23,11 @@
use OCP\Util;
Util::addStyle('deck', '../js/vendor/ng-sortable/dist/ng-sortable.min');
Util::addStyle('deck', '../js/vendor/jquery-timepicker/jquery.ui.timepicker');
Util::addStyle('deck', 'vendor');
Util::addStyle('deck', 'style');
Util::addScript('deck', 'vendor/angular/angular.min');
Util::addScript('deck', 'vendor/angular-route/angular-route.min');
Util::addScript('deck', 'vendor/angular-sanitize/angular-sanitize.min');
Util::addScript('deck', 'vendor/angular-animate/angular-animate.min');
Util::addScript('deck', 'vendor/angular-ui-router/release/angular-ui-router.min');
Util::addScript('deck', 'vendor/ng-sortable/dist/ng-sortable.min');
Util::addScript('deck', 'vendor/angular-ui-select/dist/select.min');
Util::addScript('deck', 'vendor/markdown-it/dist/markdown-it.min');
Util::addScript('deck', 'vendor/angular-markdown-it/dist/ng-markdownit.min');
Util::addScript('deck', 'vendor/markdown-it-link-target/dist/markdown-it-link-target.min');
Util::addScript('deck', 'vendor/jquery-timepicker/jquery.ui.timepicker');
if(!\OC::$server->getConfig()->getSystemValue('debug', false)) {
Util::addScript('deck', 'public/app');
} else {
// Load seperate JS files when debug mode is enabled
$js = [
'app' => ['App', 'Config', 'Run'],
'controller' => ['AppController', 'BoardController', 'CardController', 'ListController'],
'directive' => ['appnavigationentryutils', 'appPopoverMenuUtils', 'autofocusoninsert', 'avatar', 'contactsmenudelete', 'elastic', 'search', 'datepicker', 'timepicker'],
'filters' => ['boardFilterAcl', 'cardFilter', 'cardSearchFilter', 'iconWhiteFilter', 'lightenColorFilter', 'orderObjectBy', 'dateFilters', 'textColorFilter', 'withoutAssignedUsers'],
'service' => ['ApiService', 'BoardService', 'CardService', 'LabelService', 'StackService', 'StatusService'],
];
foreach($js as $folder=>$files) {
foreach ($files as $file) {
Util::addScript('deck', $folder.'/'.$file);
}
}
}
Util::addScript('deck', 'build/vendor');
Util::addScript('deck', 'build/deck');
?>
<div id="app" class="app-deck" data-ng-app="Deck" ng-controller="AppController" ng-cloak>