Giter VIP home page Giter VIP logo

spa-starter-kit's Introduction

Codecast's Single Page Application Starter Kit

Build Status

Cover

A highly opinionated Single Page Application starter kit built on top of Vue.js and Laravel.

This package contains two separate projects to act as a starting point for a Single Page Application: a Vue.js project (created with vue-cli + webpack template) and a Laravel 5.3 project.

They're not just freshly created projects but a fully working application that can be modified and expanded to become your own application.

Demo

The live demo can be found in https://spa.codecasts.rocks/.

Features

  1. Client side
    • Vue.js 2.0 project create with vue-cli + webpack template
    • Centralized state management with Vuex
    • Route management with Vue-router
    • Authentication with JWT
    • Keep user signed in using local stored info
    • HTTP requests with Axios
    • ESLint with AirBNB preset
    • Pagination integrated with Laravel's LengthAwarePaginator
    • Alerts and Confirmation Alerts provided by SweetAlert
  2. Server side

Prerequisites

Make sure you have installed Node and Yarn (latest versions) as well as PHP 7 and MySQL.

Installation

Cloning

These commands will download the repository and prepare it for you.

git clone --depth 1 -b master [email protected]:codecasts/spa-starter-kit.git
cd spa-starter-kit
rm -rf ./.git/
git init
git add --all
git commit -m "init"

Setup

  1. Client side - this is a Vue.js project created with vue-cli
    • With Terminal cd client && yarn && yarn run dev.
  2. Server side - this is a Laravel 5.3 project
    • With Terminal:
      • Navigate to webservice folder and then:
      • composer install to install Laravel and third party packages
      • touch database/database.sqlite to create an empty database file
      • cp .env.example .env to configure installation
      • php artisan key:generate to generate unique key for the project
      • php artisan jwt:secret to generate unique key for the project
      • php artisan migrate to create all the tables
      • php artisan db:seed to fill the tables with fake data
      • php artisan serve to serve application on localhost:8000

Usage

  1. Client side
  2. Server side
    • API endpoint is http://localhost:8000/api

Testing

Navigate to webservice folder and run the composer test script

$ composer test

Things worth mentioning

  1. Error handling is done globally by making use of Axios' interceptors. But you can still .catch() errors within components to perform actions related to that scope. See /client/src/plugins/http.js;

  2. The same way error messages lives in one single component (/client/src/modules/general/alerts.vue) and their visibility is controlled by a Vuex property. So to show/hide messages it is just a matter of dispaching a Vuex action from within any component;

  3. The spinner displayed during server requests (see top right close to user indentification) is also controlled by a Vuex property. The procedure to show/hide it is the same as outlined in the item 2 above;

  4. routes and Vuex modules live close to the modules they work for. Always look for routes.js and store.js inside a module directory. See /client/src/modules/categories;

  5. Important: Laravel project found in the directory webservice was modified beyond adding routes and controllers. For instance: the webservice/app/Exceptions/Handler.php was modified from its original version to return all exceptions to the client, not only HttpExceptions. Other changes are also in place. So our recommendation is to always use this project to build your own, instead of copying controllers and routes to a new project.

Contributing

  1. Fork it!
  2. Create your feature branch from develop: git checkout -b feature/my-new-feature
  3. Write your code. Comment your code.
  4. Commit your changes: git commit -am 'Add some feature'
  5. Push to the branch: git push origin feature/my-new-feature
  6. Submit a pull request to develop branch :D

Credits

Fábio Vedovelli and dedicated contributors.

License

Licensed under the MIT license.

spa-starter-kit's People

Contributors

angelorubin avatar cristiano-pacheco avatar emtudo avatar flyingluscas avatar jaonoctus avatar lednhatkhanh avatar namdau avatar skoop avatar vedovelli avatar vinicius73 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spa-starter-kit's Issues

clicking on <button @click=""></button> dumps me to git repo url

Can't seem to determine how/why clicking on a button in a new component redirects to git repo url rather than running the passed function.

I can't get it to run a native function like <button @click="alert('hello')"></button> OR a component method.

I am encountering this while trying to add a map component.

Any thoughts?

Thank You

No categories in demo

