garethdaine

garethdaine

Member Since 5 Years Ago

Aughton

Founder at Daine Media Limited

Experience Points 5,815
Experience Level 2

4,185 experience to go until the next level!

In case you were wondering, you earn Laracasts experience when you:

  • Complete a lesson — 100pts
  • Create a forum thread — 50pts
  • Reply to a thread — 10pts
  • Leave a reply that is liked — 50pts
  • Receive a "Best Reply" award — 500pts
Lessons Completed 62
Lessons
Completed
Best Reply Awards 0
Best Reply
Awards
  • start-engines Created with Sketch.

    Start Your Engines

    Earned once you have completed your first Laracasts lesson.

  • first-thousand Created with Sketch.

    First Thousand

    Earned once you have earned your first 1000 experience points.

  • 1-year Created with Sketch.

    One Year Member

    Earned when you have been with Laracasts for 1 year.

  • 2-years Created with Sketch.

    Two Year Member

    Earned when you have been with Laracasts for 2 years.

  • 3-years Created with Sketch.

    Three Year Member

    Earned when you have been with Laracasts for 3 years.

  • 4-years Created with Sketch.

    Four Year Member

    Earned when you have been with Laracasts for 4 years.

  • 5-years Created with Sketch.

    Five Year Member

    Earned when you have been with Laracasts for 5 years.

  • school-session Created with Sketch.

    School In Session

    Earned when at least one Laracasts series has been fully completed.

  • welcome-newcomer Created with Sketch.

    Welcome To The Community

    Earned after your first post on the Laracasts forum.

  • full-time-student Created with Sketch.

    Full Time Learner

    Earned once 100 Laracasts lessons have been completed.

  • pay-it-forward Created with Sketch.

    Pay It Forward

    Earned once you receive your first "Best Reply" award on the Laracasts forum.

  • subscriber-token Created with Sketch.

    Subscriber

    Earned if you are a paying Laracasts subscriber.

  • lifer-token Created with Sketch.

    Lifer

    Earned if you have a lifetime subscription to Laracasts.

  • lara-evanghelist Created with Sketch.

    Laracasts Evangelist

    Earned if you share a link to Laracasts on social media. Please email [email protected] with your username and post URL to be awarded this badge.

  • chatty-cathy Created with Sketch.

    Chatty Cathy

    Earned once you have achieved 500 forum replies.

  • lara-veteran Created with Sketch.

    Laracasts Veteran

    Earned once your experience points passes 100,000.

  • 10k-strong Created with Sketch.

    Ten Thousand Strong

    Earned once your experience points hits 10,000.

  • lara-master Created with Sketch.

    Laracasts Master

    Earned once 1000 Laracasts lessons have been completed.

  • laracasts-tutor Created with Sketch.

    Laracasts Tutor

    Earned once your "Best Reply" award count is 100 or more.

  • laracasts-sensei Created with Sketch.

    Laracasts Sensei

    Earned once your experience points passes 1 million.

  • top-50 Created with Sketch.

    Top 50

    Earned once your experience points ranks in the top 50 of all Laracasts users.

09 Jun
1 month ago

garethdaine left a reply on Deploy Base WordPress Build

@NASH - Indeed, and I’ve actually checked out the first link, but couldn’t find anything relevant at first glance.

I’ll dig deeper and see what I can do. The API route might be the best option.

garethdaine started a new conversation Deploy Base WordPress Build

Hey Gang,

So, I have a base WordPress install I use for clients and internal affiliate sites that includes all the premium plugins we use, all the Elementor templates, custom fields, and custom post types.

What I’d like to do, is rather than have to set up the Forge server, install WordPress, then upload the base build, instead have a deploy script or recipe that allows me to pull the base build from a GitHub repo or other location and set it up on the server and connect to the DB.

I’ve been doing some research online but can’t seem to find anything useful to help me get started with this.

Any advice or direction would be much appreciate. Thanks.

07 Mar
1 year ago

garethdaine left a reply on Using Dropzone With Spark API

@tptompkins This pretty much saved the day. Thank you.

18 Aug
1 year ago

garethdaine started a new conversation Coupons For Specific Plans Only

Is there a straightforward way to setup coupons or site-wide promotions to only work with specific plans?

