diff --git a/.gitignore b/.gitignore index 7417bbdd840..362df57e13a 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,5 @@ Homestead.yaml /storage/images _ide_helper.php /storage/debugbar -.phpstorm.meta.php \ No newline at end of file +.phpstorm.meta.php +yarn.lock diff --git a/app/Http/Controllers/SettingController.php b/app/Http/Controllers/SettingController.php index 61ce55fa940..65135eda381 100644 --- a/app/Http/Controllers/SettingController.php +++ b/app/Http/Controllers/SettingController.php @@ -17,10 +17,7 @@ public function index() $this->setPageTitle('Settings'); // Get application version - $version = false; - if (function_exists('exec')) { - $version = exec('git describe --always --tags '); - } + $version = trim(file_get_contents(base_path('version'))); return view('settings/index', ['version' => $version]); } diff --git a/app/helpers.php b/app/helpers.php index ad1c7dd20ce..b5be0fd11ba 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -11,29 +11,20 @@ */ function versioned_asset($file = '') { - // Don't require css and JS assets for testing - if (config('app.env') === 'testing') return ''; - - static $manifest = null; - $manifestPath = 'build/manifest.json'; - - if (is_null($manifest) && file_exists($manifestPath)) { - $manifest = json_decode(file_get_contents(public_path($manifestPath)), true); - } else if (!file_exists($manifestPath)) { - if (config('app.env') !== 'production') { - $path = public_path($manifestPath); - $error = "No {$path} file found, Ensure you have built the css/js assets using gulp."; - } else { - $error = "No {$manifestPath} file found, Ensure you are using the release version of BookStack"; - } - throw new \Exception($error); + static $version = null; + + if (is_null($version)) { + $versionFile = base_path('version'); + $version = trim(file_get_contents($versionFile)); } - if (isset($manifest[$file])) { - return baseUrl($manifest[$file]); + $additional = ''; + if (config('app.env') === 'development') { + $additional = sha1_file(public_path($file)); } - throw new InvalidArgumentException("File {$file} not defined in asset manifest."); + $path = $file . '?version=' . urlencode($version) . $additional; + return baseUrl($path); } /** @@ -138,14 +129,14 @@ function sortUrl($path, $data, $overrideData = []) { $queryStringSections = []; $queryData = array_merge($data, $overrideData); - + // Change sorting direction is already sorted on current attribute if (isset($overrideData['sort']) && $overrideData['sort'] === $data['sort']) { $queryData['order'] = ($data['order'] === 'asc') ? 'desc' : 'asc'; } else { $queryData['order'] = 'asc'; } - + foreach ($queryData as $name => $value) { $trimmedVal = trim($value); if ($trimmedVal === '') continue; @@ -155,4 +146,4 @@ function sortUrl($path, $data, $overrideData = []) if (count($queryStringSections) === 0) return $path; return baseUrl($path . '?' . implode('&', $queryStringSections)); -} \ No newline at end of file +} diff --git a/gulpfile.js b/gulpfile.js index 7deefc71ac2..9d789d9b4c4 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,27 +1,8 @@ var elixir = require('laravel-elixir'); -// Custom extensions -var gulp = require('gulp'); -var Task = elixir.Task; -var fs = require('fs'); - -elixir.extend('queryVersion', function(inputFiles) { - new Task('queryVersion', function() { - var manifestObject = {}; - var uidString = Date.now().toString(16).slice(4); - for (var i = 0; i < inputFiles.length; i++) { - var file = inputFiles[i]; - manifestObject[file] = file + '?version=' + uidString; - } - var fileContents = JSON.stringify(manifestObject, null, 1); - fs.writeFileSync('public/build/manifest.json', fileContents); - }).watch(['./public/css/*.css', './public/js/*.js']); -}); - -elixir(function(mix) { - mix.sass('styles.scss') - .sass('print-styles.scss') - .sass('export-styles.scss') - .browserify('global.js', 'public/js/common.js') - .queryVersion(['css/styles.css', 'css/print-styles.css', 'js/common.js']); +elixir(mix => { + mix.sass('styles.scss'); + mix.sass('print-styles.scss'); + mix.sass('export-styles.scss'); + mix.browserify('global.js', './public/js/common.js'); }); diff --git a/package.json b/package.json index fde090beb73..30f288d451b 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,19 @@ { "private": true, - "devDependencies": { - "gulp": "^3.9.0" + "scripts": { + "prod": "gulp --production", + "dev": "gulp watch" }, - "dependencies": { + "devDependencies": { "angular": "^1.5.5", "angular-animate": "^1.5.5", "angular-resource": "^1.5.5", "angular-sanitize": "^1.5.5", - "angular-ui-sortable": "^0.14.0", - "babel-runtime": "^5.8.29", - "bootstrap-sass": "^3.0.0", + "angular-ui-sortable": "^0.15.0", "dropzone": "^4.0.1", - "laravel-elixir": "^5.0.0", + "gulp": "^3.9.0", + "laravel-elixir": "^6.0.0-11", + "laravel-elixir-browserify-official": "^0.1.3", "marked": "^0.3.5", "moment": "^2.12.0", "zeroclipboard": "^2.2.0" diff --git a/phpunit.xml b/phpunit.xml index a2b26d4132f..72e06a3fc53 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -30,6 +30,7 @@ + diff --git a/public/build/.gitignore b/public/build/.gitignore deleted file mode 100644 index d6b7ef32c84..00000000000 --- a/public/build/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore diff --git a/readme.md b/readme.md index 3a745beb11a..5d3e79a2e07 100644 --- a/readme.md +++ b/readme.md @@ -2,13 +2,15 @@ [![GitHub release](https://img.shields.io/github/release/ssddanbrown/BookStack.svg?maxAge=2592000)](https://github.com/ssddanbrown/BookStack/releases/latest) [![license](https://img.shields.io/github/license/ssddanbrown/BookStack.svg?maxAge=2592000)](https://github.com/ssddanbrown/BookStack/blob/master/LICENSE) -[![Build Status](https://travis-ci.org/ssddanbrown/BookStack.svg)](https://travis-ci.org/ssddanbrown/BookStack) +[![Build Status](https://travis-ci.org/BookStackApp/BookStack.svg)](https://travis-ci.org/BookStackApp/BookStack) A platform for storing and organising information and documentation. General information and documentation for BookStack can be found at https://www.bookstackapp.com/. * [Installation Instructions](https://www.bookstackapp.com/docs/admin/installation) * [Documentation](https://www.bookstackapp.com/docs) -* [Demo Instance](https://demo.bookstackapp.com) *(Login username: `admin@example.com`. Password: `password`)* +* [Demo Instance](https://demo.bookstackapp.com) + * *Username: `admin@example.com`* + * *Password: `password`* * [BookStack Blog](https://www.bookstackapp.com/blog) ## Development & Testing @@ -29,7 +31,7 @@ php artisan migrate --database=mysql_testing php artisan db:seed --class=DummyContentSeeder --database=mysql_testing ``` -Once done you can run `phpunit` (or `./vendor/bin/phpunit` if `phpunit` is not found) in the application root directory to run all tests. +Once done you can run `phpunit` in the application root directory to run all tests. ## License @@ -51,3 +53,5 @@ These are the great projects used to help build BookStack: * [TinyColorPicker](http://www.dematte.at/tinyColorPicker/index.html) * [Marked](https://github.com/chjj/marked) * [Moment.js](http://momentjs.com/) + +Additionally, Thank you [BrowserStack](https://www.browserstack.com/) for supporting us and making cross-browser testing easy. diff --git a/resources/assets/js/components/drop-zone.html b/resources/assets/js/components/drop-zone.html deleted file mode 100644 index 26e0ee2aa2f..00000000000 --- a/resources/assets/js/components/drop-zone.html +++ /dev/null @@ -1,3 +0,0 @@ -
-
Drop files or click here to upload
-
\ No newline at end of file diff --git a/resources/assets/js/components/image-picker.html b/resources/assets/js/components/image-picker.html deleted file mode 100644 index 1a07b9274e1..00000000000 --- a/resources/assets/js/components/image-picker.html +++ /dev/null @@ -1,15 +0,0 @@ - -
-
- Image Preview - Image Preview -
- -
- - - | - - - -
\ No newline at end of file diff --git a/resources/assets/js/components/toggle-switch.html b/resources/assets/js/components/toggle-switch.html deleted file mode 100644 index 455969a84be..00000000000 --- a/resources/assets/js/components/toggle-switch.html +++ /dev/null @@ -1,4 +0,0 @@ -
- -
-
\ No newline at end of file diff --git a/resources/assets/js/controllers.js b/resources/assets/js/controllers.js index 99cf6af9d65..f4f1f3e3926 100644 --- a/resources/assets/js/controllers.js +++ b/resources/assets/js/controllers.js @@ -1,6 +1,8 @@ "use strict"; -const moment = require('moment'); +import moment from 'moment'; +import 'moment/locale/en-gb'; +moment.locale('en-gb'); module.exports = function (ngApp, events) { @@ -17,7 +19,7 @@ module.exports = function (ngApp, events) { $scope.imageDeleteSuccess = false; $scope.uploadedTo = $attrs.uploadedTo; $scope.view = 'all'; - + $scope.searching = false; $scope.searchTerm = ''; @@ -48,7 +50,7 @@ module.exports = function (ngApp, events) { $scope.hasMore = preSearchHasMore; } $scope.cancelSearch = cancelSearch; - + /** * Runs on image upload, Adds an image to local list of images @@ -437,7 +439,7 @@ module.exports = function (ngApp, events) { const pageId = Number($attrs.pageId); $scope.tags = []; - + $scope.sortOptions = { handle: '.handle', items: '> tr', @@ -729,20 +731,3 @@ module.exports = function (ngApp, events) { }]); }; - - - - - - - - - - - - - - - - - diff --git a/resources/assets/js/directives.js b/resources/assets/js/directives.js index fa6c2c3be03..44d1a14e1a1 100644 --- a/resources/assets/js/directives.js +++ b/resources/assets/js/directives.js @@ -2,10 +2,6 @@ const DropZone = require('dropzone'); const markdown = require('marked'); -const toggleSwitchTemplate = require('./components/toggle-switch.html'); -const imagePickerTemplate = require('./components/image-picker.html'); -const dropZoneTemplate = require('./components/drop-zone.html'); - module.exports = function (ngApp, events) { /** @@ -16,7 +12,12 @@ module.exports = function (ngApp, events) { ngApp.directive('toggleSwitch', function () { return { restrict: 'A', - template: toggleSwitchTemplate, + template: ` +
+ +
+
+ `, scope: true, link: function (scope, element, attrs) { scope.name = attrs.name; @@ -77,7 +78,7 @@ module.exports = function (ngApp, events) { }); element.find('button[type="submit"]').click(submitEvent); - + function submitEvent(e) { e.preventDefault() if (attrs.subForm) scope.$eval(attrs.subForm); @@ -94,7 +95,22 @@ module.exports = function (ngApp, events) { ngApp.directive('imagePicker', ['$http', 'imageManagerService', function ($http, imageManagerService) { return { restrict: 'E', - template: imagePickerTemplate, + template: ` +
+
+ Image Preview + Image Preview +
+ +
+ + + | + + + +
+ `, scope: { name: '@', resizeHeight: '@', @@ -161,7 +177,11 @@ module.exports = function (ngApp, events) { ngApp.directive('dropZone', [function () { return { restrict: 'E', - template: dropZoneTemplate, + template: ` +
+
Drop files or click here to upload
+
+ `, scope: { uploadUrl: '@', eventSuccess: '=', @@ -603,7 +623,7 @@ module.exports = function (ngApp, events) { let val = $input.val(); let url = $input.attr('autosuggest'); let type = $input.attr('autosuggest-type'); - + // Add name param to request if for a value if (type.toLowerCase() === 'value') { let $nameInput = $input.closest('tr').find('[autosuggest-type="name"]').first(); @@ -904,17 +924,3 @@ module.exports = function (ngApp, events) { }; }]); }; - - - - - - - - - - - - - - diff --git a/version b/version new file mode 100644 index 00000000000..8287f2896ba --- /dev/null +++ b/version @@ -0,0 +1 @@ +v0.13-dev