When adding a new product, no categories are being pulled into the add product form.

Token Signature could not be verified.

I created in a postgres db, after logging in and trying to access the modules (categories, products) the system closes with the following api message

BadRequestHttpException in BaseMiddleware.php line 51:
Token not provided

in BaseMiddleware.php line 51
at BaseMiddleware->checkForToken(object(Request)) in BaseMiddleware.php line 66
at BaseMiddleware->authenticate(object(Request)) in Authenticate.php line 30
at Authenticate->handle(object(Request), object(Closure)) in Pipeline.php line 137
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in Pipeline.php line 33
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in HandleCors.php line 34
at HandleCors->handle(object(Request), object(Closure)) in Pipeline.php line 137
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in Pipeline.php line 33
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in SubstituteBindings.php line 41
at SubstituteBindings->handle(object(Request), object(Closure)) in Pipeline.php line 137
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in Pipeline.php line 33
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in ThrottleRequests.php line 49
at ThrottleRequests->handle(object(Request), object(Closure), '60', '1') in Pipeline.php line 137
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in Pipeline.php line 33
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in Pipeline.php line 104
at Pipeline->then(object(Closure)) in Router.php line 655
at Router->runRouteWithinStack(object(Route), object(Request)) in Router.php line 629
at Router->dispatchToRoute(object(Request)) in Router.php line 607
at Router->dispatch(object(Request)) in Kernel.php line 268
at Kernel->Illuminate\Foundation\Http\{closure}(object(Request)) in Pipeline.php line 53
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in HandleCors.php line 34
at HandleCors->handle(object(Request), object(Closure)) in Pipeline.php line 137
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in Pipeline.php line 33
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in CheckForMaintenanceMode.php line 46
at CheckForMaintenanceMode->handle(object(Request), object(Closure)) in Pipeline.php line 137
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in Pipeline.php line 33
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in Pipeline.php line 104
at Pipeline->then(object(Closure)) in Kernel.php line 150
at Kernel->sendRequestThroughRouter(object(Request)) in Kernel.php line 117
at Kernel->handle(object(Request)) in index.php line 53
at require_once('/home/prodap/Workspace/tmp/spa-starter-kit/webservice/public/index.php') in server.php line 21

Import store in eager components causes a circular dependency

The problems only happens on eager components.

For example:

If you import and log the store on app/auth/components/main.vue, the output is the store object. But, if you make this component eager and run de test again, the output will be undefined.

I belive that the problem is caused by an circular dependency:

store/index -> store/modules -> app/index -> app/routes -> app/auth/index -> app/auth/routes -> app/auth/components/main -> src/store

In my specific case, a need to use the store inside de vue-router beforeRouteEnter guard to access some info in the store. Inside this guard, this.$route will not be available, because the component instance has no created yet.

Implement the refresh token feature on the client.

When api returns a response with status 401 and with data.reason = 'token_expired'

1- Try to update the user's token, sending a request to /auth/refresh

  • If successful:
    Update the user's token (Local Storer, Vuex, Header) and resend the previous request.

  • If you do not succeed:
    Delete the token and user data in Vuex and Local Storage and redirect to the login page.

.gitignore, .gitattributes, and app.scss

Great project!

Would you consider adding .idea to the root .gitignore file?

Also I believe it's good practice to protect Web fonts from text encoding, by including the following in a .gitattributes file (so that fonts in /client/src/assets/fonts are treated as binary files).

*.ttf   binary
*.otf   binary
*.eot   binary
*.woff  binary
*.woff2 binary

Also I believe that /client/src/assets/sass/app.scss can be updated as below, with correct paths to node_modules for imports. I've tested this in dev and build environments and it compiles fine. I'd be happy to submit a pull request for both if you think this is okay.