18 Feb
2 years ago

garethdaine started a new conversation Update Spark State User...

Hi Folks,

Is there a way to update spark.state.user when working via Vue JS/AJAX?

I have an AJAX login and I can update the global user object using the global event bus and calling Bus.$emit('updateUser') which calls Spark.getUser();, but it does not update the state.

Does anyone know of a way to do this?

12 Jan
2 years ago

garethdaine started a new conversation Spark Mixins

Does anyone know how to use Spark mixins in your custom components? I particularly want to use the tabState located at spark/resources/assets/js/mixins/tab-state.js

garethdaine started a new conversation Dom Specific Manipulation With JQuery

Hi Folks,

How are people managing dom manipulation in Spark? For example, say I want to use the jQuery Match Height plugin to make certain elements the same height. How would you guys pull this in and use it with how Spark is setup for JS?

Thanks

16 Dec
2 years ago

garethdaine left a reply on Can We Track Last Login Date Of Authorised User

Well, probably use the Illuminate\Auth\Events\Logout event instead of the Login event @yansusanto and keep the rest the same. That way that field will only ever be updated when the user logs out.

garethdaine left a reply on Can We Track Last Login Date Of Authorised User

It will @yansusanto yes, but I assumed that the OP wanted to have a way to track when the users of his app had last logged in so that he could see it.

If he wants a way to track last logged in and current (so the currently logged in user can see their last logged in time), then he'd probably have to have two extra fields last_logged_in_at and current_login_time, then as a user logs in, take the old current_login_time value and update last_logged_in_at field with that time and the current_login_time with the current time. Unless there's another way to do this.

I suppose, you could create an event listener that listened for when the user logs out, Illuminate\Auth\Events\Logout and then update the last_logged_in_atfield.

garethdaine left a reply on Todd...

Yup, guessed that it was a joke @JeffreyWay, just wondered what it referenced, is all.

garethdaine started a new conversation Todd...

I've just noticed this in the footer of the site:

'© Laracasts 2016. All rights reserved. Yes, all of them. That means you, Todd.'

Hahaha! Who is Todd? And, what is this all about?

garethdaine left a reply on Vimeo For Business

Hey @MikeHopley,

Yes, completely understand I would have to write the authorisation logic and connect to the Vimeo API to retrieve the asset.

My question was more to do with how Vimeo protects those assets.

I understand it can be restricted by domain, but I'm guessing there is also some sort of tokenisation functionality available.

For example:

  1. A user purchases a course.
  2. The course contains several videos (does Vimeo allow you to categorise content via their API? Playlist, Collections, Categories?)
  3. The user clicks on a video in that course to play it.
  4. My app checks to see if the user has authorisation (based on purchase data and connected ids in the DB) to play the video.
  5. If so, the app connects to the Vimeo API to retrieve the asset but using a generated token with an expiry on it.

So, if someone wanted to get the video URL from the dev tools/inspector (even with the token), they would only have access for a specific amount of time before that token expires. When it does, the video will not play.

Seems reasonable that Vimeo would have this sort of functionality, but I'm not entirely sure.

I've also been looking at VHX (https://www.vhx.tv/) which is also a Vimeo company.

garethdaine started a new conversation Vimeo For Elearning...

Hi Folks,

I really want to get some opinions and insights on the best service to use for building an elearning platform.

I'm currently working on a project that requires a platform that will allow admins to create courses and upload video, which can then be purchased and viewed by users.

