diff --git a/gulpfile.js b/gulpfile.js index c12c6aa..14d35df 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -38,17 +38,8 @@ const sassOutputStyle = isProduction ? "compressed" : "nested", autoprefixerSettings = { remove: false, cascade: false, browsers: [ "last 6 versions" ] }, 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 -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" -]; +const jsPublic = [ "resources/assets/js/app.js" ]; // Javascript libraries for the public site const jsPublicLibs = [ @@ -149,14 +140,9 @@ gulp.task("sass-dashboard", () => { return processSass("dashboard"); }); -// Task for public vue -gulp.task("js-public-vue", () => { - return processVue("app-vue", vuePublic); -}); - // Task for public javascript gulp.task("js-public", () => { - return processJavaScript("app", jsPublic, true); + return processVue("app", jsPublic); }); // 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([ vuePublic, "resources/assets/js/mixins/**/*.js", "resources/components/**/*.vue" ], gulp.series("js-public-vue", browserSyncReload)); - gulp.watch(jsPublic, gulp.series("js-public", browserSyncReload)); + gulp.watch([ jsPublic, "resources/assets/js/mixins/**/*.js", "resources/components/**/*.vue" ], 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")); }); @@ -213,7 +198,6 @@ gulp.task("watch", () => { gulp.task("default", gulp.parallel( "sass-public", "sass-dashboard", - "js-public-vue", "js-public", "js-public-libs", "js-dashboard", diff --git a/resources/assets/js/app-vue.js b/resources/assets/js/app-vue.js deleted file mode 100644 index fe80ab7..0000000 --- a/resources/assets/js/app-vue.js +++ /dev/null @@ -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"); diff --git a/resources/assets/js/app.js b/resources/assets/js/app.js index 1ab70a2..fe80ab7 100644 --- a/resources/assets/js/app.js +++ b/resources/assets/js/app.js @@ -1,13 +1,128 @@ -// run once the document is ready -$(document).ready(function() { - navInit(); +// 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"); - switch (SiteVars.page) { - case "": - subscriptionFormInit(); - break; - case "contact": - contactFormInit(); - break; +// 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"); diff --git a/resources/views/templates/public.blade.php b/resources/views/templates/public.blade.php index bd7f2be..30b0318 100644 --- a/resources/views/templates/public.blade.php +++ b/resources/views/templates/public.blade.php @@ -2,20 +2,24 @@ @section('page-includes') - + @include('elements.variables') @endsection @section('page-content') - @include('sections.nav') +
-
- @yield('content') +
+
- @include('sections.footer') +
@endsection + +@section('page-bottom') + +@endsection diff --git a/routes/web.php b/routes/web.php index 3c77bd9..bf36a86 100644 --- a/routes/web.php +++ b/routes/web.php @@ -53,14 +53,6 @@ Route::get('/language/{lang}', function($lang) { return redirect()->back(); }); -// Route::get('/', function() { -// return view('pages.index'); -// }); -// -// Route::get('/contact', function() { -// return view('pages.contact'); -// }); - Route::get('/{vue?}', function() { - return view('templates.public-vue'); + return view('templates.public'); })->where('vue', '[\/\w\.-]*'); diff --git a/traditional-bootstrap/gulpfile.js b/traditional-bootstrap/gulpfile.js new file mode 100644 index 0000000..31c653c --- /dev/null +++ b/traditional-bootstrap/gulpfile.js @@ -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" +)); diff --git a/traditional-bootstrap/package.json b/traditional-bootstrap/package.json new file mode 100644 index 0000000..2703e54 --- /dev/null +++ b/traditional-bootstrap/package.json @@ -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" + } +} diff --git a/traditional-bootstrap/resources/assets/js/app.js b/traditional-bootstrap/resources/assets/js/app.js new file mode 100644 index 0000000..1ab70a2 --- /dev/null +++ b/traditional-bootstrap/resources/assets/js/app.js @@ -0,0 +1,13 @@ +// run once the document is ready +$(document).ready(function() { + navInit(); + + switch (SiteVars.page) { + case "": + subscriptionFormInit(); + break; + case "contact": + contactFormInit(); + break; + } +}); diff --git a/resources/assets/js/contact.js b/traditional-bootstrap/resources/assets/js/contact.js similarity index 100% rename from resources/assets/js/contact.js rename to traditional-bootstrap/resources/assets/js/contact.js diff --git a/resources/assets/js/nav.js b/traditional-bootstrap/resources/assets/js/nav.js similarity index 100% rename from resources/assets/js/nav.js rename to traditional-bootstrap/resources/assets/js/nav.js diff --git a/resources/assets/js/site-vars.js b/traditional-bootstrap/resources/assets/js/site-vars.js similarity index 100% rename from resources/assets/js/site-vars.js rename to traditional-bootstrap/resources/assets/js/site-vars.js diff --git a/resources/assets/js/subscription.js b/traditional-bootstrap/resources/assets/js/subscription.js similarity index 100% rename from resources/assets/js/subscription.js rename to traditional-bootstrap/resources/assets/js/subscription.js diff --git a/resources/views/pages/contact.blade.php b/traditional-bootstrap/resources/views/pages/contact.blade.php similarity index 100% rename from resources/views/pages/contact.blade.php rename to traditional-bootstrap/resources/views/pages/contact.blade.php diff --git a/resources/views/pages/index.blade.php b/traditional-bootstrap/resources/views/pages/index.blade.php similarity index 100% rename from resources/views/pages/index.blade.php rename to traditional-bootstrap/resources/views/pages/index.blade.php diff --git a/resources/views/sections/footer.blade.php b/traditional-bootstrap/resources/views/sections/footer.blade.php similarity index 100% rename from resources/views/sections/footer.blade.php rename to traditional-bootstrap/resources/views/sections/footer.blade.php diff --git a/resources/views/sections/nav.blade.php b/traditional-bootstrap/resources/views/sections/nav.blade.php similarity index 100% rename from resources/views/sections/nav.blade.php rename to traditional-bootstrap/resources/views/sections/nav.blade.php diff --git a/resources/views/sections/subscription-form.blade.php b/traditional-bootstrap/resources/views/sections/subscription-form.blade.php similarity index 100% rename from resources/views/sections/subscription-form.blade.php rename to traditional-bootstrap/resources/views/sections/subscription-form.blade.php diff --git a/resources/views/templates/public-vue.blade.php b/traditional-bootstrap/resources/views/templates/public.blade.php similarity index 52% rename from resources/views/templates/public-vue.blade.php rename to traditional-bootstrap/resources/views/templates/public.blade.php index 3ce88b9..bd7f2be 100644 --- a/resources/views/templates/public-vue.blade.php +++ b/traditional-bootstrap/resources/views/templates/public.blade.php @@ -2,24 +2,20 @@ @section('page-includes') + - @include('elements.variables') @endsection @section('page-content') - + @include('sections.nav')
-
- +
+ @yield('content')
- + @include('sections.footer')
@endsection - -@section('page-bottom') - -@endsection diff --git a/traditional-bootstrap/routes/web.php b/traditional-bootstrap/routes/web.php new file mode 100644 index 0000000..8884a42 --- /dev/null +++ b/traditional-bootstrap/routes/web.php @@ -0,0 +1,62 @@ + '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'); +});