// Fonts
@import url(https://fonts.googleapis.com/css?family=Raleway:300,400,600);

// Variables
@import "variables";

// Bootstrap
@import "../../../node_modules/bootstrap-sass/assets/stylesheets/bootstrap";

// Font-awesome
@import "../../../node_modules/font-awesome/scss/font-awesome.scss";

// SweetAlert
@import "../../../node_modules/sweetalert/dev/sweetalert.scss";

Problemas no cors da api laravel

Baixei o projeto e tentei executar, mas não rola, dá erro na hora de enviar a requisição de login. Alguém mais com esse erro?
Olhem o anexo:
ccast

Prevents logged user

Prevent the user from accessing the auth route like /auth/signin if logged in.

Fractal error while navigating in the Product list

Type error: Argument 1 passed to App\Transformers\CategoryTransformer::transform() must be an instance of App\Category, null given, called in /Users/vedovelli/Codecasts/spa-starter-kit/webservice/vendor/league/fractal/src/Scope.php on line 365

This is the message coming from the server.

Could you please take a look? Thanks!

Bootstrap 4

Just a suggestion, but we've been building with Bootstrap 4 for a while now, and it's very stable - at Alpha 5 now.

Would you consider updating the starter kit to use Bootstrap 4?

npm install [email protected]

Token expired

Hi..
I've been found a bug.
After about 60 minutes without making a request to the server, if you try to press any button (ex: edit categories) that executes a request, you will have a redirect with the following error message.

Good new year at all :)
fireshot capture 008 - codecasts com br - spa - starter k_ - https___spa codecasts rocks_auth_singin

This is the json response message:

