diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..b2ee1564 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +docs/ export-ignore +javascript/src/ export ignore + +# Hide diffs +javascript/dist/ -diff diff --git a/.gitignore b/.gitignore index 8a9c5dfa..0421b1fc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .sass-cache .DS_Store -node_modules \ No newline at end of file +node_modules +/**/*.js.map diff --git a/code/controllers/CMSMain.php b/code/controllers/CMSMain.php index 88568e84..f038ac5a 100644 --- a/code/controllers/CMSMain.php +++ b/code/controllers/CMSMain.php @@ -69,7 +69,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr Requirements::css(CMS_DIR . '/css/screen.css'); Requirements::customCSS($this->generatePageIconsCss()); Requirements::add_i18n_javascript(CMS_DIR . '/javascript/lang', false, true); - Requirements::javascript(CMS_DIR . '/javascript/dist/bundle-lib.js', [ + Requirements::javascript(CMS_DIR . '/javascript/dist/bundle-legacy.js', [ 'provides' => [ CMS_DIR . '/javascript/dist/CMSMain.AddForm.js', CMS_DIR . '/javascript/dist/CMSMain.EditForm.js', diff --git a/gulpfile.js b/gulpfile.js index 2fde3ee1..54c53833 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -4,6 +4,7 @@ var gulp = require('gulp'), notify = require('gulp-notify'), uglify = require('gulp-uglify'); gulpUtil = require('gulp-util'), + gulpif = require('gulp-if'), browserify = require('browserify'), babelify = require('babelify'), watchify = require('watchify'), @@ -13,7 +14,8 @@ var gulp = require('gulp'), glob = require('glob'), eventStream = require('event-stream'), semver = require('semver'), - packageJson = require('./package.json'); + packageJson = require('./package.json'), + sourcemaps = require('gulp-sourcemaps'); var PATHS = { MODULES: './node_modules', @@ -28,6 +30,10 @@ var browserifyOptions = { plugin: [watchify] }; +var isDev = typeof process.env.npm_config_development !== 'undefined'; + +process.env.NODE_ENV = isDev ? 'development' : 'production'; + /** * Transforms the passed JavaScript files to UMD modules. * @@ -41,7 +47,8 @@ function transformToUmd(files, dest) { .pipe(babel({ presets: ['es2015'], moduleId: 'ss.' + path.parse(file).name, - plugins: ['transform-es2015-modules-umd'] + plugins: ['transform-es2015-modules-umd'], + comments: false })) .on('error', notify.onError({ message: 'Error: <%= error.message %>', @@ -56,36 +63,36 @@ if (!semver.satisfies(process.versions.node, packageJson.engines.node)) { process.exit(1); } -if (process.env.npm_config_development) { +if (isDev) { browserifyOptions.debug = true; } -gulp.task('build', ['umd-cms', 'umd-watch', 'bundle-lib']); +var babelifyOptions = { + presets: ['es2015', 'react'], + ignore: /(node_modules|thirdparty)/, + comments: false +}; -gulp.task('bundle-lib', function bundleLib() { - var stream = browserify(Object.assign({}, browserifyOptions, { - entries: PATHS.CMS_JAVASCRIPT_SRC + '/bundles/lib.js' - })) - .transform(babelify.configure({ - presets: ['es2015'], - ignore: /(thirdparty)/ - })) - .on('log', function (msg) { gulpUtil.log('Finished bundle-lib.js ' + msg); }) - .on('update', bundleLib) - .external('jQuery') - .external('i18n') - .bundle() - .on('error', notify.onError({ - message: 'Error: <%= error.message %>', - })) - .pipe(source('bundle-lib.js')) - .pipe(buffer()); +gulp.task('build', ['umd-cms', 'umd-watch', 'bundle-legacy']); - if (typeof process.env.npm_config_development === 'undefined') { - stream.pipe(uglify()); - } +gulp.task('bundle-legacy', function bundleLeftAndMain() { + var bundleFileName = 'bundle-legacy.js'; - return stream.pipe(gulp.dest(PATHS.CMS_JAVASCRIPT_DIST)); + return browserify(Object.assign({}, browserifyOptions, { entries: PATHS.CMS_JAVASCRIPT_SRC + '/bundles/legacy.js' })) + .on('update', bundleLeftAndMain) + .on('log', function (msg) { gulpUtil.log('Finished', 'bundled ' + bundleFileName + ' ' + msg) }) + .transform('babelify', babelifyOptions) + .external('jQuery') + .external('i18n') + .external('router') + .bundle() + .on('error', notify.onError({ message: bundleFileName + ': <%= error.message %>' })) + .pipe(source(bundleFileName)) + .pipe(buffer()) + .pipe(sourcemaps.init({ loadMaps: true })) + .pipe(gulpif(!isDev, uglify())) + .pipe(sourcemaps.write('./')) + .pipe(gulp.dest(PATHS.CMS_JAVASCRIPT_DIST)); }); gulp.task('umd-cms', function () { diff --git a/javascript/dist/AssetAdmin.js b/javascript/dist/AssetAdmin.js index fdbfe43c..ab05186d 100644 --- a/javascript/dist/AssetAdmin.js +++ b/javascript/dist/AssetAdmin.js @@ -23,39 +23,9 @@ }; } - /** - * File: AssetAdmin.js - */ - _jQuery2.default.entwine('ss', function ($) { - /** - * Delete selected folders through "batch actions" tab. - */ - /* assets don't currently have batch actions; disabling for now - $(document).ready(function() { - $('#Form_BatchActionsForm').entwine('.ss.tree').register( - // TODO Hardcoding of base URL - 'admin/assets/batchactions/delete', - function(ids) { - var confirmed = confirm( - i18n.sprintf( - i18n._t('AssetAdmin.BATCHACTIONSDELETECONFIRM'), - ids.length - ) - ); - return (confirmed) ? ids : false; - } - ); - }); - */ - - /** - * Load folder detail view via controller methods - * rather than built-in GridField view (which is only geared towards showing files). - */ $('.AssetAdmin.cms-edit-form .ss-gridfield-item').entwine({ onclick: function onclick(e) { - // Let actions do their own thing if ($(e.target).closest('.action').length) { this._super(e); return; @@ -94,12 +64,6 @@ } }); - /** - * Prompt for a new foldername, rather than using dedicated form. - * Better usability, but less flexibility in terms of inputs and validation. - * Mainly necessary because AssetAdmin->AddForm() returns don't play nicely - * with the nested AssetAdmin->EditForm() DOM structures. - */ $('.AssetAdmin .cms-add-folder-link').entwine({ onclick: function onclick(e) { var name = prompt(_i18n2.default._t('Folder.Name')); @@ -110,17 +74,7 @@ } }); - /** - * Class: #Form_SyncForm - */ $('#Form_SyncForm').entwine({ - - /** - * Function: onsubmit - * - * Parameters: - * (Event) e - */ onsubmit: function onsubmit(e) { var button = jQuery(this).find(':submit:first'); button.addClass('loading'); @@ -129,16 +83,14 @@ data: this.serializeArray(), success: function success() { button.removeClass('loading'); - // reload current form and tree + var currNode = $('.cms-tree')[0].firstSelected(); if (currNode) { var url = $(currNode).find('a').attr('href'); $('.cms-content').loadPanel(url); } $('.cms-tree')[0].setCustomURL('admin/assets/getsubtree'); - $('.cms-tree')[0].reload({ onSuccess: function onSuccess() { - // TODO Reset current tree node - } }); + $('.cms-tree')[0].reload({ onSuccess: function onSuccess() {} }); } }); @@ -146,9 +98,6 @@ } }); - /** - * Reload the gridfield to show the user the file has been added - */ $('.AssetAdmin.cms-edit-form .ss-uploadfield-item-progress').entwine({ onunmatch: function onunmatch() { $('.AssetAdmin.cms-edit-form .ss-gridfield').reload(); diff --git a/javascript/dist/CMSMain.AddForm.js b/javascript/dist/CMSMain.AddForm.js index 25cae0a7..a0098c61 100644 --- a/javascript/dist/CMSMain.AddForm.js +++ b/javascript/dist/CMSMain.AddForm.js @@ -22,10 +22,6 @@ } _jQuery2.default.entwine('ss', function ($) { - /** - * Reset the parent node selection if the type is - * set back to "toplevel page", to avoid submitting inconsistent state. - */ $(".cms-add-form .parent-mode :input").entwine({ onclick: function onclick(e) { if (this.val() == 'top') { @@ -37,8 +33,8 @@ }); $(".cms-add-form").entwine({ - ParentID: 0, // Last selected parentID - ParentCache: {}, // Cache allowed children for each selected page + ParentID: 0, + ParentCache: {}, onadd: function onadd() { var self = this; this.find('#Form_AddForm_ParentID_Holder .TreeDropdownField').bind('change', function () { @@ -58,12 +54,7 @@ cache[parentID] = children; this.setParentCache(cache); }, - /** - * Limit page type selection based on parent selection. - * Select of root classes is pre-computed, but selections with a given parent - * are updated on-demand. - * Similar implementation to LeftAndMain.Tree.js. - */ + updateTypeList: function updateTypeList() { var hints = this.data('hints'), parentTree = this.find('#Form_AddForm_ParentID_Holder .TreeDropdownField'), @@ -78,15 +69,12 @@ disallowedChildren = []; if (id) { - // Prevent interface operations if (this.hasClass('loading')) return; this.addClass('loading'); - // Enable last parent ID to be re-selected from memory this.setParentID(id); if (!parentTree.getValue()) parentTree.setValue(id); - // Use cached data if available disallowedChildren = this.loadCachedChildren(id); if (disallowedChildren !== null) { this.updateSelectionFilter(disallowedChildren, defaultChildClass); @@ -97,7 +85,6 @@ url: self.data('childfilter'), data: { 'ParentID': id }, success: function success(data) { - // reload current form and tree self.saveCachedChildren(id, data); self.updateSelectionFilter(data, defaultChildClass); }, @@ -111,15 +98,9 @@ disallowedChildren = hint && typeof hint.disallowedChildren !== 'undefined' ? hint.disallowedChildren : [], this.updateSelectionFilter(disallowedChildren, defaultChildClass); } }, - /** - * Update the selection filter with the given blacklist and default selection - * - * @param array disallowedChildren - * @param string defaultChildClass - */ + updateSelectionFilter: function updateSelectionFilter(disallowedChildren, defaultChildClass) { - // Limit selection - var allAllowed = null; // troolian + var allAllowed = null; this.find('#Form_AddForm_PageType li').each(function () { var className = $(this).find('input').val(), isAllowed = $.inArray(className, disallowedChildren) === -1; @@ -129,7 +110,6 @@ if (allAllowed === null) allAllowed = isAllowed;else allAllowed = allAllowed && isAllowed; }); - // Set default child selection, or fall back to first available option if (defaultChildClass) { var selectedEl = this.find('#Form_AddForm_PageType li input[value=' + defaultChildClass + ']').parents('li:first'); } else { @@ -138,7 +118,6 @@ selectedEl.setSelected(true); selectedEl.siblings().setSelected(false); - // Disable the "Create" button if none of the pagetypes are available var buttonState = this.find('#Form_AddForm_PageType li:not(.disabled)').length ? 'enable' : 'disable'; this.find('button[name=action_doAdd]').button(buttonState); @@ -173,7 +152,6 @@ list = $('.cms-list'), parentId = 0; - // Choose parent ID either from tree or list view, depending which is visible if (tree.is(':visible')) { var selected = tree.jstree('get_selected'); parentId = selected ? $(selected[0]).data('id') : null; @@ -194,11 +172,7 @@ $('.cms-container').loadPanel(url, null, data); e.preventDefault(); - // Remove focussed state from button this.blur(); - - // $('.cms-page-add-form-dialog').dialog('open'); - // e.preventDefault(); } }); }); diff --git a/javascript/dist/CMSMain.EditForm.js b/javascript/dist/CMSMain.EditForm.js index 035d9935..1cea35de 100644 --- a/javascript/dist/CMSMain.EditForm.js +++ b/javascript/dist/CMSMain.EditForm.js @@ -23,31 +23,14 @@ }; } - /** - * File: CMSMain.EditForm.js - */ - - _jQuery2.default.entwine('ss', function ($) { - /** - * Class: .cms-edit-form :input[name=ClassName] - * Alert the user on change of page-type. This might have implications - * on the available form fields etc. - */ $('.cms-edit-form :input[name=ClassName]').entwine({ - // Function: onchange onchange: function onchange() { alert(_i18n2.default._t('CMSMAIN.ALERTCLASSNAME')); } }); - /** - * Class: .cms-edit-form input[name=Title] - * - * Input validation on the Title field - */ $('.cms-edit-form input[name=Title]').entwine({ - // Constructor: onmatch onmatch: function onmatch() { var self = this; @@ -64,7 +47,6 @@ var title = self.val(); self.data('OrigVal', title); - // Criteria for defining a "new" page if (urlSegmentInput.val().indexOf(urlSegmentInput.data('defaultUrl')) === 0 && liveLinkInput.val() == '') { self.updateURLSegment(title); } else { @@ -82,31 +64,17 @@ this._super(); }, - /** - * Function: updateRelatedFields - * - * Update the related fields if appropriate - * (String) title The new title - * (Stirng) origTitle The original title - */ updateRelatedFields: function updateRelatedFields(title, origTitle) { - // Update these fields only if their value was originally the same as the title this.parents('form').find('input[name=MetaTitle], input[name=MenuTitle]').each(function () { var $this = $(this); if ($this.val() == origTitle) { $this.val(title); - // Onchange bubbling didn't work in IE8, so .trigger('change') couldn't be used + if ($this.updatedRelatedFields) $this.updatedRelatedFields(); } }); }, - /** - * Function: updateURLSegment - * - * Update the URLSegment - * (String) title - */ updateURLSegment: function updateURLSegment(title) { var urlSegmentInput = $('input:text[name=URLSegment]', this.closest('form')); var urlSegmentField = urlSegmentInput.closest('.field.urlsegment'); @@ -117,12 +85,6 @@ } }, - /** - * Function: updateBreadcrumbLabel - * - * Update the breadcrumb - * (String) title - */ updateBreadcrumbLabel: function updateBreadcrumbLabel(title) { var pageID = $('.cms-edit-form input[name=ID]').val(); var panelCrumb = $('span.cms-panel-link.crumb'); @@ -131,17 +93,10 @@ } }, - /** - * Function: _addActions - * - * Utility to add update from title action - * - */ _addActions: function _addActions() { var self = this; var updateURLFromTitle; - // update button updateURLFromTitle = $('