Dan Brown

Updated build and versioning system

Added versioning file instead of using git tags
(Step towards removing git as a dependancy in the future)

Updated gulpfile to fit with verisioning system and cleaned
up node dependancies.

Fixes #108
...@@ -12,3 +12,4 @@ Homestead.yaml ...@@ -12,3 +12,4 @@ Homestead.yaml
12 _ide_helper.php 12 _ide_helper.php
13 /storage/debugbar 13 /storage/debugbar
14 .phpstorm.meta.php 14 .phpstorm.meta.php
15 +yarn.lock
......
...@@ -17,10 +17,7 @@ class SettingController extends Controller ...@@ -17,10 +17,7 @@ class SettingController extends Controller
17 $this->setPageTitle('Settings'); 17 $this->setPageTitle('Settings');
18 18
19 // Get application version 19 // Get application version
20 - $version = false; 20 + $version = trim(file_get_contents(base_path('version')));
21 - if (function_exists('exec')) {
22 - $version = exec('git describe --always --tags ');
23 - }
24 21
25 return view('settings/index', ['version' => $version]); 22 return view('settings/index', ['version' => $version]);
26 } 23 }
......
...@@ -11,29 +11,20 @@ use BookStack\Ownable; ...@@ -11,29 +11,20 @@ use BookStack\Ownable;
11 */ 11 */
12 function versioned_asset($file = '') 12 function versioned_asset($file = '')
13 { 13 {
14 - // Don't require css and JS assets for testing 14 + static $version = null;
15 - if (config('app.env') === 'testing') return ''; 15 +
16 - 16 + if (is_null($version)) {
17 - static $manifest = null; 17 + $versionFile = base_path('version');
18 - $manifestPath = 'build/manifest.json'; 18 + $version = trim(file_get_contents($versionFile));
19 -
20 - if (is_null($manifest) && file_exists($manifestPath)) {
21 - $manifest = json_decode(file_get_contents(public_path($manifestPath)), true);
22 - } else if (!file_exists($manifestPath)) {
23 - if (config('app.env') !== 'production') {
24 - $path = public_path($manifestPath);
25 - $error = "No {$path} file found, Ensure you have built the css/js assets using gulp.";
26 - } else {
27 - $error = "No {$manifestPath} file found, Ensure you are using the release version of BookStack";
28 - }
29 - throw new \Exception($error);
30 } 19 }
31 20
32 - if (isset($manifest[$file])) { 21 + $additional = '';
33 - return baseUrl($manifest[$file]); 22 + if (config('app.env') === 'development') {
23 + $additional = sha1_file(public_path($file));
34 } 24 }
35 25
36 - throw new InvalidArgumentException("File {$file} not defined in asset manifest."); 26 + $path = $file . '?version=' . urlencode($version) . $additional;
27 + return baseUrl($path);
37 } 28 }
38 29
39 /** 30 /**
......
1 var elixir = require('laravel-elixir'); 1 var elixir = require('laravel-elixir');
2 2
3 -// Custom extensions 3 +elixir(mix => {
4 -var gulp = require('gulp'); 4 + mix.sass('styles.scss');
5 -var Task = elixir.Task; 5 + mix.sass('print-styles.scss');
6 -var fs = require('fs'); 6 + mix.sass('export-styles.scss');
7 - 7 + mix.browserify('global.js', './public/js/common.js');
8 -elixir.extend('queryVersion', function(inputFiles) {
9 - new Task('queryVersion', function() {
10 - var manifestObject = {};
11 - var uidString = Date.now().toString(16).slice(4);
12 - for (var i = 0; i < inputFiles.length; i++) {
13 - var file = inputFiles[i];
14 - manifestObject[file] = file + '?version=' + uidString;
15 - }
16 - var fileContents = JSON.stringify(manifestObject, null, 1);
17 - fs.writeFileSync('public/build/manifest.json', fileContents);
18 - }).watch(['./public/css/*.css', './public/js/*.js']);
19 -});
20 -
21 -elixir(function(mix) {
22 - mix.sass('styles.scss')
23 - .sass('print-styles.scss')
24 - .sass('export-styles.scss')
25 - .browserify('global.js', 'public/js/common.js')
26 - .queryVersion(['css/styles.css', 'css/print-styles.css', 'js/common.js']);
27 }); 8 });
......
1 { 1 {
2 "private": true, 2 "private": true,
3 - "devDependencies": { 3 + "scripts": {
4 - "gulp": "^3.9.0" 4 + "prod": "gulp --production",
5 + "dev": "gulp watch"
5 }, 6 },
6 - "dependencies": { 7 + "devDependencies": {
7 "angular": "^1.5.5", 8 "angular": "^1.5.5",
8 "angular-animate": "^1.5.5", 9 "angular-animate": "^1.5.5",
9 "angular-resource": "^1.5.5", 10 "angular-resource": "^1.5.5",
10 "angular-sanitize": "^1.5.5", 11 "angular-sanitize": "^1.5.5",
11 - "angular-ui-sortable": "^0.14.0", 12 + "angular-ui-sortable": "^0.15.0",
12 - "babel-runtime": "^5.8.29",
13 - "bootstrap-sass": "^3.0.0",
14 "dropzone": "^4.0.1", 13 "dropzone": "^4.0.1",
15 - "laravel-elixir": "^5.0.0", 14 + "gulp": "^3.9.0",
15 + "laravel-elixir": "^6.0.0-11",
16 + "laravel-elixir-browserify-official": "^0.1.3",
16 "marked": "^0.3.5", 17 "marked": "^0.3.5",
17 "moment": "^2.12.0", 18 "moment": "^2.12.0",
18 "zeroclipboard": "^2.2.0" 19 "zeroclipboard": "^2.2.0"
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
30 <env name="AUTH_METHOD" value="standard"/> 30 <env name="AUTH_METHOD" value="standard"/>
31 <env name="DISABLE_EXTERNAL_SERVICES" value="true"/> 31 <env name="DISABLE_EXTERNAL_SERVICES" value="true"/>
32 <env name="LDAP_VERSION" value="3"/> 32 <env name="LDAP_VERSION" value="3"/>
33 + <env name="STORAGE_TYPE" value="local"/>
33 <env name="GITHUB_APP_ID" value="aaaaaaaaaaaaaa"/> 34 <env name="GITHUB_APP_ID" value="aaaaaaaaaaaaaa"/>
34 <env name="GITHUB_APP_SECRET" value="aaaaaaaaaaaaaa"/> 35 <env name="GITHUB_APP_SECRET" value="aaaaaaaaaaaaaa"/>
35 <env name="GOOGLE_APP_ID" value="aaaaaaaaaaaaaa"/> 36 <env name="GOOGLE_APP_ID" value="aaaaaaaaaaaaaa"/>
......
...@@ -2,13 +2,15 @@ ...@@ -2,13 +2,15 @@
2 2
3 [![GitHub release](https://img.shields.io/github/release/ssddanbrown/BookStack.svg?maxAge=2592000)](https://github.com/ssddanbrown/BookStack/releases/latest) 3 [![GitHub release](https://img.shields.io/github/release/ssddanbrown/BookStack.svg?maxAge=2592000)](https://github.com/ssddanbrown/BookStack/releases/latest)
4 [![license](https://img.shields.io/github/license/ssddanbrown/BookStack.svg?maxAge=2592000)](https://github.com/ssddanbrown/BookStack/blob/master/LICENSE) 4 [![license](https://img.shields.io/github/license/ssddanbrown/BookStack.svg?maxAge=2592000)](https://github.com/ssddanbrown/BookStack/blob/master/LICENSE)
5 -[![Build Status](https://travis-ci.org/ssddanbrown/BookStack.svg)](https://travis-ci.org/ssddanbrown/BookStack) 5 +[![Build Status](https://travis-ci.org/BookStackApp/BookStack.svg)](https://travis-ci.org/BookStackApp/BookStack)
6 6
7 A platform for storing and organising information and documentation. General information and documentation for BookStack can be found at https://www.bookstackapp.com/. 7 A platform for storing and organising information and documentation. General information and documentation for BookStack can be found at https://www.bookstackapp.com/.
8 8
9 * [Installation Instructions](https://www.bookstackapp.com/docs/admin/installation) 9 * [Installation Instructions](https://www.bookstackapp.com/docs/admin/installation)
10 * [Documentation](https://www.bookstackapp.com/docs) 10 * [Documentation](https://www.bookstackapp.com/docs)
11 -* [Demo Instance](https://demo.bookstackapp.com) *(Login username: `admin@example.com`. Password: `password`)* 11 +* [Demo Instance](https://demo.bookstackapp.com)
12 + * *Username: `admin@example.com`*
13 + * *Password: `password`*
12 * [BookStack Blog](https://www.bookstackapp.com/blog) 14 * [BookStack Blog](https://www.bookstackapp.com/blog)
13 15
14 ## Development & Testing 16 ## Development & Testing
...@@ -29,7 +31,7 @@ php artisan migrate --database=mysql_testing ...@@ -29,7 +31,7 @@ php artisan migrate --database=mysql_testing
29 php artisan db:seed --class=DummyContentSeeder --database=mysql_testing 31 php artisan db:seed --class=DummyContentSeeder --database=mysql_testing
30 ``` 32 ```
31 33
32 -Once done you can run `phpunit` (or `./vendor/bin/phpunit` if `phpunit` is not found) in the application root directory to run all tests. 34 +Once done you can run `phpunit` in the application root directory to run all tests.
33 35
34 ## License 36 ## License
35 37
...@@ -51,3 +53,5 @@ These are the great projects used to help build BookStack: ...@@ -51,3 +53,5 @@ These are the great projects used to help build BookStack:
51 * [TinyColorPicker](http://www.dematte.at/tinyColorPicker/index.html) 53 * [TinyColorPicker](http://www.dematte.at/tinyColorPicker/index.html)
52 * [Marked](https://github.com/chjj/marked) 54 * [Marked](https://github.com/chjj/marked)
53 * [Moment.js](http://momentjs.com/) 55 * [Moment.js](http://momentjs.com/)
56 +
57 +Additionally, Thank you [BrowserStack](https://www.browserstack.com/) for supporting us and making cross-browser testing easy.
......
1 -<div class="dropzone-container">
2 - <div class="dz-message">Drop files or click here to upload</div>
3 -</div>
...\ No newline at end of file ...\ No newline at end of file
1 -
2 -<div class="image-picker">
3 - <div>
4 - <img ng-if="image && image !== 'none'" ng-src="{{image}}" ng-class="{{imageClass}}" alt="Image Preview">
5 - <img ng-if="image === '' && defaultImage" ng-src="{{defaultImage}}" ng-class="{{imageClass}}" alt="Image Preview">
6 - </div>
7 - <button class="button" type="button" ng-click="showImageManager()">Select Image</button>
8 - <br>
9 -
10 - <button class="text-button" ng-click="reset()" type="button">Reset</button>
11 - <span ng-show="showRemove" class="sep">|</span>
12 - <button ng-show="showRemove" class="text-button neg" ng-click="remove()" type="button">Remove</button>
13 -
14 - <input type="hidden" ng-attr-name="{{name}}" ng-attr-id="{{name}}" ng-attr-value="{{value}}">
15 -</div>
...\ No newline at end of file ...\ No newline at end of file
1 -<div class="toggle-switch" ng-click="switch()" ng-class="{'active': isActive}">
2 - <input type="hidden" ng-attr-name="{{name}}" ng-attr-value="{{value}}"/>
3 - <div class="switch-handle"></div>
4 -</div>
...\ No newline at end of file ...\ No newline at end of file
1 "use strict"; 1 "use strict";
2 2
3 -const moment = require('moment'); 3 +import moment from 'moment';
4 +import 'moment/locale/en-gb';
5 +moment.locale('en-gb');
4 6
5 module.exports = function (ngApp, events) { 7 module.exports = function (ngApp, events) {
6 8
...@@ -729,20 +731,3 @@ module.exports = function (ngApp, events) { ...@@ -729,20 +731,3 @@ module.exports = function (ngApp, events) {
729 }]); 731 }]);
730 732
731 }; 733 };
732 -
733 -
734 -
735 -
736 -
737 -
738 -
739 -
740 -
741 -
742 -
743 -
744 -
745 -
746 -
747 -
748 -
......
...@@ -2,10 +2,6 @@ ...@@ -2,10 +2,6 @@
2 const DropZone = require('dropzone'); 2 const DropZone = require('dropzone');
3 const markdown = require('marked'); 3 const markdown = require('marked');
4 4
5 -const toggleSwitchTemplate = require('./components/toggle-switch.html');
6 -const imagePickerTemplate = require('./components/image-picker.html');
7 -const dropZoneTemplate = require('./components/drop-zone.html');
8 -
9 module.exports = function (ngApp, events) { 5 module.exports = function (ngApp, events) {
10 6
11 /** 7 /**
...@@ -16,7 +12,12 @@ module.exports = function (ngApp, events) { ...@@ -16,7 +12,12 @@ module.exports = function (ngApp, events) {
16 ngApp.directive('toggleSwitch', function () { 12 ngApp.directive('toggleSwitch', function () {
17 return { 13 return {
18 restrict: 'A', 14 restrict: 'A',
19 - template: toggleSwitchTemplate, 15 + template: `
16 + <div class="toggle-switch" ng-click="switch()" ng-class="{'active': isActive}">
17 + <input type="hidden" ng-attr-name="{{name}}" ng-attr-value="{{value}}"/>
18 + <div class="switch-handle"></div>
19 + </div>
20 + `,
20 scope: true, 21 scope: true,
21 link: function (scope, element, attrs) { 22 link: function (scope, element, attrs) {
22 scope.name = attrs.name; 23 scope.name = attrs.name;
...@@ -94,7 +95,22 @@ module.exports = function (ngApp, events) { ...@@ -94,7 +95,22 @@ module.exports = function (ngApp, events) {
94 ngApp.directive('imagePicker', ['$http', 'imageManagerService', function ($http, imageManagerService) { 95 ngApp.directive('imagePicker', ['$http', 'imageManagerService', function ($http, imageManagerService) {
95 return { 96 return {
96 restrict: 'E', 97 restrict: 'E',
97 - template: imagePickerTemplate, 98 + template: `
99 + <div class="image-picker">
100 + <div>
101 + <img ng-if="image && image !== 'none'" ng-src="{{image}}" ng-class="{{imageClass}}" alt="Image Preview">
102 + <img ng-if="image === '' && defaultImage" ng-src="{{defaultImage}}" ng-class="{{imageClass}}" alt="Image Preview">
103 + </div>
104 + <button class="button" type="button" ng-click="showImageManager()">Select Image</button>
105 + <br>
106 +
107 + <button class="text-button" ng-click="reset()" type="button">Reset</button>
108 + <span ng-show="showRemove" class="sep">|</span>
109 + <button ng-show="showRemove" class="text-button neg" ng-click="remove()" type="button">Remove</button>
110 +
111 + <input type="hidden" ng-attr-name="{{name}}" ng-attr-id="{{name}}" ng-attr-value="{{value}}">
112 + </div>
113 + `,
98 scope: { 114 scope: {
99 name: '@', 115 name: '@',
100 resizeHeight: '@', 116 resizeHeight: '@',
...@@ -161,7 +177,11 @@ module.exports = function (ngApp, events) { ...@@ -161,7 +177,11 @@ module.exports = function (ngApp, events) {
161 ngApp.directive('dropZone', [function () { 177 ngApp.directive('dropZone', [function () {
162 return { 178 return {
163 restrict: 'E', 179 restrict: 'E',
164 - template: dropZoneTemplate, 180 + template: `
181 + <div class="dropzone-container">
182 + <div class="dz-message">Drop files or click here to upload</div>
183 + </div>
184 + `,
165 scope: { 185 scope: {
166 uploadUrl: '@', 186 uploadUrl: '@',
167 eventSuccess: '=', 187 eventSuccess: '=',
...@@ -904,17 +924,3 @@ module.exports = function (ngApp, events) { ...@@ -904,17 +924,3 @@ module.exports = function (ngApp, events) {
904 }; 924 };
905 }]); 925 }]);
906 }; 926 };
907 -
908 -
909 -
910 -
911 -
912 -
913 -
914 -
915 -
916 -
917 -
918 -
919 -
920 -
......
1 +v0.13-dev