{"messages":["Token has expired"],"reason":"token_expired","trace":[{"file":"\/var\/www\/vhosts\/spa.vedcasts.com.br\/httpdocs\/vendor\/tymon\/jwt-auth\/src\/Http\/Middleware\/Authenticate.php","line":30,"function":"authenticate","class":"Tymon\\JWTAuth\\Http\\Middleware\\BaseMiddleware","type":"->","args":[{"attributes":{},"request":{},"query":{},"server":{},"files":{},"cookies":{},"headers":{}}]},{"file":"\/var\/www\/vhosts\/spa.vedcasts.com.br\/httpdocs\/bootstrap\/cache\/compiled.php","line":9904,"function":"handle","class":"Tymon\\JWTAuth\\Http\\Middleware\\Authenticate","type":"->","args":[{"attributes":{},"request":{},"query":{},"server":{},"files":{},"cookies":{},"headers":{}},{}]},{"file":"\/var\/www\/vhosts\/spa.vedcasts.com.br\/httpdocs\/vendor\/laravel\/framework\/src\/Illuminate\/Routing\/Pipeline.php","line":33,"function":"Illuminate\\Pipeline\\{closure}","class":"Illuminate\\Pipeline\\Pipeline","type":"->","args":[{"attributes":{},"request":{},"query":{},"server":{},"files":{},"cookies":{},"headers":{}}]},{"file":"\/var\/www\/vhosts\/spa.vedcasts.com.br\/httpdocs\/vendor\/barryvdh\/laravel-cors\/src\/HandleCors.php","line":42,"function":"Illuminate\\Routing\\{closure}","class":"Illuminate\\Routing\\Pipeline","type":"->","args":[{"attributes":{},"request":{},"query":{},"server":{},"files":{},"cookies":{},"headers":{}}]},{"file":"\/var\/www\/vhosts\/spa.vedcasts.com.br\/httpdocs\/bootstrap\/cache\/compiled.php","line":9904,"function":"handle","class":"Barryvdh\\Cors\\HandleCors","type":"->","args":[{"attributes":{},"request":{},"query":{},"server":{},"files":{},"cookies":{},"headers":{}},{}]},{"file":"\/var\/www\/vhosts\/spa.vedcasts.com.br\/httpdocs\/vendor\/laravel\/framework\/src\/Illuminate\/Routing\/Pipeline.php","line":33,"function":"Illuminate\\Pipeline\\{closure}","class":"Illuminate\\Pipeline\\Pipeline","type":"->","args":[{"attributes":{},"request":{},"query":{},"server":{},"files":{},"cookies":{},"headers":{}}]},{"file":"\/var\/www\/vhosts\/spa.vedcasts.com.br\/httpdocs\/bootstrap\/cache\/compiled.php","line":10012,"function":"Illuminate\\Routing\\{closure}","class":"Illuminate\\Routing\\Pipeline","type":"->","args":[{"attributes":{},"request":{},"query":{},"server":{},"files":{},"cookies":{},"headers":{}}]},{"file":"\/var\/www\/vhosts\/spa.vedcasts.com.br\/httpdocs\/bootstrap\/cache\/compiled.php","line":9904,"function":"handle","class":"Illuminate\\Routing\\Middleware\\SubstituteBindings","type":"->","args":[{"attributes":{},"request":{},"query":{},"server":{},"files":{},"cookies":{},"headers":{}},{}]},{"file":"\/var\/www\/vhosts\/spa.vedcasts.com.br\/httpdocs\/vendor\/laravel\/framework\/src\/Illuminate\/Routing\/Pipeline.php","line":33,"function":"Illuminate\\Pipeline\\{closure}","class":"Illuminate\\Pipeline\\Pipeline","type":"->","args":[{"attributes":{},"request":{},"query":{},"server":{},"files":{},"cookies":{},"headers":{}}]},{"file":"\/var\/www\/vhosts\/spa.vedcasts.com.br\/httpdocs\/vendor\/laravel\/framework\/src\/Illuminate\/Routing\/Middleware\/ThrottleRequests.php","line":49,"function":"Illuminate\\Routing\\{closure}","class":"Illuminate\\Routing\\Pipeline","type":"->","args":[{"attributes":{},"request":{},"query":{},"server":{},"files":{},"cookies":{},"headers":{}}]},{"file":"\/var\/www\/vhosts\/spa.vedcasts.com.br\/httpdocs\/bootstrap\/cache\/compiled.php","line":9904,"function":"handle","class":"Illuminate\\Routing\\Middleware\\ThrottleRequests","type":"->","args":[{"attributes":{},"request":{},"query":{},"server":{},"files":{},"cookies":{},"headers":{}},{},"60","1"]},{"file":"\/var\/www\/vhosts\/spa.vedcasts.com.br\/httpdocs\/vendor\/laravel\/framework\/src\/Illuminate\/Routing\/Pipeline.php","line":33,"function":"Illuminate\\Pipeline\\{closure}","class":"Illuminate\\Pipeline\\Pipeline","type":"->","args":[{"attributes":{},"request":{},"query":{},"server":{},"files":{},"cookies":{},"headers":{}}]},{"file":"\/var\/www\/vhosts\/spa.vedcasts.com.br\/httpdocs\/bootstrap\/cache\/compiled.php","line":9889,"function":"Illuminate\\Routing\\{closure}","class":"Illuminate\\Routing\\Pipeline","type":"->","args":[{"attributes":{},"request":{},"query":{},"server":{},"files":{},"cookies":{},"headers":{}}]},{"file":"\/var\/www\/vhosts\/spa.vedcasts.com.br\/httpdocs\/bootstrap\/cache\/compiled.php","line":8191,"function":"then","class":"Illuminate\\Pipeline\\Pipeline","type":"->","args":[{}]},{"file":"\/var\/www\/vhosts\/spa.vedcasts.com.br\/httpdocs\/bootstrap\/cache\/compiled.php","line":8182,"function":"runRouteWithinStack","class":"Illuminate\\Routing\\Router","type":"->","args":[{},{"attributes":{},"request":{},"query":{},"server":{},"files":{},"cookies":{},"headers":{}}]},{"file":"\/var\/www\/vhosts\/spa.vedcasts.com.br\/httpdocs\/bootstrap\/cache\/compiled.php","line":8173,"function":"dispatchToRoute","class":"Illuminate\\Routing\\Router","type":"->","args":[{"attributes":{},"request":{},"query":{},"server":{},"files":{},"cookies":{},"headers":{}}]},{"file":"\/var\/www\/vhosts\/spa.vedcasts.com.br\/httpdocs\/bootstrap\/cache\/compiled.php","line":2471,"function":"dispatch","class":"Illuminate\\Routing\\Router","type":"->","args":[{"attributes":{},"request":{},"query":{},"server":{},"files":{},"cookies":{},"headers":{}}]},{"file":"\/var\/www\/vhosts\/spa.vedcasts.com.br\/httpdocs\/vendor\/laravel\/framework\/src\/Illuminate\/Routing\/Pipeline.php","line":53,"function":"Illuminate\\Foundation\\Http\\{closure}","class":"Illuminate\\Foundation\\Http\\Kernel","type":"->","args":[{"attributes":{},"request":{},"query":{},"server":{},"files":{},"cookies":{},"headers":{}}]},{"file":"\/var\/www\/vhosts\/spa.vedcasts.com.br\/httpdocs\/vendor\/barryvdh\/laravel-cors\/src\/HandleCors.php","line":42,"function":"Illuminate\\Routing\\{closure}","class":"Illuminate\\Routing\\Pipeline","type":"->","args":[{"attributes":{},"request":{},"query":{},"server":{},"files":{},"cookies":{},"headers":{}}]},{"file":"\/var\/www\/vhosts\/spa.vedcasts.com.br\/httpdocs\/bootstrap\/cache\/compiled.php","line":9904,"function":"handle","class":"Barryvdh\\Cors\\HandleCors","type":"->","args":[{"attributes":{},"request":{},"query":{},"server":{},"files":{},"cookies":{},"headers":{}},{}]},{"file":"\/var\/www\/vhosts\/spa.vedcasts.com.br\/httpdocs\/vendor\/laravel\/framework\/src\/Illuminate\/Routing\/Pipeline.php","line":33,"function":"Illuminate\\Pipeline\\{closure}","class":"Illuminate\\Pipeline\\Pipeline","type":"->","args":[{"attributes":{},"request":{},"query":{},"server":{},"files":{},"cookies":{},"headers":{}}]},{"file":"\/var\/www\/vhosts\/spa.vedcasts.com.br\/httpdocs\/bootstrap\/cache\/compiled.php","line":3226,"function":"Illuminate\\Routing\\{closure}","class":"Illuminate\\Routing\\Pipeline","type":"->","args":[{"attributes":{},"request":{},"query":{},"server":{},"files":{},"cookies":{},"headers":{}}]},{"file":"\/var\/www\/vhosts\/spa.vedcasts.com.br\/httpdocs\/bootstrap\/cache\/compiled.php","line":9904,"function":"handle","class":"Illuminate\\Foundation\\Http\\Middleware\\CheckForMaintenanceMode","type":"->","args":[{"attributes":{},"request":{},"query":{},"server":{},"files":{},"cookies":{},"headers":{}},{}]},{"file":"\/var\/www\/vhosts\/spa.vedcasts.com.br\/httpdocs\/vendor\/laravel\/framework\/src\/Illuminate\/Routing\/Pipeline.php","line":33,"function":"Illuminate\\Pipeline\\{closure}","class":"Illuminate\\Pipeline\\Pipeline","type":"->","args":[{"attributes":{},"request":{},"query":{},"server":{},"files":{},"cookies":{},"headers":{}}]},{"file":"\/var\/www\/vhosts\/spa.vedcasts.com.br\/httpdocs\/bootstrap\/cache\/compiled.php","line":9889,"function":"Illuminate\\Routing\\{closure}","class":"Illuminate\\Routing\\Pipeline","type":"->","args":[{"attributes":{},"request":{},"query":{},"server":{},"files":{},"cookies":{},"headers":{}}]},{"file":"\/var\/www\/vhosts\/spa.vedcasts.com.br\/httpdocs\/bootstrap\/cache\/compiled.php","line":2415,"function":"then","class":"Illuminate\\Pipeline\\Pipeline","type":"->","args":[{}]},{"file":"\/var\/www\/vhosts\/spa.vedcasts.com.br\/httpdocs\/bootstrap\/cache\/compiled.php","line":2399,"function":"sendRequestThroughRouter","class":"Illuminate\\Foundation\\Http\\Kernel","type":"->","args":[{"attributes":{},"request":{},"query":{},"server":{},"files":{},"cookies":{},"headers":{}}]},{"file":"\/var\/www\/vhosts\/spa.vedcasts.com.br\/httpdocs\/public\/index.php","line":53,"function":"handle","class":"Illuminate\\Foundation\\Http\\Kernel","type":"->","args":[{"attributes":{},"request":{},"query":{},"server":{},"files":{},"cookies":{},"headers":{}}]}]}