I've been looking at several options:

  1. Vimeo Business (https://vimeo.com/business)
  2. VHX (https://www.vhx.tv/)
  3. Brightcove Video Cloud (https://www.brightcove.com/en/)
  4. Building Our Own

We're going to need a way to do a couple of different things:

  1. Protect Video Content (Tokenisation?)/Authorise Playback
  2. Upload and Store Video via Our Own Admin
  3. Modify the Player Interface
  4. Have Access to an API

I'm really after some advice on what you guys feel is the best service, or if you know of any alternatives.

Also, it would be great if @JeffreyWay would be able to comment. I know you use Vimeo in some capacity. Is it Vimeo Business?

Anyway, thank and looking forward to your responses.

Cheers

Gaz

18 Nov
2 years ago

garethdaine left a reply on Spark User

Nope, not that I can tell. I can see the user being set there via the Spark global object, but where and how is the user created in the Spark global object? As this Spark.state.user doesn't really tell me anything about how the data is retrieved or how the user is created.

In terms of the created() method, the only thing related to the user is the this.loadDataForAuthenticatedUser() method, but all that does is retrieve notifications for the authenticated user.

Now, I've figured out that the global Spark object is created in the Spark layout file app.blade.php and that the method scriptVariables() pulls in the data for it via a ProvidesScriptVariables trait. The state is set there using Spark::call(InitialFrontendState::class.'@forUser', [Auth::user()]).

The class InitialFrontendState implements to a contract of the same name and the forUser() method retrieves the user data which is then set on the global Spark object via the call in the primary layout file.

17 Nov
2 years ago

garethdaine left a reply on Spark User

Yes, thanks. I am already aware of that, though. I'd really like to get some advice on where this is created and then passed to the global Spark object.

I've checked a lot of the bootstrapping and components, but can't seem to see where the user data is actually being retrieved from and how, and how it is then sent to the global object.

garethdaine started a new conversation Spark User

Guys, could one of you Spark gurus give me some pointers on what to look at to find out how Spark retrieves and exposes the currently logged in user to the frontend API, please?

I'm looking to learn how this is achieved.

10 Oct
2 years ago

garethdaine started a new conversation Spark Global Object Data

Hey Folks,

I've looked through the Spark JS but can't quite seem to see how the Spark global object retrieves its data from the Laravel backend, such as the Stripe key, for example.

Does anyone know or can anyone point me in the right direction? Cheers.

05 Oct
2 years ago

garethdaine left a reply on Vimeo For Business

@martinbean For example, this video on Laracasts is hosted on a Vimeo CDN https://fpdl.vimeocdn.com/vimeo-prod-skyfire-std-us/01/4563/6/172817621/557822165.mp4.

You can't get access to it unless a valid token is passed as a query string parameter. Surely, using thins token based authentication I'd be able to restrict access per user based on generated tokens? No?

garethdaine left a reply on Vimeo For Business

@martinbean Hmmm. Are you certain that's the case? Laracasts uses Vimeo to host its video content and that is restricted based on your subscription level. Of course, this is handled in Laracasts itself, but there must be a way to restrict/un-restrict video based on active subscriptions, as this is what this site does.

garethdaine left a reply on Vimeo For Business

Perhaps something like this would be better https://wistia.com/use-cases/training-and-education

garethdaine left a reply on Vimeo For Business

@martinbean Thanks. Would I not be able to completely restrict the video and then implement some sort of authentication within the app that then sends a request to Vimeo to 'unlock' it per session, or something similar.

So, essentially, no one has access until my app authenticates them and then the app retrieves the video for playback based on an API key or something?

garethdaine started a new conversation Vimeo For Business

Hey Folks,

I'm currently building an LMS and I'd like to get some feedback on the use of Vimeo Business to host and manage the videos, and whether it is a suitable service for our needs.

In the system, tutors, admins, and B2B customers will be able to create courses and for each section of the course, they will be able to upload video.

Does the Vimeo API handle this sort of thing and will it allow restrictions on the videos based on whether someone has purchased that specific course?

It will be similar to Laracasts in that the video is behind a subscription/payment, but all videos won't be accessible once you have an account, you'll purchase courses individually and all videos attached to that course will be available. This is probably handled in the code itself, but just wanted some opinions on whether Vimeo is a good fit.

Also, does the API allow management of videos etc like this? Would I be able to allow our software to allow users to upload video from the dashboard of our app to Vimeo?

Would appreciate your thoughts as well @JeffreyWay. Thanks.

19 Sep
2 years ago

garethdaine left a reply on Spark For A SPA? Start From Scratch Or Build On What's There?

I've gone with using default Spark functionality, specifically using the tab-state mixin and the sparkHashChanged event.

So, in my home component:

Vue.component('home', {
    props: ['user'],

    /**
     * Load mixins for the component.
     */
    mixins: [require('./../spark/mixins/tab-state')],

    ready() {
        this.usePushStateForTabs('.spark-settings-tabs');
    }
}); 

Then:

Vue.component('courses', { data() {

        return {

            test: ''

        }

    },

    ready() {
        //
    },


    events: {
        /**
         * Handle the Spark tab changed event.
         */
        sparkHashChanged(hash) {
            if (hash == 'courses') {
                this.getTest();
            }

            return true;
        }
    },

    methods: {
        getTest() {
            this.$http.get('/dashboard/test')
                .then(response => {
                    this.test = response.data;
                });
        }
    }
});

In my component, and finally setting up my primary layout and tab content as per Spark settings views.

Seems to work pretty well.

This is only basic at the moment, so I may come across issues as I build out functionality, but so far so good.

I can create individual views tied to specific Spark components, that pull through and render whatever data I want, but only load it once the hash has changed. Pretty decent stuff.

I'll probably look deeper into vue-router at a later date. Any questions, let me know.

garethdaine left a reply on Spark & Vue-Router...

So, I've dug a little deeper, and I've decided to go down a different route.

I've gone with using default Spark functionality, specifically using the tab-state mixin and the sparkHashChanged event.

So, in my home component:

Vue.component('home', {
    props: ['user'],

    /**
     * Load mixins for the component.
     */
    mixins: [require('./../spark/mixins/tab-state')],

    ready() {
        this.usePushStateForTabs('.spark-settings-tabs');
    }
});

Then:

Vue.component('courses', {
    data() {

        return {

            test: ''

        }

    },

    ready() {
        //
    },


    events: {
        /**
         * Handle the Spark tab changed event.
         */
        sparkHashChanged(hash) {
            if (hash == 'courses') {
                this.getTest();
            }

            return true;
        }
    },

    methods: {
        getTest() {
            this.$http.get('/dashboard/test')
                .then(response => {
                    this.test = response.data;
                });
        }
    }
});

In my component, and finally setting up my primary layout and tab content as per Spark settings views.

Seems to work pretty well.

This is only basic at the moment, so I may come across issues as I build out functionality, but so far so good.

I can create individual views tied to specific Spark components, that pull through and render whatever data I want, but only load it once the hash has changed. Pretty decent stuff.

I'll probably look deeper into vue-router at a later date. Any questions, let me know.

garethdaine left a reply on Can We Track Last Login Date Of Authorised User

In Laravel 5.3, you can accomplish this by creating an event/listener binding as follows.

In your EventServiceProvider service provider (app/Providers/EventServiceProvider.php) add the following to the $listen array:

 'Illuminate\Auth\Events\Login' => [
    'App\Listeners\Users\UpdateLastLoggedInAt',
],

The run php artisan event:generate. This will create your event listener located at app\Listeners\Users\UpdateLastLoggedInAt.

In the event listener, add the following to the handle() method (making sure you use Carbon\Carbon within your listener class):

public function handle(Login $event)
{
    $event->user->last_logged_in_at = Carbon::now();
    $event->user->save();
}

Note: Make sure you have a last_logged_in_at column in your users table and that you make it fillable.

garethdaine started a new conversation Spark & Vue-Router...

Hey Folks,

Has anyone had any success in setting up Spark to utilise vue-router to create a Single Page App (SPA)?

Looking for any advice anyone might have.

I did find this resource but wondered if others might be approaching it in a different way. Thanks.

Gaz

garethdaine started a new conversation Spark User

Hey Folks,

Could someone give me a pointer on how Spark sends the user information from the database to the Spark user object/prop?

I'd like to dig in a little deeper and find out how this data is passed to the component, for example home.

Cheers

30 Jun
3 years ago

garethdaine left a reply on Vue + Spark Walkthrough Screencast?

I was confused myself at first when working with Spark and Vue, and the way it had been implemented didn't seem to work the way Jeff showed in his various Vue series', especially with regard to importing other npm packages and the like. But now I am used to it and have figured out how it all works together, it really is well implemented and makes a lot of sense, particularly extending Spark Vue components, or creating your own.

I actually now really love working with it and frontend dev has become quite fun again. :-)

It would be good, though, if the documentation for Spark was a bit more comprehensive, but I understand it's early days and there's a lot of ground to cover.

I found great help in the Vue JS Gitter chat, https://gitter.im/vuejs/vue.

18 Jun
3 years ago

garethdaine started a new conversation Auth

Does Spark still use the Auth class?

garethdaine left a reply on Adding Properties To Spark Objects, Such As User

Yes, I've used the custom variables, but I was wondering if there was a way to add properties to the user object?

17 Jun
3 years ago

garethdaine left a reply on Make Use Of External Js-libs In Spark

But how are you requiring it? Can you show the code?

Also, how are you trying to access/use it in your code?

garethdaine left a reply on Spark & Homestead

Use composer outside of the VM when possible. You can even run certain artisan commands outside of your VM, as long as they don't rely on database usage.

garethdaine left a reply on Make Use Of External Js-libs In Spark

Have you installed it via NPM and how are you requiring it in your component?

garethdaine left a reply on Fire Event After Team Register

Just to add to the answer by @martinbean, go to your app\Providers\EventServiceProvider.php file and add your listener to the $listen property, specifically the Laravel\Spark\Events\Teams\Subscription\TeamSubscribed event:

'Laravel\Spark\Events\Teams\Subscription\TeamSubscribed' => [
    'Namespace\Listeners\Teams\Subscription\SendWelcomeEmail',
],

Then in your console use the php artisan event:generate command to generate your listener. It will be located at Namespace\Listeners\Teams\Subscription\SendWelcomeEmail.

Then you just need to add your mail code to the handle method of the listener. Something like this for example:

public function handle(TeamSubscribed $event)
{
    $user = $event->user;

    Mail::send('emails.team.subscription.welcome', ['user' => $user], function($message) use ($user) {
        $message->from('[email protected]', 'Company Name');
        $message->to($user->email, $user->name)->subject('Welcome '.explode(' ',trim($user->name))[0]);
    });
}

Hope this helps.

garethdaine started a new conversation Adding Properties To Spark Objects, Such As User

Hey Folks,

Could anyone give me a little direction on how they go about adding properties to the global Spark object and sub-objects, such as User?

I have a couple of methods on my User model that do things like create a secure hash from their email and convert the created_at field to a UNIX timestamp.

I'd like to be able to add this data to properties on the Spark Vue global object.

Any advice is very much appreciated. Thanks.

garethdaine left a reply on Adding A Settings Tab

Thanks, @dannydjones1994

That's great stuff. I'd pretty much figured it our before you replied, but thanks. :-)

16 Jun
3 years ago

garethdaine left a reply on Change RedirectTo After Login

Hi @BobaFett ,

I came across this issue myself. There are two options.

You can use that class in a custom LoginController and extend it, setting the redirectTo property, or you can catch the URI of the route in your routes.php file and perform a redirect.

15 Jun
3 years ago

garethdaine left a reply on Adding A Settings Tab

Anyone got any info on this?

garethdaine left a reply on Spark & Homestead

You should run the migrate command in the VM, as it needs to connect to your database.

14 Jun
3 years ago

garethdaine left a reply on Restrict Coupon To Specific Plan

OK, so now the user can only select a plan that matches the coupon code (both monthly and yearly plans):

var base = require('auth/register-stripe');

Vue.component('spark-register-stripe', {
    mixins: [base],

    methods: {
        /**
         * Select the appropriate default plan for registration.
         */
        selectAppropriateDefaultPlan() {
            if (this.monthlyPlans.length == 0 && this.yearlyPlans.length > 0) {
                this.showYearlyPlans();
            }

            if (this.query.plan) {
                this.selectPlanByName(this.query.plan);
            } else if (this.query.invitation) {
                this.selectFreePlan();
            } else if (this.paidPlansForActiveInterval.length > 0) {
                if (typeof this.query.coupon !== 'undefined') {
                    this.selectPlanByName(this.toTitleCase(this.query.coupon));
                } else {
                    this.selectPlan(this.paidPlansForActiveInterval[0]);
                }
            } else {
                this.selectFreePlan();
            }
        },


        /**
         * Select the given plan.
         */
        selectPlan(plan) {
            var planId = plan.id;

            if (typeof this.query.coupon !== 'undefined') {
                if (planId.indexOf(this.query.coupon) > -1) {
                    var allowedPlan = _.find(this.plans, plan => plan.id === planId);
                    
                    this.selectedPlan = allowedPlan;
                    this.registerForm.plan = allowedPlan.id;
                } else if (planId !== this.query.coupon) {
                    var allowedPlan = _.find(this.plans, plan => plan.id === this.query.coupon);

                    this.selectedPlan = allowedPlan;
                    this.registerForm.plan = allowedPlan.id;
                }
            } else {
                this.selectedPlan = plan;
                this.registerForm.plan = plan.id;
            }
        },

        toTitleCase(str) {
            return str.replace(/\b\w+/g, function(s) {
                return s.charAt(0).toUpperCase() + s.substr(1).toLowerCase();
            });
        }
    }
});

So, now just for the validation server side.

garethdaine left a reply on Restrict Coupon To Specific Plan

OK, I have the frontend working by extending the resources/assets/js/spark-components/auth/register-stripe.js components selectAppropriateDefaultPlan() method.

var base = require('auth/register-stripe');

Vue.component('spark-register-stripe', {
    mixins: [base],

    methods: {
        selectAppropriateDefaultPlan() {
            if (this.monthlyPlans.length == 0 && this.yearlyPlans.length > 0) {
                this.showYearlyPlans();
            }
            
            var coupon = this.query.coupon;

            if (this.query.plan) {
                this.selectPlanByName(this.query.plan);
            } else if (this.query.invitation) {
                this.selectFreePlan();
            } else if (this.paidPlansForActiveInterval.length > 0) {
                if (typeof coupon !== 'undefined') {
                    this.selectPlanByName(this.toTitleCase(coupon));
                } else {
                    this.selectPlan(this.paidPlansForActiveInterval[0]);
                }
            } else {
                this.selectFreePlan();
            }
        },

        toTitleCase(str) {
            return str.replace(/\b\w+/g, function(s) {
                return s.charAt(0).toUpperCase() + s.substr(1).toLowerCase();
            });
        }
    }
});

Now I just need to perform the validation server side.

garethdaine started a new conversation Restrict Coupon To Specific Plan

Hi Folks,

I need to restrict coupon usage during registration both on the frontend and on the server based on the selected plan.

So when a user visits the following URL:

https://example.com/register?coupon=agency

I want to be able to not allow the user to select the other plans if that coupon is being used.

So, I have three plans:

  1. Individual - 40% Coupon
  2. Business - 50% Coupon
  3. Agency - 55% Coupon

As above, depending on the URL the customer goes to it will restrict plan selection based on the matching coupon code.

Additionally, I would like it that based on the coupon passed, the appropriate plan would be selected.

There would also need to be some validation on the server side to check whether the coupon passed matches the plan selected.

Any advice would be most appreciated.

Thanks

garethdaine left a reply on Spark & Homestead

Hey,

Install everything locally on your machine, not in Homestead. This includes the Laravel installer.

garethdaine started a new conversation Spark Views

Folks,

Does anyone know what the difference (uses) is between:

resources/views/vendor/spark/layouts/blade/app.blade.php

and

resources/views/vendor/spark/layouts/app.blade.php

Cheers

garethdaine started a new conversation Restricting Coupon Codes To Specific Plans

Hey Folks,

How easy would it be to restrict promotion codes per plan when registering?

Cheers

garethdaine left a reply on Redirect After Registration/Subscription

Hey @EventFellows ,

So I did it using an event listener:

<?php

namespace ContentSleuth\Listeners\Subscription;

use Laravel\Spark\Events\Subscription\UserSubscribed;
use Auth;

class LoginAndRedirect
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     *
     * @param  UserSubscribed  $event
     * @return void
     */
    public function handle(UserSubscribed $event)
    {
        Auth::login($event->user);

        return redirect()->route('dashboard');
    }
}

garethdaine left a reply on Debugging Spark Registration

Sorted it. You can just generate a token via CURL https://stripe.com/docs/api#create_card_token and add that to Postman.

garethdaine left a reply on Looks Like The Forum Here Is Going To Need Some Spam Control

Hey, everyone -

Sorry, the spam had gotten really bad the last few days. I got a little too aggressive with the spam detection. But, man, this dang Korean Casino spammer...

I fixed the regex today, so all should be fine now. Sorry about that. :)

garethdaine started a new conversation Adding A Settings Tab

How do you guys handle adding another tab to the Spark settings page? Would be interested in hearing approaches.