Move traditional-website files to a new bootstrap folder and use vue as the default public facing front-end rather than trying to offer both simultaneously

This commit is contained in:
Kevin MacMartin 2018-04-15 21:05:42 -04:00
parent eb946e26cb
commit 3c048f6096
19 changed files with 438 additions and 180 deletions

22
gulpfile.js vendored
View file

@ -38,17 +38,8 @@ const sassOutputStyle = isProduction ? "compressed" : "nested",
autoprefixerSettings = { remove: false, cascade: false, browsers: [ "last 6 versions" ] }, autoprefixerSettings = { remove: false, cascade: false, browsers: [ "last 6 versions" ] },
vuePaths = [ "./bower_components", "./node_modules", "./resources/components", "./resources/assets/js" ]; vuePaths = [ "./bower_components", "./node_modules", "./resources/components", "./resources/assets/js" ];
// Vue file for the public site
const vuePublic = "resources/assets/js/app-vue.js";
// Javascript files for the public site // Javascript files for the public site
const jsPublic = [ const jsPublic = [ "resources/assets/js/app.js" ];
"resources/assets/js/site-vars.js",
"resources/assets/js/nav.js",
"resources/assets/js/contact.js",
"resources/assets/js/subscription.js",
"resources/assets/js/app.js"
];
// Javascript libraries for the public site // Javascript libraries for the public site
const jsPublicLibs = [ const jsPublicLibs = [
@ -149,14 +140,9 @@ gulp.task("sass-dashboard", () => {
return processSass("dashboard"); return processSass("dashboard");
}); });
// Task for public vue
gulp.task("js-public-vue", () => {
return processVue("app-vue", vuePublic);
});
// Task for public javascript // Task for public javascript
gulp.task("js-public", () => { gulp.task("js-public", () => {
return processJavaScript("app", jsPublic, true); return processVue("app", jsPublic);
}); });
// Task for public javascript libraries // Task for public javascript libraries
@ -203,8 +189,7 @@ gulp.task("watch", () => {
}); });
gulp.watch([ "app/**/*.php", "routes/**/*.php", "resources/views/**/*.blade.php" ], gulp.series(browserSyncReload)); gulp.watch([ "app/**/*.php", "routes/**/*.php", "resources/views/**/*.blade.php" ], gulp.series(browserSyncReload));
gulp.watch([ vuePublic, "resources/assets/js/mixins/**/*.js", "resources/components/**/*.vue" ], gulp.series("js-public-vue", browserSyncReload)); gulp.watch([ jsPublic, "resources/assets/js/mixins/**/*.js", "resources/components/**/*.vue" ], gulp.series("js-public", browserSyncReload));
gulp.watch(jsPublic, gulp.series("js-public", browserSyncReload));
gulp.watch(jsDashboard, gulp.series("js-dashboard", browserSyncReload)); gulp.watch(jsDashboard, gulp.series("js-dashboard", browserSyncReload));
gulp.watch("resources/assets/sass/**/*.scss", gulp.parallel("sass-public", "sass-dashboard")); gulp.watch("resources/assets/sass/**/*.scss", gulp.parallel("sass-public", "sass-dashboard"));
}); });
@ -213,7 +198,6 @@ gulp.task("watch", () => {
gulp.task("default", gulp.parallel( gulp.task("default", gulp.parallel(
"sass-public", "sass-public",
"sass-dashboard", "sass-dashboard",
"js-public-vue",
"js-public", "js-public",
"js-public-libs", "js-public-libs",
"js-dashboard", "js-dashboard",

View file

@ -1,128 +0,0 @@
// Determine whether to use vue.js in debug or production mode
const Vue = env.debug ? require("vue/dist/vue.js") : require("vue/dist/vue.min.js");
// Import plugins
import VueRouter from "vue-router";
import VueResource from "vue-resource";
import Vuex from "vuex";
import { sync } from "vuex-router-sync";
// Load plugins
Vue.use(VueRouter);
Vue.use(VueResource);
Vue.use(Vuex);
// CSRF prevention header
Vue.http.headers.common["X-CSRF-TOKEN"] = env.csrfToken;
// Import page components
import HomePage from "pages/home.vue";
import ContactPage from "pages/contact.vue";
import Error404Page from "pages/error404.vue";
// Import section components
import NavSection from "sections/nav.vue";
import FooterSection from "sections/footer.vue";
// Name the nav and footer components so they can be used globally
Vue.component("nav-component", NavSection);
Vue.component("footer-component", FooterSection);
// Create a router instance
const router = new VueRouter({
mode: "history",
linkActiveClass: "active",
root: "/",
routes: [
{ path: "/", component: HomePage },
{ path: "/contact", component: ContactPage },
{ path: "/*", component: Error404Page }
],
scrollBehavior(to, from, savedPosition) {
if (to.hash) {
return {
selector: `[id='${to.hash.slice(1)}']`
};
} else {
return { x: 0, y: 0 };
}
}
});
// Create a vuex store instance
const store = new Vuex.Store({
state: {
appName: env.appName,
firstLoad: true,
lastPath: ""
},
getters: {
getAppName: state => {
return state.appName;
},
getFirstLoad: state => {
return state.firstLoad;
},
getLastPath: state => {
return state.lastPath;
}
},
mutations: {
setFirstLoad(state, value) {
state.firstLoad = value;
},
setLastPath(state, value) {
state.lastPath = value;
}
},
actions: {
}
});
// Sync vue-router-sync with vuex store
sync(store, router);
// Functionality to run before page load and change
router.beforeEach((to, from, next) => {
if (to.path !== store.getters.getLastPath) {
if (store.getters.getFirstLoad) {
next();
} else {
// Fade the page out and scroll when moving from one page to another
TweenMax.to("#router-view", 0.25, {
opacity: 0,
onComplete: next
});
}
}
});
// Functionality to run on page load and change
router.afterEach((to, from) => {
if (to.path !== store.getters.getLastPath) {
store.commit("setLastPath", to.path);
if (store.getters.getFirstLoad) {
// Set Page.firstLoad to false so we know the initial load has completed
store.commit("setFirstLoad", false);
} else {
Vue.nextTick(() => {
TweenMax.to("#router-view", 0.25, { opacity: 1 });
});
}
}
});
const App = new Vue({
router,
store
}).$mount("#page-content");

View file

@ -1,13 +1,128 @@
// run once the document is ready // Determine whether to use vue.js in debug or production mode
$(document).ready(function() { const Vue = env.debug ? require("vue/dist/vue.js") : require("vue/dist/vue.min.js");
navInit();
switch (SiteVars.page) { // Import plugins
case "": import VueRouter from "vue-router";
subscriptionFormInit(); import VueResource from "vue-resource";
break; import Vuex from "vuex";
case "contact": import { sync } from "vuex-router-sync";
contactFormInit();
break; // Load plugins
Vue.use(VueRouter);
Vue.use(VueResource);
Vue.use(Vuex);
// CSRF prevention header
Vue.http.headers.common["X-CSRF-TOKEN"] = env.csrfToken;
// Import page components
import HomePage from "pages/home.vue";
import ContactPage from "pages/contact.vue";
import Error404Page from "pages/error404.vue";
// Import section components
import NavSection from "sections/nav.vue";
import FooterSection from "sections/footer.vue";
// Name the nav and footer components so they can be used globally
Vue.component("nav-component", NavSection);
Vue.component("footer-component", FooterSection);
// Create a router instance
const router = new VueRouter({
mode: "history",
linkActiveClass: "active",
root: "/",
routes: [
{ path: "/", component: HomePage },
{ path: "/contact", component: ContactPage },
{ path: "/*", component: Error404Page }
],
scrollBehavior(to, from, savedPosition) {
if (to.hash) {
return {
selector: `[id='${to.hash.slice(1)}']`
};
} else {
return { x: 0, y: 0 };
}
} }
}); });
// Create a vuex store instance
const store = new Vuex.Store({
state: {
appName: env.appName,
firstLoad: true,
lastPath: ""
},
getters: {
getAppName: state => {
return state.appName;
},
getFirstLoad: state => {
return state.firstLoad;
},
getLastPath: state => {
return state.lastPath;
}
},
mutations: {
setFirstLoad(state, value) {
state.firstLoad = value;
},
setLastPath(state, value) {
state.lastPath = value;
}
},
actions: {
}
});
// Sync vue-router-sync with vuex store
sync(store, router);
// Functionality to run before page load and change
router.beforeEach((to, from, next) => {
if (to.path !== store.getters.getLastPath) {
if (store.getters.getFirstLoad) {
next();
} else {
// Fade the page out and scroll when moving from one page to another
TweenMax.to("#router-view", 0.25, {
opacity: 0,
onComplete: next
});
}
}
});
// Functionality to run on page load and change
router.afterEach((to, from) => {
if (to.path !== store.getters.getLastPath) {
store.commit("setLastPath", to.path);
if (store.getters.getFirstLoad) {
// Set Page.firstLoad to false so we know the initial load has completed
store.commit("setFirstLoad", false);
} else {
Vue.nextTick(() => {
TweenMax.to("#router-view", 0.25, { opacity: 1 });
});
}
}
});
const App = new Vue({
router,
store
}).$mount("#page-content");

View file

@ -2,20 +2,24 @@
@section('page-includes') @section('page-includes')
<script src="/js/lib.js?version={{ env('CACHE_BUST') }}"></script> <script src="/js/lib.js?version={{ env('CACHE_BUST') }}"></script>
<script src="/js/app.js?version={{ env('CACHE_BUST') }}"></script>
<link rel="stylesheet" href="/css/app.css?version={{ env('CACHE_BUST') }}" /> <link rel="stylesheet" href="/css/app.css?version={{ env('CACHE_BUST') }}" />
@include('elements.variables')
@endsection @endsection
@section('page-content') @section('page-content')
@include('sections.nav') <nav-component></nav-component>
<div class="flex-wrapper"> <div class="flex-wrapper">
<div class="page-container"> <div class="page-container">
<div class="main-content"> <div id="router-view" class="main-content">
@yield('content') <router-view></router-view>
</div> </div>
@include('sections.footer') <footer-component></footer-component>
</div> </div>
</div> </div>
@endsection @endsection
@section('page-bottom')
<script src="/js/app.js?version={{ env('CACHE_BUST') }}"></script>
@endsection

View file

@ -53,14 +53,6 @@ Route::get('/language/{lang}', function($lang) {
return redirect()->back(); return redirect()->back();
}); });
// Route::get('/', function() {
// return view('pages.index');
// });
//
// Route::get('/contact', function() {
// return view('pages.contact');
// });
Route::get('/{vue?}', function() { Route::get('/{vue?}', function() {
return view('templates.public-vue'); return view('templates.public');
})->where('vue', '[\/\w\.-]*'); })->where('vue', '[\/\w\.-]*');

186
traditional-bootstrap/gulpfile.js vendored Normal file
View file

@ -0,0 +1,186 @@
// Core packages
const gulp = require("gulp"),
minimist = require("minimist"),
log = require("fancy-log"),
plumber = require("gulp-plumber"),
concat = require("gulp-concat");
// Sass packages
const sass = require("gulp-sass"),
sassGlob = require("gulp-sass-glob"),
postCSS = require("gulp-postcss"),
autoprefixer = require("autoprefixer");
// Javascript packages
const babel = require("gulp-babel"),
stripDebug = require("gulp-strip-debug"),
uglify = require("gulp-uglify");
// Determine if gulp has been run with --production
const isProduction = minimist(process.argv.slice(2)).production !== undefined;
// Include browsersync when gulp has not been run with --production
let browserSync = undefined;
if (!isProduction) {
browserSync = require("browser-sync").create();
}
// Declare plugin settings
const sassOutputStyle = isProduction ? "compressed" : "nested",
sassPaths = [ "bower_components", "node_modules" ],
autoprefixerSettings = { remove: false, cascade: false, browsers: [ "last 6 versions" ] };
// Javascript files for the public site
const jsPublic = [
"resources/assets/js/site-vars.js",
"resources/assets/js/nav.js",
"resources/assets/js/contact.js",
"resources/assets/js/subscription.js",
"resources/assets/js/app.js"
];
// Javascript libraries for the public site
const jsPublicLibs = [
"node_modules/jquery/dist/jquery.js",
"node_modules/popper.js/dist/umd/popper.js",
"node_modules/bootstrap/dist/js/bootstrap.js",
"node_modules/gsap/src/uncompressed/TweenMax.js",
"node_modules/what-input/dist/what-input.js"
];
// Javascript files for the dashboard
const jsDashboard = [
"resources/assets/js/dashboard.js"
];
// Javascript libraries for the dashboard
const jsDashboardLibs = [
"bower_components/jquery/dist/jquery.js",
"bower_components/bootstrap-sass/assets/javascripts/bootstrap.js",
"bower_components/Sortable/Sortable.js",
"bower_components/pickadate/lib/picker.js",
"bower_components/pickadate/lib/picker.date.js",
"bower_components/list.js/dist/list.js",
"bower_components/simplemde/dist/simplemde.min.js"
];
// Paths to folders containing fonts that should be copied to public/fonts/
const fontPaths = [
"resources/assets/fonts/**"
];
// Handle errors
function handleError(err) {
log.error(err);
this.emit("end");
}
// Process sass
function processSass(filename) {
const css = gulp.src("resources/assets/sass/" + filename + ".scss")
.pipe(plumber(handleError))
.pipe(sassGlob())
.pipe(sass({ outputStyle: sassOutputStyle, includePaths: sassPaths }))
.pipe(postCSS([ autoprefixer(autoprefixerSettings) ]))
.pipe(concat(filename + ".css"))
.pipe(gulp.dest("public/css/"));
if (!isProduction) {
css.pipe(browserSync.stream({ match: "**/" + filename + ".css" }));
}
return css;
}
// Process javascript
function processJavaScript(ouputFilename, inputFiles, es6) {
const javascript = gulp.src(inputFiles)
.pipe(plumber(handleError))
.pipe(concat(ouputFilename + ".js"));
if (es6) {
javascript.pipe(babel());
}
if (isProduction) {
javascript.pipe(stripDebug()).pipe(uglify());
}
return javascript.pipe(gulp.dest("public/js/"));
}
// Task for public styles
gulp.task("sass-public", () => {
return processSass("app");
});
// Task for dashboard styles
gulp.task("sass-dashboard", () => {
return processSass("dashboard");
});
// Task for public javascript
gulp.task("js-public", () => {
return processJavaScript("app", jsPublic, true);
});
// Task for public javascript libraries
gulp.task("js-public-libs", () => {
return processJavaScript("lib", jsPublicLibs, false);
});
// Task for dashboard javascript
gulp.task("js-dashboard", () => {
return processJavaScript("dashboard", jsDashboard, true);
});
// Task for dashboard javascript libraries
gulp.task("js-dashboard-libs", () => {
return processJavaScript("lib-dashboard", jsDashboardLibs, false);
});
// Task to copy fonts
gulp.task("fonts", (done) => {
gulp.src(fontPaths)
.pipe(plumber(handleError))
.pipe(gulp.dest("public/fonts/"));
done();
});
// Task to watch files and run respective tasks when changes occur
gulp.task("watch", () => {
const browserSyncReload = (done) => {
browserSync.reload();
done();
};
browserSync.init({
logLevel: "silent",
baseDir: "./public",
notify: false,
ghostMode: {
clicks: true,
forms: true,
scroll: false
}
});
gulp.watch([ "app/**/*.php", "routes/**/*.php", "resources/views/**/*.blade.php" ], gulp.series(browserSyncReload));
gulp.watch(jsPublic, gulp.series("js-public", browserSyncReload));
gulp.watch(jsDashboard, gulp.series("js-dashboard", browserSyncReload));
gulp.watch("resources/assets/sass/**/*.scss", gulp.parallel("sass-public", "sass-dashboard"));
});
// Task to run non-development tasks
gulp.task("default", gulp.parallel(
"sass-public",
"sass-dashboard",
"js-public",
"js-public-libs",
"js-dashboard",
"js-dashboard-libs",
"fonts"
));

View file

@ -0,0 +1,34 @@
{
"private": true,
"scripts": {
"prod": "gulp --production",
"dev": "gulp default watch"
},
"devDependencies": {
"browser-sync": "^2.23.6"
},
"dependencies": {
"autoprefixer": "^8.2.0",
"babel-core": "^6.26.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.6.1",
"babelify": "^8.0.0",
"bootstrap": "^4.0.0",
"es6-promise": "^4.2.4",
"fancy-log": "^1.3.2",
"gsap": "^1.20.4",
"gulp": "^4.0.0",
"gulp-babel": "^7.0.1",
"gulp-concat": "^2.6.1",
"gulp-plumber": "^1.2.0",
"gulp-postcss": "^7.0.1",
"gulp-sass": "^4.0.1",
"gulp-sass-glob": "^1.0.9",
"gulp-strip-debug": "^3.0.0",
"gulp-uglify": "^3.0.0",
"jquery": "^3.3.1",
"minimist": "^1.2.0",
"popper.js": "^1.14.3",
"what-input": "^5.0.5"
}
}

View file

@ -0,0 +1,13 @@
// run once the document is ready
$(document).ready(function() {
navInit();
switch (SiteVars.page) {
case "":
subscriptionFormInit();
break;
case "contact":
contactFormInit();
break;
}
});

View file

@ -2,24 +2,20 @@
@section('page-includes') @section('page-includes')
<script src="/js/lib.js?version={{ env('CACHE_BUST') }}"></script> <script src="/js/lib.js?version={{ env('CACHE_BUST') }}"></script>
<script src="/js/app.js?version={{ env('CACHE_BUST') }}"></script>
<link rel="stylesheet" href="/css/app.css?version={{ env('CACHE_BUST') }}" /> <link rel="stylesheet" href="/css/app.css?version={{ env('CACHE_BUST') }}" />
@include('elements.variables')
@endsection @endsection
@section('page-content') @section('page-content')
<nav-component></nav-component> @include('sections.nav')
<div class="flex-wrapper"> <div class="flex-wrapper">
<div class="page-container"> <div class="page-container">
<div id="router-view" class="main-content"> <div class="main-content">
<router-view></router-view> @yield('content')
</div> </div>
<footer-component></footer-component> @include('sections.footer')
</div> </div>
</div> </div>
@endsection @endsection
@section('page-bottom')
<script src="/js/app-vue.js?version={{ env('CACHE_BUST') }}"></script>
@endsection

View file

@ -0,0 +1,62 @@
<?php
use App\Utilities\Language;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
/*
|--------------------------------------------------------------------------
| Authentication Routes
|--------------------------------------------------------------------------
*/
Route::auth();
Route::get('/logout', 'Auth\LoginController@logout');
/*
|--------------------------------------------------------------------------
| Dashboard Routes
|--------------------------------------------------------------------------
*/
Route::group([ 'prefix' => 'dashboard' ], function() {
Route::get('/', 'DashboardController@index');
Route::get('/contact', 'DashboardController@getContact');
Route::get('/subscriptions', 'DashboardController@getSubscriptions');
Route::get('/export/{model}', 'DashboardController@getExport');
Route::post('/image-upload', 'DashboardController@postImageUpload');
Route::post('/file-upload', 'DashboardController@postFileUpload');
Route::post('/edit', 'DashboardController@postEdit');
Route::post('/reorder', 'DashboardController@postReorder');
Route::delete('/delete', 'DashboardController@deleteDelete');
Route::delete('/image-delete', 'DashboardController@deleteImageDelete');
Route::delete('/file-delete', 'DashboardController@deleteFileDelete');
});
/*
|--------------------------------------------------------------------------
| Public Routes
|--------------------------------------------------------------------------
*/
Route::get('/language/{lang}', function($lang) {
Language::setSessionLanguage($lang);
return redirect()->back();
});
Route::get('/', function() {
return view('pages.index');
});
Route::get('/contact', function() {
return view('pages.contact');
});