[doc] Improve code with readme.md in folders

add an readme.md in some folders

Client

  • /client/src
  • /client/src/app
  • /client/src/app/auth/components
  • /client/src/app/auth/routes
  • /client/src/app/auth/vuex
  • /client/src/components
  • /client/src/root
  • /client/src/router
  • /client/src/store

Query parameters

Hey guys, do you think it would be nice to have query parameters when requesting data from the API?

Example /api/categories?limit=10&sort=name&order=desc

API Response Format

Would be nice if all of spa-starter-kit's REST API responses conform to the JSend Specification.

This means that every response will have a status and a data field in the JSON response. The status field will give either a success or fail. In the case of a success, the data will contain the requested data. In the case of a fail, the data will contain error messages.

For example, in the case of a bad request:

{
  "status": "fail",
  "data": {
    "errors": [
      { "name": "title", "message": "cannot be this ridiculous" },
      { "name": "description", "message": "must be provided" }       
    ]
  }
}

Here is an example of a successful request of a public profile:

{
  "status": "success",
  "data": {
    "id": 1,
    "email": "[email protected]"
  }
}

What about Dynamic Page Title & Meta Info?

no doubt it's great effort from your side.

but i searched lot on internet but can't find any proper solution for Routes Page Title & Meta info.

you should add this feature too in your repo.

