Added support for custom UI folder

This commit is contained in:
Keivan Beigi 2015-07-21 19:42:38 -07:00
parent 760469fc5f
commit 98acd0d886
17 changed files with 192 additions and 131 deletions

View File

@ -6,7 +6,13 @@ require('./less');
require('./handlebars'); require('./handlebars');
require('./copy'); require('./copy');
gulp.task('build', function () { gulp.task('build', function() {
return runSequence('clean', return runSequence('clean', [
['webpack', 'less', 'handlebars', 'copyHtml', 'copyContent', 'copyJs']); 'webpack',
'less',
'handlebars',
'copyHtml',
'copyContent',
'copyJs'
]);
}); });

View File

@ -3,6 +3,6 @@ var del = require('del');
var paths = require('./paths'); var paths = require('./paths');
gulp.task('clean', function (cb) { gulp.task('clean', function(cb) {
del([paths.dest.root], cb); del([paths.dest.root], cb);
}); });

View File

@ -1,7 +1,7 @@
module.exports = { module.exports = {
onError:function (error) { onError : function(error) {
//If you want details of the error in the console //If you want details of the error in the console
console.log(error.toString()); console.log(error.toString());
this.emit('end'); this.emit('end');
} }
} };

View File

@ -10,15 +10,18 @@ var stripbom = require('gulp-stripbom');
var paths = require('./paths.js'); var paths = require('./paths.js');
gulp.task('handlebars', function () { gulp.task('handlebars', function() {
var coreStream = gulp.src([paths.src.templates, '!*/**/*Partial.*']) var coreStream = gulp.src([
.pipe(stripbom({ showLog: false })) paths.src.templates,
'!*/**/*Partial.*'
])
.pipe(stripbom({ showLog : false }))
.pipe(handlebars()) .pipe(handlebars())
.pipe(declare({ .pipe(declare({
namespace: 'T', namespace : 'T',
noRedeclare: true, noRedeclare : true,
processName: function (filePath) { processName : function(filePath) {
filePath = path.relative(paths.src.root, filePath); filePath = path.relative(paths.src.root, filePath);
@ -30,12 +33,12 @@ gulp.task('handlebars', function () {
})); }));
var partialStream = gulp.src([paths.src.partials]) var partialStream = gulp.src([paths.src.partials])
.pipe(stripbom({ showLog: false })) .pipe(stripbom({ showLog : false }))
.pipe(handlebars()) .pipe(handlebars())
.pipe(wrap('Handlebars.template(<%= contents %>)')) .pipe(wrap('Handlebars.template(<%= contents %>)'))
.pipe(wrap('Handlebars.registerPartial(<%= processPartialName(file.relative) %>, <%= contents %>)', {}, { .pipe(wrap('Handlebars.registerPartial(<%= processPartialName(file.relative) %>, <%= contents %>)', {}, {
imports: { imports : {
processPartialName: function (fileName) { processPartialName : function(fileName) {
return JSON.stringify( return JSON.stringify(
path.basename(fileName, '.js') path.basename(fileName, '.js')
); );
@ -43,8 +46,7 @@ gulp.task('handlebars', function () {
} }
})); }));
return streamqueue({ objectMode : true },
return streamqueue({ objectMode: true },
partialStream, partialStream,
coreStream coreStream
).pipe(concat('templates.js')) ).pipe(concat('templates.js'))

View File

@ -2,14 +2,13 @@ var gulp = require('gulp');
var print = require('gulp-print'); var print = require('gulp-print');
var paths = require('./paths.js'); var paths = require('./paths.js');
gulp.task('imageMin', function() {
gulp.task('imageMin', function () {
var imagemin = require('gulp-imagemin'); var imagemin = require('gulp-imagemin');
return gulp.src(paths.src.images) return gulp.src(paths.src.images)
.pipe(imagemin({ .pipe(imagemin({
progressive: false, progressive : false,
optimizationLevel :4, optimizationLevel : 4,
svgoPlugins: [{removeViewBox: false}] svgoPlugins : [{ removeViewBox : false }]
})) }))
.pipe(print()) .pipe(print())
.pipe(gulp.dest(paths.src.content + 'Images/')); .pipe(gulp.dest(paths.src.content + 'Images/'));

View File

@ -4,9 +4,11 @@ var stylish = require('jshint-stylish');
var cache = require('gulp-cached'); var cache = require('gulp-cached');
var paths = require('./paths.js'); var paths = require('./paths.js');
gulp.task('jshint', function() {
gulp.task('jshint', function () { return gulp.src([
return gulp.src([paths.src.scripts, paths.src.exclude.libs]) paths.src.scripts,
paths.src.exclude.libs
])
.pipe(cache('jshint')) .pipe(cache('jshint'))
.pipe(jshint()) .pipe(jshint())
.pipe(jshint.reporter(stylish)); .pipe(jshint.reporter(stylish));

View File

@ -1,15 +1,35 @@
var gulp = require('gulp'); var gulp = require('gulp');
var less = require('gulp-less'); var less = require('gulp-less');
var print = require('gulp-print'); var print = require('gulp-print');
var phantom = require('./phantom');
var livereload = require('gulp-livereload'); var livereload = require('gulp-livereload');
var paths = require('./paths'); var paths = require('./paths');
var errorHandler = require('./errorHandler'); var errorHandler = require('./errorHandler');
gulp.task('less', function () { gulp.task('less', function() {
return gulp.src([
var src = [
paths.src.content + 'bootstrap.less',
paths.src.content + 'theme.less',
paths.src.content + 'overrides.less',
paths.src.root + 'Series/series.less',
paths.src.root + 'Activity/activity.less',
paths.src.root + 'AddSeries/addSeries.less',
paths.src.root + 'Calendar/calendar.less',
paths.src.root + 'Cells/cells.less',
paths.src.root + 'ManualImport/manualimport.less',
paths.src.root + 'Settings/settings.less',
paths.src.root + 'System/Logs/logs.less',
paths.src.root + 'System/Update/update.less',
paths.src.root + 'System/Info/info.less',
];
if (phantom) {
src = [
paths.src.content + 'bootstrap.less', paths.src.content + 'bootstrap.less',
paths.src.content + 'theme.less', paths.src.content + 'angle.less',
paths.src.content + 'sonarr.less',
paths.src.content + 'overrides.less', paths.src.content + 'overrides.less',
paths.src.root + 'Series/series.less', paths.src.root + 'Series/series.less',
paths.src.root + 'Activity/activity.less', paths.src.root + 'Activity/activity.less',
@ -21,14 +41,17 @@ gulp.task('less', function () {
paths.src.root + 'System/Logs/logs.less', paths.src.root + 'System/Logs/logs.less',
paths.src.root + 'System/Update/update.less', paths.src.root + 'System/Update/update.less',
paths.src.root + 'System/Info/info.less', paths.src.root + 'System/Info/info.less',
]) ]
}
return gulp.src(src)
.pipe(print()) .pipe(print())
.pipe(less({ .pipe(less({
dumpLineNumbers: 'false', dumpLineNumbers : 'false',
compress: true, compress : true,
yuicompress: true, yuicompress : true,
ieCompat: true, ieCompat : true,
strictImports: true strictImports : true
})) }))
.on('error', errorHandler.onError) .on('error', errorHandler.onError)
.pipe(gulp.dest(paths.dest.content)) .pipe(gulp.dest(paths.dest.content))

View File

@ -1,45 +1,45 @@
var phantom = require('./phantom'); var phantom = require('./phantom');
var paths = { var paths = {
src: { src : {
root: './src/UI/', root : './src/UI/',
templates: './src/UI/**/*.hbs', templates : './src/UI/**/*.hbs',
html: './src/UI/*.html', html : './src/UI/*.html',
partials: './src/UI/**/*Partial.hbs', partials : './src/UI/**/*Partial.hbs',
scripts: './src/UI/**/*.js', scripts : './src/UI/**/*.js',
less: ['./src/UI/**/*.less'], less : ['./src/UI/**/*.less'],
content: './src/UI/Content/', content : './src/UI/Content/',
images: './src/UI/Content/Images/**/*', images : './src/UI/Content/Images/**/*',
exclude: { exclude : {
libs: '!./src/UI/JsLibraries/**' libs : '!./src/UI/JsLibraries/**'
}
},
dest : {
root : './_output/UI/',
content : './_output/UI/Content/'
} }
},
dest: {
root: './_output/UI/',
content: './_output/UI/Content/'
}
}; };
if (phantom) { if (phantom) {
paths = { paths = {
src: { src : {
root: './src/UI.Phantom/', root : './src/UI.Phantom/',
templates: './src/UI.Phantom/**/*.hbs', templates : './src/UI.Phantom/**/*.hbs',
html: './src/UI.Phantom/*.html', html : './src/UI.Phantom/*.html',
partials: './src/UI.Phantom/**/*Partial.hbs', partials : './src/UI.Phantom/**/*Partial.hbs',
scripts: './src/UI.Phantom/**/*.js', scripts : './src/UI.Phantom/**/*.js',
less: ['./src/UI.Phantom/**/*.less'], less : ['./src/UI.Phantom/**/*.less'],
content: './src/UI.Phantom/Content/', content : './src/UI.Phantom/Content/',
images: './src/UI.Phantom/Content/Images/**/*', images : './src/UI.Phantom/Content/Images/**/*',
exclude: { exclude : {
libs: '!./src/UI.Phantom/JsLibraries/**' libs : '!./src/UI.Phantom/JsLibraries/**'
} }
}, },
dest: { dest : {
root: './_output/UI.Phantom/', root : './_output/UI.Phantom/',
content: './_output/UI.Phantom/Content/' content : './_output/UI.Phantom/Content/'
} }
}; };
} }
module.exports = paths; module.exports = paths;

View File

@ -4,9 +4,11 @@
var phantom = false; var phantom = false;
process.argv.forEach(function (val, index, array) { process.argv.forEach(function (val, index, array) {
if(val=== '--phantom'){ if (val === '--phantom') {
phantom = true; phantom = true;
} }
}); });
console.log('Phantom:', phantom);
module.exports = phantom; module.exports = phantom;

View File

@ -84,7 +84,7 @@ gulp.task('getSonarr', function () {
download(package.url, packagePath, function () { download(package.url, packagePath, function () {
extract(packagePath, dirName, function () { extract(packagePath, dirName, function () {
// clean old binaries // clean old binaries
console.log('Cleaning old binaries') console.log('Cleaning old binaries');
del.sync(['./_output/*', '!./_output/UI/']); del.sync(['./_output/*', '!./_output/UI/']);
console.log('copying binaries to target'); console.log('copying binaries to target');
gulp.src(dirName + '/NzbDrone/*.*') gulp.src(dirName + '/NzbDrone/*.*')

View File

@ -3,17 +3,20 @@ using System.IO;
using NLog; using NLog;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Core.Configuration;
namespace NzbDrone.Api.Frontend.Mappers namespace NzbDrone.Api.Frontend.Mappers
{ {
public class FaviconMapper : StaticResourceMapperBase public class FaviconMapper : StaticResourceMapperBase
{ {
private readonly IAppFolderInfo _appFolderInfo; private readonly IAppFolderInfo _appFolderInfo;
private readonly IConfigFileProvider _configFileProvider;
public FaviconMapper(IAppFolderInfo appFolderInfo, IDiskProvider diskProvider, Logger logger) public FaviconMapper(IAppFolderInfo appFolderInfo, IDiskProvider diskProvider,IConfigFileProvider configFileProvider, Logger logger)
: base(diskProvider, logger) : base(diskProvider, logger)
{ {
_appFolderInfo = appFolderInfo; _appFolderInfo = appFolderInfo;
_configFileProvider = configFileProvider;
} }
public override string Map(string resourceUrl) public override string Map(string resourceUrl)
@ -27,7 +30,7 @@ namespace NzbDrone.Api.Frontend.Mappers
var path = Path.Combine("Content", "Images", fileName); var path = Path.Combine("Content", "Images", fileName);
return Path.Combine(_appFolderInfo.StartUpFolder, "UI", path); return Path.Combine(_appFolderInfo.StartUpFolder, _configFileProvider.UiFolder, path);
} }
public override bool CanHandle(string resourceUrl) public override bool CanHandle(string resourceUrl)

View File

@ -36,7 +36,7 @@ namespace NzbDrone.Api.Frontend.Mappers
_configFileProvider = configFileProvider; _configFileProvider = configFileProvider;
_analyticsService = analyticsService; _analyticsService = analyticsService;
_cacheBreakProviderFactory = cacheBreakProviderFactory; _cacheBreakProviderFactory = cacheBreakProviderFactory;
_indexPath = Path.Combine(appFolderInfo.StartUpFolder, "UI", "index.html"); _indexPath = Path.Combine(appFolderInfo.StartUpFolder, _configFileProvider.UiFolder, "index.html");
API_KEY = configFileProvider.ApiKey; API_KEY = configFileProvider.ApiKey;
URL_BASE = configFileProvider.UrlBase; URL_BASE = configFileProvider.UrlBase;

View File

@ -12,6 +12,7 @@ namespace NzbDrone.Api.Frontend.Mappers
public class LoginHtmlMapper : StaticResourceMapperBase public class LoginHtmlMapper : StaticResourceMapperBase
{ {
private readonly IDiskProvider _diskProvider; private readonly IDiskProvider _diskProvider;
private readonly IConfigFileProvider _configFileProvider;
private readonly Func<ICacheBreakerProvider> _cacheBreakProviderFactory; private readonly Func<ICacheBreakerProvider> _cacheBreakProviderFactory;
private readonly string _indexPath; private readonly string _indexPath;
private static readonly Regex ReplaceRegex = new Regex("(?<=(?:href|src|data-main)=\").*?(?=\")", RegexOptions.Compiled | RegexOptions.IgnoreCase); private static readonly Regex ReplaceRegex = new Regex("(?<=(?:href|src|data-main)=\").*?(?=\")", RegexOptions.Compiled | RegexOptions.IgnoreCase);
@ -27,8 +28,9 @@ namespace NzbDrone.Api.Frontend.Mappers
: base(diskProvider, logger) : base(diskProvider, logger)
{ {
_diskProvider = diskProvider; _diskProvider = diskProvider;
_configFileProvider = configFileProvider;
_cacheBreakProviderFactory = cacheBreakProviderFactory; _cacheBreakProviderFactory = cacheBreakProviderFactory;
_indexPath = Path.Combine(appFolderInfo.StartUpFolder, "UI", "login.html"); _indexPath = Path.Combine(appFolderInfo.StartUpFolder, _configFileProvider.UiFolder, "login.html");
URL_BASE = configFileProvider.UrlBase; URL_BASE = configFileProvider.UrlBase;
} }

View File

@ -3,24 +3,27 @@ using System.IO;
using NLog; using NLog;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Core.Configuration;
namespace NzbDrone.Api.Frontend.Mappers namespace NzbDrone.Api.Frontend.Mappers
{ {
public class RobotsTxtMapper : StaticResourceMapperBase public class RobotsTxtMapper : StaticResourceMapperBase
{ {
private readonly IAppFolderInfo _appFolderInfo; private readonly IAppFolderInfo _appFolderInfo;
private readonly IConfigFileProvider _configFileProvider;
public RobotsTxtMapper(IAppFolderInfo appFolderInfo, IDiskProvider diskProvider, Logger logger) public RobotsTxtMapper(IAppFolderInfo appFolderInfo, IDiskProvider diskProvider, IConfigFileProvider configFileProvider, Logger logger)
: base(diskProvider, logger) : base(diskProvider, logger)
{ {
_appFolderInfo = appFolderInfo; _appFolderInfo = appFolderInfo;
_configFileProvider = configFileProvider;
} }
public override string Map(string resourceUrl) public override string Map(string resourceUrl)
{ {
var path = Path.Combine("Content", "robots.txt"); var path = Path.Combine("Content", "robots.txt");
return Path.Combine(_appFolderInfo.StartUpFolder, "UI", path); return Path.Combine(_appFolderInfo.StartUpFolder, _configFileProvider.UiFolder, path);
} }
public override bool CanHandle(string resourceUrl) public override bool CanHandle(string resourceUrl)

View File

@ -2,17 +2,20 @@ using System.IO;
using NLog; using NLog;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Core.Configuration;
namespace NzbDrone.Api.Frontend.Mappers namespace NzbDrone.Api.Frontend.Mappers
{ {
public class StaticResourceMapper : StaticResourceMapperBase public class StaticResourceMapper : StaticResourceMapperBase
{ {
private readonly IAppFolderInfo _appFolderInfo; private readonly IAppFolderInfo _appFolderInfo;
private readonly IConfigFileProvider _configFileProvider;
public StaticResourceMapper(IAppFolderInfo appFolderInfo, IDiskProvider diskProvider, Logger logger) public StaticResourceMapper(IAppFolderInfo appFolderInfo, IDiskProvider diskProvider, IConfigFileProvider configFileProvider, Logger logger)
: base(diskProvider, logger) : base(diskProvider, logger)
{ {
_appFolderInfo = appFolderInfo; _appFolderInfo = appFolderInfo;
_configFileProvider = configFileProvider;
} }
public override string Map(string resourceUrl) public override string Map(string resourceUrl)
@ -20,7 +23,7 @@ namespace NzbDrone.Api.Frontend.Mappers
var path = resourceUrl.Replace('/', Path.DirectorySeparatorChar); var path = resourceUrl.Replace('/', Path.DirectorySeparatorChar);
path = path.Trim(Path.DirectorySeparatorChar); path = path.Trim(Path.DirectorySeparatorChar);
return Path.Combine(_appFolderInfo.StartUpFolder, "UI", path); return Path.Combine(_appFolderInfo.StartUpFolder, _configFileProvider.UiFolder, path);
} }
public override bool CanHandle(string resourceUrl) public override bool CanHandle(string resourceUrl)

View File

@ -37,6 +37,7 @@ namespace NzbDrone.Core.Configuration
string ApiKey { get; } string ApiKey { get; }
string SslCertHash { get; } string SslCertHash { get; }
string UrlBase { get; } string UrlBase { get; }
string UiFolder { get; }
Boolean UpdateAutomatically { get; } Boolean UpdateAutomatically { get; }
UpdateMechanism UpdateMechanism { get; } UpdateMechanism UpdateMechanism { get; }
String UpdateScriptPath { get; } String UpdateScriptPath { get; }
@ -215,6 +216,14 @@ namespace NzbDrone.Core.Configuration
} }
} }
public string UiFolder
{
get
{
return GetValue("UiFolder", "UI", false);
}
}
public bool UpdateAutomatically public bool UpdateAutomatically
{ {
get { return GetValueBoolean("UpdateAutomatically", false, false); } get { return GetValueBoolean("UpdateAutomatically", false, false); }

View File

@ -1,67 +1,74 @@
var path = require('path'); var path = require('path');
var stylish = require('jshint-stylish'); var stylish = require('jshint-stylish');
var webpack = require('webpack'); var webpack = require('webpack');
var phantom = require('./gulp/phantom');
var uglifyJsPlugin = new webpack.optimize.UglifyJsPlugin(); var uglifyJsPlugin = new webpack.optimize.UglifyJsPlugin();
var uiFolder = 'UI';
if (phantom) {
uiFolder = 'UI.Phantom';
}
module.exports = { module.exports = {
entry: { entry: {
vendor: 'vendor.js', vendor: 'vendor.js',
main: 'main.js' main: 'main.js'
}, },
resolve : { resolve: {
root : path.join(__dirname, 'src', 'UI'), root: path.join(__dirname, 'src', uiFolder),
alias : { alias: {
'vent' : 'vent', 'vent': 'vent',
'backbone' : 'Shims/backbone', 'backbone': 'Shims/backbone',
'moment' : 'JsLibraries/moment', 'moment': 'JsLibraries/moment',
'filesize' : 'JsLibraries/filesize', 'filesize': 'JsLibraries/filesize',
'handlebars' : 'Shims/handlebars', 'handlebars': 'Shims/handlebars',
'handlebars.helpers' : 'JsLibraries/handlebars.helpers', 'handlebars.helpers': 'JsLibraries/handlebars.helpers',
'bootstrap' : 'JsLibraries/bootstrap', 'bootstrap': 'JsLibraries/bootstrap',
'backbone.deepmodel' : 'JsLibraries/backbone.deep.model', 'backbone.deepmodel': 'JsLibraries/backbone.deep.model',
'backbone.pageable' : 'JsLibraries/backbone.pageable', 'backbone.pageable': 'JsLibraries/backbone.pageable',
'backbone-pageable' : 'JsLibraries/backbone.pageable', 'backbone-pageable': 'JsLibraries/backbone.pageable',
'backbone.validation' : 'Shims/backbone.validation', 'backbone.validation': 'Shims/backbone.validation',
'backbone.modelbinder' : 'JsLibraries/backbone.modelbinder', 'backbone.modelbinder': 'JsLibraries/backbone.modelbinder',
'backbone.collectionview' : 'Shims/backbone.collectionview', 'backbone.collectionview': 'Shims/backbone.collectionview',
'backgrid' : 'Shims/backgrid', 'backgrid': 'Shims/backgrid',
'backgrid.paginator' : 'Shims/backgrid.paginator', 'backgrid.paginator': 'Shims/backgrid.paginator',
'backgrid.selectall' : 'Shims/backbone.backgrid.selectall', 'backgrid.selectall': 'Shims/backbone.backgrid.selectall',
'fullcalendar' : 'JsLibraries/fullcalendar', 'fullcalendar': 'JsLibraries/fullcalendar',
'backstrech' : 'JsLibraries/jquery.backstretch', 'backstrech': 'JsLibraries/jquery.backstretch',
'underscore' : 'JsLibraries/lodash.underscore', 'underscore': 'JsLibraries/lodash.underscore',
'marionette' : 'Shims/backbone.marionette', 'marionette': 'Shims/backbone.marionette',
'signalR' : 'Shims/jquery.signalR', 'signalR': 'Shims/jquery.signalR',
'jquery-ui' : 'JsLibraries/jquery-ui', 'jquery-ui': 'JsLibraries/jquery-ui',
'jquery.knob' : 'JsLibraries/jquery.knob', 'jquery.knob': 'JsLibraries/jquery.knob',
'jquery.easypiechart' : 'JsLibraries/jquery.easypiechart', 'jquery.easypiechart': 'JsLibraries/jquery.easypiechart',
'jquery.dotdotdot' : 'JsLibraries/jquery.dotdotdot', 'jquery.dotdotdot': 'JsLibraries/jquery.dotdotdot',
'messenger' : 'Shims/messenger', 'messenger': 'Shims/messenger',
'jquery' : 'Shims/jquery', 'jquery': 'Shims/jquery',
'typeahead' : 'JsLibraries/typeahead', 'typeahead': 'JsLibraries/typeahead',
'zero.clipboard' : 'JsLibraries/zero.clipboard', 'zero.clipboard': 'JsLibraries/zero.clipboard',
'bootstrap.tagsinput' : 'JsLibraries/bootstrap.tagsinput', 'bootstrap.tagsinput': 'JsLibraries/bootstrap.tagsinput',
'libs' : 'JsLibraries/' 'libs': 'JsLibraries/'
} }
}, },
output : { output: {
filename : '_output/UI/[name].js', filename: '_output/' + uiFolder + '/[name].js',
sourceMapFilename : '_output/UI/[name].map' sourceMapFilename: '_output/' + uiFolder + '/[name].map'
}, },
plugins : [ plugins: [
new webpack.optimize.CommonsChunkPlugin({name: 'vendor'}) new webpack.optimize.CommonsChunkPlugin({ name: 'vendor' })
], ],
module: { module: {
//this doesn't work yet. wainting for https://github.com/spenceralger/rcloader/issues/5 //this doesn't work yet. wainting for https://github.com/spenceralger/rcloader/issues/5
/*preLoaders: [ /*preLoaders: [
{ {
test: /\.js$/, // include .js files test: /\.js$/, // include .js files
loader: "jshint-loader", loader: "jshint-loader",
exclude: [/JsLibraries/,/node_modules/] exclude: [/JsLibraries/,/node_modules/]
} }
] ]
*/ */
} }
}; };