it'll help me lot & others too :)

JavaScript Style

Curious to know why the project isn't using the 'standard' eslint settings. There are Webpack options for linting that come ready to go with the Vuejs.org Webpack template starter (on which this project is based)...

https://github.com/vuejs-templates/webpack
https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style

Dangling commas in particular are a PHP PSR recommendation I believe, but not usually found in JavaScript.

No strong feelings here, but curious nevertheless. ;-)

Should we migrate to Lumen?

Hi guys,

I recently have started developing an API using Lumen, and in my experience has been quite simple and faster than using Laravel itself.

I think the reason is that Laravel is not meant for just APIs, so he brings a lot of things that we don't need when building an API, like session management, CSRF protection among other things.

So I was thinking if it is worth migrate to Lumen? because in my opinion, the API would be faster and the code would be more clean and simple.

What do you guys think?

Unable to get roles and permissions

How are you doing! I use Ultraware/Roles this permission pack. ``
User::find(1)->getRoles();
Gets the role to be empty, but the Laravel auth can fetch;

Error Handling, Validators, the Interceptor and Response Formats

Just a few thoughts, suggestions and observations here...

There are a few strategies in Laravel/Eloquent for creating and saving models. We typically test for...

// We have static event rules on the model. This will return a 422 invalid entity response
$this->validate($request, Product::getCreateValidationRules($id), Product::getCreateValidationMessages());
$attributes = $request->all();
$event = new Product($attributes);
if($event->save())  {
    ...
   // Send success response - 200
} else {
  // Send failed response - or exception 
}

Or for updates...

$this->validate($request, Product::getUpdateValidationRules($id), Product::getUpdateValidationMessages());
// This will automatically send a 404 not found response - although probably not what you 
// want if you are going to transform the output - see below...
$event = Product::findOrFail($id);
$attributes = $request->all();
if($event->update($attributes)) {
   // Send success response - 200
} else {
  // Send failed response - or exception
}

Sending a response of return $this->response([ 'result' => 'success',]); is okay, but slightly RPC-ish in so far as the result status is duplicated by the http status - 200 is okay, 422 validation failure, 400 invalid client data, 500 server error etc.

Also I see you've included league/fractal package for response transforms which is excellent. The maintainers of the package refer to HAL, and JSON-API as possible output formats. A complete API design might be outside the scope of your starter pack - but there are some great pointers in http://stateless.co/hal_specification.html, http://jsonapi.org/format/ (albeit a bit 'rails-ish) , and even https://github.com/argo-rest/spec Here's an example format for an in-house API we created. Error, and Errors are first class - https://gist.github.com/58bits/aa14c7a8f525a074f7a6aaf5b9dd60b6

It might be nice if you created a simplified version of any of the above, using league/fractal transformer to create an API response format to abstract away from Laravel's default Json response - which would nicely decouple your starter-pack from Laravel itself.

Also in terms of handling errors in the http plugin (Axios) - you've got a great global error handler in the interceptor, but sniffing for the return type (array or object) to determine the error type is a little brittle. With a standard response format, and errors, response codes, all first class, you can make the switch based on the response code and data itself (e.g.. 422 for invalid entities etc. - and then check for the error or errors properties.)

In the http client for the entities/forms, I also think you still need a catch handler (even if it's empty), for example...

update () {
        this.$http.put(`events/${this.event.id}`, this.event).then(() => {
          /**
          * This event will notify the world about
          * the event creation. In this case
          * the Event main component will intercept
          * the event and refresh the list.
          */
          this.$bus.$emit('event.updated')

          /**
          * Hides the global spinner
          */
          this.setFetching({ fetching: false })

          /**
          * Sets the global feedback message
          */
          this.setMessage({ type: 'success', message: 'Event was updated' })
        }).catch((error) => {
          console.log('our own error handler.')
          console.log(error)
        })
      },

... Otherwise axios will generate an uncaught in Promise exception, and dump this to the console as...

Uncaught (in promise) Error: Request failed with status code 422
    at createError (eval at <anonymous> (app.js:876), <anonymous>:15:15)
    at settle (eval at <anonymous> (app.js:1104), <anonymous>:18:12)
    at XMLHttpRequest.handleLoad (eval at <anonymous> (app.js:858), <anonymous>:77:7)

Very lastly, just in case you or anyone else is using Xdebug to debug your PHP API server (Laravel in this case), here's an updated interceptors.js file, which will add the XDEBUG_SESSION_START parameter to the query string (or post values) for all requests, to tell XDEBUG to debug the request. This is a a little hacky, and I'm using PHPStorm as my debugger client. The session identifier is generated by PHPStorm (which is listening for incoming Xdebugger requests). XDEBUG_SESSION_START can be used for the same session repeatedly, and it's a better method than trying to set the XDEBUG_SESSION session cookie, as cookies will fail to be set if you're making a CORS request to the API server.

https://gist.github.com/58bits/c7b7dccf3f922fde13275d1a54990838

And the PHPStorm docs for setting up Xdebug here... https://www.jetbrains.com/help/phpstorm/2016.2/configuring-xdebug.html

Hope some of this helps, and thanks for the great starter kit. It's helping us a lot in getting started with Vuejs.org.

Uncaught SyntaxError: Unexpected token import

Fresh install and now get the following. I am running on Windows 10.

Uncaught SyntaxError: Unexpected token import
    at Object.<anonymous> (app.js:2162)
    at __webpack_require__ (app.js:583)
    at fn (app.js:107)
    at eval (eval at <anonymous> (app.js:2082), <anonymous>:8:19)
    at Object.<anonymous> (app.js:2082)
    at __webpack_require__ (app.js:583)
    at fn (app.js:107)
    at eval (eval at <anonymous> (app.js:1548), <anonymous>:17:13)
    at Object.<anonymous> (app.js:1548)
    at __webpack_require__ (app.js:583)

Critical dependency warning: localforage.js

When running yarn run dev:

Child html-webpack-plugin for "index.html":
         Asset     Size  Chunks       Chunk Names
    index.html  1.47 MB       0
webpack: bundle is now VALID.
webpack: bundle is now INVALID.
webpack building...
webpack built 6207064b6b09e040d5fd in 285ms
Hash: 6207064b6b09e040d5fd
Version: webpack 1.14.0
Time: 285ms
                 Asset       Size  Chunks             Chunk Names
      0.auth-bundle.js    35.3 kB       0             auth-bundle
     1.parks-bundle.js     582 kB       1             parks-bundle
  2.products-bundle.js      57 kB       2             products-bundle
3.categories-bundle.js    54.2 kB       3             categories-bundle
                app.js    6.21 MB       4             app
 5.dashboard-bundle.js      14 kB       5             dashboard-bundle
            index.html  342 bytes          [emitted]

WARNING in ./~/localforage/dist/localforage.js
Critical dependencies:
7:484-491 This seems to be a pre-built javascript file. Though this is possible, it's not recommended. Try to require the original source to get better results.
 @ ./~/localforage/dist/localforage.js 7:484-491

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.