first commit

This commit is contained in:
benjibennn
2023-12-22 12:35:55 +08:00
commit 9f89a732d6
872 changed files with 156291 additions and 0 deletions

2
wave/docs/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
/node_modules
package-lock.json

33
wave/docs/_sidebar.md Normal file
View File

@@ -0,0 +1,33 @@
- Getting started
- [Welcome](/welcome.md)
- [Installation](/installation.md)
- [Configurations](/configurations.md)
- [Upgrading](/upgrading.md)
- Features
- [Authentication](/features/authentication.md)
- [User Profiles](/features/user-profiles.md)
- [User Impersonation](/features/user-impersonation.md)
- [Billing](/features/billing.md)
- [Subscription Plans](/features/subscription-plans.md)
- [User Roles](/features/user-roles.md)
- [Notifications](/features/notifications.md)
- [Announcements](/features/announcements.md)
- [Blog](/features/blog.md)
- [API](/features/api.md)
- [Admin](/features/admin.md)
- [Themes](/features/themes.md)
- Basic Concepts
- [Routing](/concepts/routing.md)
- [Themes](/concepts/themes.md)
- [Structure](/concepts/structure.md)
- Resources
- [Video Tutorials](https://devdojo.com/series/wave)
- [Support](https://devdojo.com/forums/category/wave)
- [Laravel](https://laravel.com)
- [Voyager](https://voyager.devdojo.com)

33
wave/docs/assets/app.js Normal file
View File

@@ -0,0 +1,33 @@
import 'alpinejs';
window.inIframe = function() {
try {
return window.self !== window.top;
} catch (e) {
return true;
}
}
document.addEventListener('DOMContentLoaded', function(){
if(inIframe()){
hideIframeElements();
}
});
window.hideIframeElements = function(){
document.getElementById('backToSiteBtn').classList.add('hidden');
}
window.searchFocused = function(focused){
if(focused){
document.getElementById('sidebar').classList.remove('overflow-scroll');
document.getElementById('bg-fade').classList.remove('invisible');
document.getElementById('bg-fade').classList.remove('opacity-0');
document.getElementById('bg-fade').classList.add('opacity-25');
} else {
document.getElementById('sidebar').classList.add('overflow-scroll');
document.getElementById('bg-fade').classList.add('invisible');
document.getElementById('bg-fade').classList.add('opacity-0');
document.getElementById('bg-fade').classList.remove('opacity-25');
}
}

40
wave/docs/assets/app.scss Normal file
View File

@@ -0,0 +1,40 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
[x-cloak]{
display:none;
}
html, body {
scroll-behavior: smooth;
}
.docs{
.prose h1, .lg\:prose-xl h1{
@apply bg-clip-text text-transparent bg-gradient-to-r from-wave-500 to-purple-500 mb-5 pb-5;
}
.prose pre{
background:#1e1b47;
}
.prose p code{
font-size: 15px;
color: #3c4257;
font-weight: 500;
padding: 1px 2px;
background: #f8fafc;
border: 1px solid #e3e8ee;
border-radius: 4px;
&::before, &::after{
content:"";
}
}
.prose blockquote p{
&::before, &::after{
content: "";
}
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,4 @@
{
"/js/app.js": "/js/app.js",
"/css/app.css": "/css/app.css"
}

View File

@@ -0,0 +1,160 @@
# Routing
In this section we'll quickly cover the Wave routes.
- [Wave Web Routes](#web-routes)
- [Wave API Routes](#api-routes)
- [Wave Middleware](#wave-middleware)
---
<a name="web-routes"></a>
### Wave Web Routes
If you take a look inside of `wave/routes/web.php` you will see all the Wave web routes:
```php
<?php
Route::impersonate();
Route::get('/', '\Wave\Http\Controllers\HomeController@index')->name('wave.home');
Route::get('@{username}', '\Wave\Http\Controllers\ProfileController@index')->name('wave.profile');
// Documentation routes
Route::view('docs/{page?}', 'docs::index')->where('page', '(.*)');
// Additional Auth Routes
Route::get('logout', 'Auth\LoginController@logout')->name('logout');
Route::get('user/verify/{verification_code}', 'Auth\RegisterController@verify')->name('verify');
Route::post('register/complete', '\Wave\Http\Controllers\Auth\RegisterController@complete')->name('wave.register-complete');
Route::get('blog', '\Wave\Http\Controllers\BlogController@index')->name('wave.blog');
Route::get('blog/{category}', '\Wave\Http\Controllers\BlogController@category')->name('wave.blog.category');
Route::get('blog/{category}/{post}', '\Wave\Http\Controllers\BlogController@post')->name('wave.blog.post');
Route::view('install', 'wave::install')->name('wave.install');
/***** Pages *****/
Route::get('p/{page}', '\Wave\Http\Controllers\PageController@page');
/***** Pricing Page *****/
Route::view('pricing', 'theme::pricing')->name('wave.pricing');
/***** Billing Routes *****/
Route::post('/billing/webhook', '\Wave\Http\Controllers\WebhookController@handleWebhook');
Route::post('paddle/webhook', '\Wave\Http\Controllers\SubscriptionController@hook');
Route::post('checkout', '\Wave\Http\Controllers\SubscriptionController@checkout')->name('checkout');
Route::get('test', '\Wave\Http\Controllers\SubscriptionController@test');
Route::group(['middleware' => 'wave'], function () {
Route::get('dashboard', '\Wave\Http\Controllers\DashboardController@index')->name('wave.dashboard');
});
Route::group(['middleware' => 'auth'], function(){
Route::get('settings/{section?}', '\Wave\Http\Controllers\SettingsController@index')->name('wave.settings');
Route::post('settings/profile', '\Wave\Http\Controllers\SettingsController@profilePut')->name('wave.settings.profile.put');
Route::put('settings/security', '\Wave\Http\Controllers\SettingsController@securityPut')->name('wave.settings.security.put');
Route::post('settings/api', '\Wave\Http\Controllers\SettingsController@apiPost')->name('wave.settings.api.post');
Route::put('settings/api/{id?}', '\Wave\Http\Controllers\SettingsController@apiPut')->name('wave.settings.api.put');
Route::delete('settings/api/{id?}', '\Wave\Http\Controllers\SettingsController@apiDelete')->name('wave.settings.api.delete');
Route::get('settings/invoices/{invoice}', '\Wave\Http\Controllers\SettingsController@invoice')->name('wave.invoice');
Route::get('notifications', '\Wave\Http\Controllers\NotificationController@index')->name('wave.notifications');
Route::get('announcements', '\Wave\Http\Controllers\AnnouncementController@index')->name('wave.announcements');
Route::get('announcement/{id}', '\Wave\Http\Controllers\AnnouncementController@announcement')->name('wave.announcement');
Route::post('announcements/read', '\Wave\Http\Controllers\AnnouncementController@read')->name('wave.announcements.read');
Route::get('notifications', '\Wave\Http\Controllers\NotificationController@index')->name('wave.notifications');
Route::post('notification/read/{id}', '\Wave\Http\Controllers\NotificationController@delete')->name('wave.notification.read');
/********** Checkout/Billing Routes ***********/
Route::post('cancel', '\Wave\Http\Controllers\SubscriptionController@cancel')->name('wave.cancel');
Route::view('checkout/welcome', 'theme::welcome');
Route::post('subscribe', '\Wave\Http\Controllers\SubscriptionController@subscribe')->name('wave.subscribe');
Route::view('trial_over', 'theme::trial_over')->name('wave.trial_over');
Route::view('cancelled', 'theme::cancelled')->name('wave.cancelled');
Route::post('switch-plans', '\Wave\Http\Controllers\SubscriptionController@switchPlans')->name('wave.switch-plans');
});
Route::group(['middleware' => 'admin.user'], function(){
Route::view('admin/do', 'wave::do');
});
```
Next, if you take a look inside of your `routes/web.php`, you will see the following line:
```php
// Include Wave Routes
Wave::routes();
```
This line includes all the Wave routes into your application.
<a name="api-routes"></a>
### Wave API Routes
The Wave API routes are located at `wave/routes/api.php`. The contents of the file are as follows:
```php
Route::post('login', '\Wave\Http\Controllers\API\AuthController@login');
Route::post('register', '\Wave\Http\Controllers\API\AuthController@register');
Route::post('logout', '\Wave\Http\Controllers\API\AuthController@logout');
Route::post('refresh', '\Wave\Http\Controllers\API\AuthController@refresh');
Route::post('token', '\Wave\Http\Controllers\API\AuthController@token');
// BROWSE
Route::get('/{datatype}', '\Wave\Http\Controllers\API\ApiController@browse');
// READ
Route::get('/{datatype}/{id}', '\Wave\Http\Controllers\API\ApiController@read');
// EDIT
Route::put('/{datatype}/{id}', '\Wave\Http\Controllers\API\ApiController@edit');
// ADD
Route::post('/{datatype}', '\Wave\Http\Controllers\API\ApiController@add');
// DELETE
Route::delete('/{datatype}/{id}', '\Wave\Http\Controllers\API\ApiController@delete');
```
Then, if you take a look inside of your `routes/api.php`, you will see the following line:
```php
// Include Wave Routes
Wave::api();
```
This line includes all the Wave API routes into your application API.
<a name="wave-middleware"></a>
### Wave Middleware
Inside of the Wave routes.php file you will see the following line:
```php
Route::group(['middleware' => 'wave'], function () {
Route::get('dashboard', '\Wave\Http\Controllers\DashboardController@index')->name('wave.dashboard');
});
```
This is the only current route protected by the `wave` middleware. The `wave` middleware is used to protect routes against users who no longer have an active subscription or are no longer on a trial. You can include your application routes inside of this middleware:
```php
Route::group(['middleware' => 'wave'], function () {
// Add your application routes here.
});
```
You may also wish to include this middleware in a single route:
```php
Route::get('awesome', 'AwesomeController@index')->middleware('wave');
```
And now your application routes will be protected from users who are no longer active paying users.

View File

@@ -0,0 +1,98 @@
# File Structure
In this section of the documentaion we will briefly discuss the file structure of Wave so that way you can better familiarize yourself with how Wave functions.
- [Root Folder Structure](#root-structure)
- [Wave Folder Structure](#wave-structure)
---
<a name="root-structure"></a>
### Root Folder Structure
If you are already familiar with Laravel a lot of this will seem very familiar. Let's discuss each main folder/file in your Wave application.
> bold text indicates a folder, non-bold indicates a file.
- **app** -
This directory will hold most (if not all) of your application logic including Models, Controllers, Services, and many other classes.
- **bootstrap** -
This folder contains files to bootstrap (start-up) Laravel.
- **config** -
This folder will container many of the global configurations in our application.
- **database** -
This folder contains database files such as migrations and seeds.
- **public** -
This public folder contains many of the applications public assets such as images, stylesheets, and scripts.
- **resources** -
This folder contains the views inside of our application and it also contains our theme files located inside of `resources/views/themes` folder.
- **routes** -
This folder will contain all the routes files for our application.
- **storage** -
This folder is used to store session information, cache files, and logs.
- **tests** -
This folder contains files that we use to test the logic of our application.
- **vendor** -
This folder contains the composer (third-party) dependencies we use in our application.
- **wave** -
This folder contains all the logic for the wave application. We'll be talking more about the contents of this folder in the next step.
- *.env.example* -
This is an example environment file. Duplicate this file and rename it to `.env` in order to make it your application environment file.
- *artisan* -
This is the artisan command we use to run CLI commands, such as `php artisan tinker` and many others.
- *composer.json* -
This is the file that tells our application what third-party composer packages we want to include.
- *composer.lock* -
This is the file that contains the exact version number of the composer packages included in our application.
- *deploy.json* -
This file contains information to deploy your app to the DigitalOcean app marketplace.
- *docker-compose.yml* -
This is a docker compose file that will allow you to run your app using <a href="https://laravel.com/docs/sail" target="_blank">Laravel Sail</a>.
- *phpunit.xml* -
This file is used to store information in order to run tests and test the functionality of our application.
- *README.md* -
This is a quick Readme Markdown file.
- *server.php* -
This is the file that allows us to create a quick local PHP server.
<a name="wave-structure"></a>
### Wave Folder Structure
The Wave folder structure is pretty simple and straight forward. If you look inside the `wave` folder located in the application folder you will see the following folder structure:
- **database** -
This folder contains the migration files needed for our Wave application.
- **docs** -
This folder contains the documentation files. The files from which you are reading right now.
- **resources** -
This folder contains a few shared views used by Wave.
- **routes** -
This folder contains the routes defined for our wave application. You will see the web routes located at `wave/routes/web.php` and the API routes located at `/wave/routes/api.php`, go ahead and feel free to take a look at the defined routes.
- **src** -
This is where all the logic happens for our Wave application including Models, Controllers, Helpers, and much more.
- *composer.json* -
This file is used to require any dependencies required by Wave.

View File

@@ -0,0 +1,87 @@
# Themes
In this section we'll teach you how to create a new theme, reference a theme view, and add theme options for your particular theme.
- [Create a Theme](#create-theme)
- [Theme Views](#theme-views)
- [Theme Options](#theme-options)
- [Theme Assets](#theme-assets)
---
<a name="create-theme"></a>
## Create a Theme
In order to create a theme, you will need to create a new folder inside of `resources/views/themes`. Let's call this folder `sample-theme`. Then inside of this folder we need a matching filename called `sample-theme.json`:
```json
{
"name": "Sample Theme",
"version": "1.0"
}
```
Now, if you visit `/admin/themes`, you'll see this new theme available to activate.
> You may see a broken image in the admin if you do not have an image for that theme. Inside of your theme folder you will need a `.jpg` file with the same name as the folder `sample-theme.jpg` (recommended 800x500px)
<a name="theme-views"></a>
## Theme Views
After activating a theme you can render any view `file.blade.php` or `file.php` by calling `theme::file`.
For instance, if we created a new file inside our sample theme at `resources/views/themes/sample-theme/home.blade.php` we could then return the view in a controller like so:
```php
public function home(){
return view('theme::home');
}
```
Or, you could do this inside of your route file:
```php
Route::view('/', 'theme::home');
```
<a name="theme-options"></a>
## Theme Options
Every theme can include options such as logo, color scheme, etc... You can choose to program any amount of options into your theme.
In order to create an *options* page for your theme you need to create a new file inside your theme folder called `options.blade.php`. As an example take a look at the Tailwind theme options located at `resources/views/themes/tailwind/options.blade.php`, you will see a snippet similar to:
```php
<div id="branding" class="tab-pane fade in active">
{!! theme_field('image', 'logo', 'Site Logo') !!}
{!! theme_field('image', 'footer_logo', 'Footer Logo') !!}
</div>
```
This will allow us to create some dynamic theme fields. This is powered by the [DevDojo Themes Package](https://github.com/thedevdojo/themes). You can easily create input fields for your theme options.
For more information about the different type of fields be sure to visit the themes package located at [https://github.com/thedevdojo/themes](https://github.com/thedevdojo/themes)
<a name="theme-assets"></a>
## Theme Assets
The current themes use Webpack to mix their assets. In order to run the assets for each theme you will need to go into the theme folder and run:
```javascript
npm run watch
```
Additionally, to compile the assets and make them production ready, you'll need to use:
```javascript
npm run production
```
> Before compiling assets in each theme you may need to include the asset dependencies by running `npm install` inside of the theme folder.
---
Now, you can quickly and easily create configurable themes for your application 🎉

115
wave/docs/configurations.md Normal file
View File

@@ -0,0 +1,115 @@
# Configurations
Wave has many configs to help you customize and build your SAAS app!
Wave is also built on top of Voyager, so all the Voyager configs are available to you as well. To learn more about those you can check out the <a href="https://voyager-docs.devdojo.com/getting-started/configurations" target="_blank">voyager docs here</a>.
---
- [Settings](#settings)
- [Configs](#configs)
<a name="settings"></a>
## Wave Settings Configuration
There are many settings available in your Wave admin section. Visit `/admin/settings` and you will be at your application settings. Which has the following settings you can modify.
> In order to login to the admin section of your application you can use the following credentials `admin@admin.com` and password as `password`
### Site Settings
From the Site Settings tab you can modify the following settings:
- **Site Title** - The title of your application
- **Site Description** - The description of your application
- **Google Analytics Tracking ID** - Enter your Analytics Tracking code to track page views and analytics
- **Favicon** - Upload your application favicon
### Admin Settings
These are settings to customize your admin
- **Admin Title** - The title of you application admin
- **Google Analytics Client ID** - This is used to show Google Analytics in your admin dashboard
- **Admin Description** - The description of your application admin
- **Admin Loader** - The loading image for your admin
- **Admin Icon Image** - The admin or application icon image
### Authentication Settings
- **Homepage Redirect to Dashboard if Logged in** - When an authenticated user visits the homepage you may with to redirect them to the application dashboard
- **Users Login with Email or Username** - Choose whether you want your users to login with their email or username
- **Username when Registering** - Show the username in the signup form or have it automatically generated based on the users name
- **Verify Email during Sign Up** - Enable this setting if you want your users to verify their email before being able to login
### Billing
- **Require Credit Card Up Front** - You can choose whether or not you want users to enter a credit card while signing up
- **Trial Days when No Credit Card Up Front** - Specify the amount of total trial days. Specify `-1` if you don't want to have any trial days.
---
<a name="configs"></a>
## Wave Configuration File
There are a few logical configurations you can make within the wave configuration file located at `/config/wave.php`. The contents of that file is as follows:
```php
<?php
return [
'profile_fields' => [
'about'
],
'api' => [
'auth_token_expires' => 60,
'key_token_expires' => 1,
],
'auth' => [
'min_password_length' => 5,
],
'user_model' => App\Models\User::class,
'show_docs' => env('WAVE_DOCS', true),
'demo' => env('WAVE_DEMO', false),
'dev_bar' => env('WAVE_BAR', false),
'paddle' => [
'vendor' => env('PADDLE_VENDOR_ID', ''),
'auth_code' => env('PADDLE_VENDOR_AUTH_CODE', ''),
'env' => env('PADDLE_ENV', 'sandbox')
]
];
```
- **profile_fields** - Whenever you want to dynamically create a new user profile field such as `about`, `social_links`, or any other field you will need to include the field name in this config. You will learn all about *Custom Profile Fields* in the [User Profiles Section](/docs/features/user-profiles)
- **api => auth_token_expires** - This is the amount of time you want your JSON web token to expire. After this token has expired the app will then request a refresh token. You will most likely never need to change this value, but it's there if you need it.
- **api => key_token_expires** - This is the amount of time (in minutes) an API token will expire when it is generated with a user API Key.
A user can generate an API key in your application which is used to create an API token during a request. After the default **1** minute. The user or the users application will need to make another request with their API key.
- **auth => min_password_length** - This is the minimum password length a user must enter when registering for an acccount.
- **user_model** - This is the default user model of your application. In most cases this is going to be the `App\Models\User` model. If you are using a different user model you will want to add that here.
Remember your User Model will also need to extend the `\Wave\User` model. If you take a look at the `App\Models\User` model you can see it extends from the Wave user model:
```php
class User extends \Wave\User
```
- **show_docs** - When developing your application you may want to keep the documentation accessible in your app. Set this to false if you do not want the docs to be accessible.
- **demo** - This is primarily used for demo purposes of the Wave project, in your project you will probably want to set this to false (unless you want to test out some of the demo functionality).
- **dev_bar** - If you enable the **dev_bar**, you will have a developer bar at the bottom of your screen that will allow you to easily jump to the documentation or the admin.
- **paddle** - This is the configuration settings you will need to integrate billing into your application. You can learn more about these configurations from the [billing documentation](/docs/features/billing).
---
> Wave themes will give you unlimited configurations for your SAAS. We'll cover more of this later, or you can jump to the [Themes section by clicking here](/docs/features/themes).

View File

@@ -0,0 +1,75 @@
# Admin
Wave has been built using the Voyager Admin, which is an all-in-one admin interface for Laravel. This means that you can leverage all the powers of Wave with the power of Voyager as well.
> If you have not had a chance to check out the documentation be sure to head over to <a href="https://voyager-docs.devdojo.com" target="_blank">voyager-docs.devdojo.com</a> to learn more.
- [The Admin Interface](#admin-interface)
- [Admin Dashboard Sections](#admin-dashboard-sections)
---
<a name="admin-interface"></a>
### Admin Interface
You may have noticed the UI for the Wave admin may look a little different than the default Voyager theme.
![admin](https://cdn.devdojo.com/images/april2021/admin.png)
The different UI will have no effect on the Voyager functionality. Everything that you enjoy with Voyager will be the same with the Wave admin.
Next, lets briefly go over each section of the Voyager admin.
<a name="admin-dashboard-sections"></a>
### Admin Dashboard Sections
Inside of your admin dashboard there are 12 top-level sections which include:
1. Dashboard Home
2. Plans
3. Roles
4. Users
5. Media
6. Posts
7. Pages
8. Categories
9. Announcements
10. Tools
11. Settings
12. Themes
**Dashboard Home**
The Dashboard homepage is where you will land when you first login to the admin dashboard. You can view statistics on site traffic, users, posts, and many other content on your site.
**Plans**
In this section of the admin you can Add, Edit, Delete subscription plans associated with your Software as a Service.
**Roles**
In this section you can Add, Edit, Delete user roles and permissions in your application. A specific role will then be associated with a Subscription Plan above.
**Users**
You can view all the users of your application here. You can also Edit, Add, or Delete users of your application.
**Media**
This is your Media Manager where you can view all the media in your application. You can also Upload, Rename, and Delete current media.
**Posts**
This is where you can write blog posts related to your Software as a Service. you can also Edit or Delete current posts in your application.
**Pages**
You can add new pages to your application and link to them in the front-end. These pages might be an About page, Policy page, or any other page you need to add to your application.
**Categories**
You can add, edit, or delete post categories in this section. After creating a new category you can then categorize any post with this specific category in your application.
**Announcements**
In the announcements section you can add new announcements to be shown to your users. User will see the latest popup announcement when they visit your application so they can stay updated with the latest features or news related to your SAAS.
**Tools**
The tools section has a variety of tools that you can use to manage your SAAS including a Menu Builder, Bread Builder, and Database Structure.
**Settings**
In this section of you admin you can modify site-wide settings for your application including Authentication and Billing settings.
**Themes**
In this section you can view the current themes in your application, activate/deactivate themes, and edit theme settings.

View File

@@ -0,0 +1,34 @@
# Announcements
As you continue to improve your SAAS app youre going to need a quick and easy way to communicate with your users. Announcements are perfect for letting your users know about bug fixes or special promotions.
- [Creating an Announcement](#create-announcement)
- [Viewing an Announcement](#view-announcement)
---
<a name="create-announcement"></a>
### Creating an Announcement
You can create a new announcement by visiting the admin announcements section at `/admin/announcements`. If you have past announcement youll see them listed out. Then to create a new announcement youll want to click on Add New button.
![announcements 1](https://cdn.devdojo.com/images/april2021/announcements-1.png)
Then, simply add the content of your new announcement.
![announcements 2](https://cdn.devdojo.com/images/april2021/announcements-2.png)
And now your users will see your latest announcement the next time they visit your application.
<a name="view-announcement"></a>
### Viewing an Announcement
Every user in your application will see the latest announcement when they visit your application. The announcements will look as follows:
![announcements 3](https://cdn.devdojo.com/images/april2021/announcements-3.png)
The title and description will be displayed in the popup announcement. When the user clicks the announcement they will be taken to the announcement page where they can view the full content of the announcement.
![announcements 4](https://cdn.devdojo.com/images/april2021/announcements-4.png)
After the user clicks or closes the announcement they will no longer see that particular announcement.

147
wave/docs/features/api.md Normal file
View File

@@ -0,0 +1,147 @@
# API
Wave comes with an out-of-the-box API, which will allow you to provide an API to your users or build a mobile app from your API.
In this section we will go into more depth on how you can use the Wave API.
- [Access API Data](#access-data)
- [Access Token From API Key](#access-token-from-api-key)
- [Access Token from Login](#acess-token-from-login)
- [Requesting Data from Tokens](#request-data-from-token)
- [Testing Your API](#testing-api)
- [Registering via the API](#registering-via-api)
---
<a name="access-data"></a>
### Access Data from the API
In order to access data from the API a user or an application will need to pass an **Access Token** to the API. This access token will determine what kind of data can be accessed or returned.
There are 2 ways to get an Access Token:
1. You can request an **Access Token** from an API key.
2. You can request an **Access Token** with an email and password.
<a name="access-token-from-api-key"></a>
### Get Access Token from an API Key
To create an API key you can visit your API settings page at: `/settings/api`, then to create a new API key, enter a name in the textbox and click on the `Create New Key` button.
![api screenshot 1](https://cdn.devdojo.com/images/april2021/api-1.png)
After creating your new API key you will see it in the list of *Current API Keys*. You'll be able to see the Name, Date Created, and the Last Used. There are also 3 actions you can do with this new API Key. To view the current API Key. Click on the `View` button:
![api screenshot 2](https://cdn.devdojo.com/images/april2021/api-2.png)
And you will see the current API key where you can copy and paste it to be used.
![api screenshot 3](https://cdn.devdojo.com/images/april2021/api-3.png)
Next, you can click on the `Edit` button:
![api screenshot 4](https://cdn.devdojo.com/images/april2021/api-4.png)
Where you will be able to edit the current API key name.
![api screenshot 5](https://cdn.devdojo.com/images/april2021/api-5.png)
Lastly, if you click on the delete button:
![api screenshot 6](https://cdn.devdojo.com/images/april2021/api-6.png)
You will be able to delete the current API key.
![api screenshot 7](https://cdn.devdojo.com/images/april2021/api-7.png)
Next, let's move on to learning how you can use this API key to request an **Access Token** from the API. After we recieve the **Access Token** we can then use that to retrieve data from our application.
To request an **Access Token** we can submit a POST request to:
```php
/api/token?key=API_KEY_HERE
```
And you will get a response that looks similar to the following:
```json
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC93YXZlLnRlc3RcL2FwaVwvdG9rZW4iLCJpYXQiOjE1Mzk4MDg4OTUsImV4cCI6MTUzOTgxMjQ5NSwibmJmIjoxNTM5ODA4ODk1LCJqdGkiOiJRdTViYnhwdlBkNE9tT3ZZIiwic3ViIjoyLCJwcnYiOiI4N2UwYWYxZWY5ZmQxNTgxMmZkZWM5NzE1M2ExNGUwYjA0NzU0NmFhIn0.AJNTXTlnI74ZyPw2rqvEaI7P5YPaLnZNWcCBBmRX0W0"
}
```
This is the **Access Token** we will use to retrieve data in our application. We'll show you how to use this Access Token in the next few steps.
<a name="acess-token-from-login"></a>
## Get Access Token from Login
To get an **Access Token** from a User Login you can do a POST request to:
```php
/api/login?email=admin@admin.com&password=password
```
And you will get a similar response to the response above:
```json
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC93YXZlLnRlc3RcL2FwaVwvbG9naW4iLCJpYXQiOjE1Mzk4MTE0NjUsImV4cCI6MTUzOTgxNTA2NSwibmJmIjoxNTM5ODExNDY1LCJqdGkiOiJKRWljOGdTWFp4S0VjaWh1Iiwic3ViIjoxLCJwcnYiOiI4N2UwYWYxZWY5ZmQxNTgxMmZkZWM5NzE1M2ExNGUwYjA0NzU0NmFhIn0._1oFRK-zeUKMpvCcg8kmM86avzzmI--yQnI4KRwYk1k",
"token_type": "bearer",
"expires_in": 60
}
```
You'll see that this response includes 2 more fields the **token_type** and the **expires_in**. When your application detects the access token has expired it will need request a new access token with the following API request:
| METHOD | URI | Bearer TOKEN |
|:-|:-|:-|
| POST | `/api/refresh` | Bearer: eyJ0e... |
And you will recieve a new **Access Token** for your application to be used. This expiration and refresh tokens are common for keeping your API secure.
<a name="request-data-from-token"></a>
### Request Data with an Access Token
Now, that you have an Access Token you can request data from the application using that token. Based on the permission of the current user they will be able to **B**rowse, **R**ead, **E**dit, **A**dd, and **D**elete any content in your application.
Take the blog **posts** for instance, a user can retrieve data using the following restful routes:
| TYPE | METHOD | URI | Bearer TOKEN |
|:-|:-|:-|:-|
| JSON | GET (Browse) | `/api/posts` | Bearer: eyJ0e... |
| JSON | GET (Read) | `/api/posts/{id}` | Bearer: eyJ0e... |
| JSON | PUT (Edit) | `/api/posts/{id}` | Bearer: eyJ0e... |
| JSON | POST (Add) | `/api/posts` | Bearer: eyJ0e... |
| JSON | DELETE (Delete) | `/api/posts` | Bearer: eyJ0e... |
In the PUT and POST methods above you can pass JSON data to Edit or Add content.
<a name="testing-api"></a>
### Testing Your API
You can test out your application by using a third-party tool called <a href="https://insomnia.rest/" target="_blank">Insomnia</a>, this is a free app that you can download and you can view all the endpoints on the left and the API data on the right.
![api screenshot 8](https://cdn.devdojo.com/images/april2021/api-8.png)
In order to download the End Points for the Wave application you can find this file located here: [https://github.com/thedevdojo/laravel-wave-api-endpoints](https://github.com/thedevdojo/laravel-wave-api-endpoints), this page also shows instructions on how to import the current endpoints.
After you have imported the API endpoints, you may also wish to change the BASE_URL variable in the application. We use `https://wave.test` for testing, but your local URL may be different. To do this, you'll need to click on **Development->Manage Environments**
![api screenshot 9](https://cdn.devdojo.com/images/april2021/api-9.png)
Then, you'll need to change the `base_url` value to your application URL.
![api screenshot 10](https://cdn.devdojo.com/images/april2021/api-10.png)
And, now you're ready to test out your API.
<a name="registering-via-api"></a>
### Registering via the API
If you are creating an API, you may also wish to allow your users to register. This is simple as well. You can perform a POST request to:
```php
/api/register?name=John Doe&username=jdoe&email=jdoe@gmail.com&password=pass
```
And a new user will be registered and given an Access Token to access data via your API.

View File

@@ -0,0 +1,57 @@
# Authentication
Wave is built on top of the default Laravel Authentication and includes a few additional features such as email verification, forgot password, username login, and of course billing upon registration.
- [Registration](#register)
- [Login](#login)
- [Email Verification](#email-verification)
- [Login Options](#login-options)
- [Forgot Password](#forgot-password)
---
<a name="register"></a>
### Registration
By default users will need to purchase in order to register for an account; however, you can open up free registration by visiting the admin settings `/admin/settings`, clicking on the Billing Tab, toggling off *Require Credit Card Up Front*, and save.
![no-cc](https://cdn.devdojo.com/images/april2021/no-cc.png)
Now your users will be able to register for a free account.
<a name="login"></a>
### Login
After a user has created an account through your application, they can login by visiting the `/login` route. After successfully logging in the user will then be redirected to their dashboard.
> If you have just installed Wave you can login with the default email `admin@admin.com` and password as `password`
<a name="email-verification"></a>
### Email verification
You may choose to require your users to verify their email before signing up for a free trial. To enable this you will need to visit the admin settings page at `/admin/settings`, click on the Auth tab and then toggle *Verify Email during Sign Up*
![verify-email](https://cdn.devdojo.com/images/april2021/verify-email.png)
<a name="login-options"></a>
### Login with email or username
Optionally you may choose to allow users to login with their email address or their username. You can also change this in the **Auth** tab of your admin settings (see screenshot above).
<a name="forgot-password"></a>
### Forgot password
Users can click on the forgot password link on the login page and they will be taken to a form where they can enter their email address.The user will then receive an email with a link to your application where they can reset their password.
> Quick note on Email Verification and Forgot Password, your application must be configured to send email before these features can be used.
The simplest way to test emails in development mode is to use [Mailtrap](https://mailtrap.io/). You can sign up for a free account and then enter your mailtrap credentials in your `.env` file:
```html
MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_ENCRYPTION=null
```

View File

@@ -0,0 +1,60 @@
# Billing
Wave comes packaged with integrated billing. This means that you can charge your customers to access your application or features in your application.
Wave integrates seamlessly with the <a href="https://paddle.com" target="_blank">Paddle</a> Payment Platform.
- [Create a Paddle Account](#paddle-account)
- [Add Paddle API Credentials](#paddle-credentials)
- [Test Billing Process](#test-billing)
<a name="paddle-account"></a>
## Create a Paddle Account
In order to integrate your application with Paddle you will need to signup for an account at <a href="https://paddle.com/signup" target="_blank">paddle.com/signup</a>. It may take a few days to get access to your Paddle account before you're ready to go live. In the meantime, you can signup for a Sandbox account at <a href="https://sandbox-vendors.paddle.com/signup" target="_blank">sandbox-vendors.paddle.com/signup</a>, and start testing out your payment functionality right away.
After you have created your Paddle Account you'll be able to login and see your dashboard, which should look similar to the following:
![paddle-dashboard.png](https://cdn.devdojo.com/images/april2021/paddle-dashboard.png)
Next, let's add your Paddle API credentials.
<a name="paddle-credentials"></a>
### Add Paddle API Credentials
Inside of your Paddle Dashboard you'll see a button under the **Developer Tools** menu, called **Authentication**, click on that button to get your API Authentication Credentials.
![paddle-authentication.png](https://cdn.devdojo.com/images/april2021/paddle-authentication.png)
On this page you'll find your **Vendor ID** and your **API Auth Code**. These are the credentials that you will need to add to your `.env` file for `PADDLE_VENDOR_ID` and `PADDLE_VENDOR_AUTH_CODE`:
```
PADDLE_VENDOR_ID=9999
PADDLE_VENDOR_AUTH_CODE=YOUR_REALLY_LONG_API_KEY_HERE
PADDLE_ENV=sandbox
```
After adding these credentials, your application has been successfully configured with Paddle.
#### Ready to go Live?
When you are ready to go live and take live payments you'll want to change the `PADDLE_ENV` from `sandbox` to `live`, and you'll be ready to accept live payments 💵
<a name="test-billing"></a>
### Test Billing Process
Before you can test out the full billing process, you will need to add a few [Subscription Plans](/docs/features/subscription-plans).
**Notice**: If you are using a Sandbox account, you will need to test your app from a `http://localhost` URL. The best way to do this is to utilize the laravel **Artisan Serve** command, or you can use [Laravel Sail](https://www.youtube.com/watch?v=WGhiY5xamms) docker image to serve up your app from a localhost URL.
After adding subscription plans and configuring your application with your Paddle API keys, you will now be able to test out the billing process using the following credentials:
```
Credit Card: 4242 4242 4242 4242
Expiration: Any Future Date
CVC: Any 3 digit code
```
---
After adding your Paddle API credentials, you'll need to configure your app with a few [Subscription Plans](/docs/features/subscription-plans) in order to test out the whole process. Let's move on to the [next step](/docs/features/subscription-plans) where you will learn how to do this.

View File

@@ -0,0 +1,42 @@
# Blog
In order to grow your SAAS you will need a blog to write about relevant content. This will help your business grow and get free organic traffic.
In this section you will learn about the blogging platform that comes along with Wave.
- [Your Blog](#your-blog)
- [Posts Admin](#posts-admin)
- [Posts Categories](#posts-categories)
---
<a name="your-blog"></a>
### Your Blog
After installing Wave, you will also have a blog located at the `/blog` route. You can modify or edit this theme file located at `resources/views/themes/{theme_folder}/blog/index.blade.php`
![blog 1](https://cdn.devdojo.com/images/april2021/blog-1.png)
You can also view a single post by clicking the thumbnail or title of the post. You can modify or edit the theme post view at `resources/views/themes/{theme_folder}/blog/post.blade.php`
![blog 2](https://cdn.devdojo.com/images/april2021/blog-2.png)
<a name="posts-admin"></a>
### Posts Admin
You can edit, add, or delete posts in your admin by visiting `/admin/posts`. To create a new post you can click the `Add New` button:
![blog 3](https://cdn.devdojo.com/images/april2021/blog-3.png)
Then, you'll need to fill out your new post information and click save. Only Posts with a status of `PUBLISHED` will show up on the front-end.
![blog 4](https://cdn.devdojo.com/images/april2021/blog-4.png)
<a name="posts-categories"></a>
### Post Categories
You can also choose to Add, Edit or Delete post categories by visiting the Admin Post Categories at `/admin/categories`.
![blog 5](https://cdn.devdojo.com/images/april2021/blog-5.png)
After adding a new category, you will be able to create a new post and categorize it in that specific category.

View File

@@ -0,0 +1,103 @@
# Notifications
Wave leverages the default <a href="https://laravel.com/docs/notifications" target="_blank">Laravel Notification</a> system and gives you an elegant UI to display those notifications in your app.
- [When to Use Notifications](#when-to-use)
- [Creating Notifications](#create-notifications)
- [Viewing Notifications](#viewing-notifications)
---
<a name="when-to-use"></a>
### When to use Notifications
When to use notifications in your application will be up to you. Here are a few examples:
1. Notify users in a forum discussion when a new response is added.
2. Notify a user when someone follows them.
3. Notify the user when someone sends them a message.
You get the general idea right? You are the creator and you can decide what kind of notifications your user will receive.
<a name="create-notifications"></a>
### Creating Notifications
We have built the Wave notifications on top of the default Laravel notifications, which are very simple to use and easy to implement.
> If you haven't checked out the Laravel notifications documentation, head on over to the official documentation at <a href="https://laravel.com/docs/notifications" target="_blank">laravel.com/docs/notifications</a>
We can create a new notification by running the following artisan command:
```php
php artisan make:notification TestNotification
```
You will see a new file at: `/app/Notifications/TestNotification`. Scroll down to where you see:
```php
public function via($notifiable)
{
return ['mail'];
}
```
and change this to:
```php
public function via($notifiable)
{
return ['database'];
}
```
Then scroll down to where you see:
```php
public function toArray($notifiable)
{
return [
//
];
}
```
And replace it with:
```php
public function toArray($notifiable)
{
return [
'title' => 'My Title Here',
'icon' => '/storage/users/default.png',
'body' => 'This is the body content of the notification... Yada yada yada',
'link' => 'https://google.com'
];
}
```
Next, let's create a few notifications. We can do this by using the `tinker` command:
```php
php artisan tinker
```
Inside of the tinker command you will want to run the following command a few times:
```php
App\Models\User::find(1)->notify(new App\Notifications\TestNotification);
```
After you have run that command, let's move on to learning how the user can view those notifications:
<a name="viewing-notifications"></a>
### Viewing Notifications
Login to the application with the admin user and visit any page in your application. You'll notice a bell icon on the top right with a number indicating how many unread notifications you have.
![Notification Bell](https://cdn.devdojo.com/images/april2021/notifications-bell.png)
When you hover over the bell icon you will see a nice dropdown displaying the current user notifications.
![Notification Dropdown](https://cdn.devdojo.com/images/april2021/notifications-dropdown.png)
The user can additionally, click on the `View All Notifications` button at the bottom of the dropdown and they will be taken to their notifications page where they can view all their notifications.

View File

@@ -0,0 +1,82 @@
# Subscription Plans
Billing users for a subscription plan is pretty straight forward. Every Plan **hasOne** Role, so when a user subscribes to a plan they will inherit the permissions associated with that user role.
The Plan you create in Wave will be associated with a plan you create on Paddle.
- [Current Plans](#current-plans)
- [Deleting Plans](#delete-plans)
- [Creating Plans](#create-plans)
- [Creating Plans in Paddle](#create-plans-paddle)
---
<a name="current-plans"></a>
### Current Plans
When you install Wave you will see there are 3 default plans:
1. Basic
2. Premium
3. Pro
You can delete these plans and create your own if you would like or you can edit the current plans.
<a name="delete-plans"></a>
### Deleting Plans
In order to show you how to create a new plan, we will delete the existing **Basic** plan. To delete plans you can visit `/admin/plans` and click Delete:
![plans-1.png](https://cdn.devdojo.com/images/april2021/plans-1.png)
Since our plan is associated with a role, we will also delete the associated role at `/admin/roles`
![plans-roles.png](https://cdn.devdojo.com/images/april2021/plans-roles.png)
We will cover more about User Roles in the next section.
<a name="create-plans"></a>
### Creating Plans
Now, lets create a new plan called *basic*. But before I create a new plan I will first create a new role that I want to assign to this plan. My new role will be called *starter* as well, but you can give the role any name you would like. To create a new role click on the `Add New` button.
![plans-roles-add.png](https://cdn.devdojo.com/images/april2021/plans-roles-add.png)
Then we can create our new role called **basic**
![plans-add-new-role.png](https://cdn.devdojo.com/images/april2021/plans-add-new-role.png)
Notice on this page you can specify permissions for this role. We will talk more about this in the next section. For now, you can choose to check a few of them, or leave them all unchecked. Below is a screenshot of what I have checked in this example:
![](/wave/img/docs/1.0/wave-role-permissions.png)
Now that the role is created we can create a new plan and associate it with a role:
![wave-add-plan.png](https://cdn.devdojo.com/images/april2021/wave-add-plan.png)
> Notice the **Plan ID** when creating your plan. This Plan ID is an ID we need to create in Paddle. We'll do this in the next step.
Fill out the rest of the info on the plan and click `Save` to create your new plan.
<a name="create-plans-paddle"></a>
### Creating Plans in Paddle
To create a new plan in Paddle, login to your dashboard and click **Catalog**->**Subscription Plans**. Click on the **+ New Plan** button at the top right to create a new plan.
![paddle-plans-01.png](https://cdn.devdojo.com/images/april2021/paddle-plans-01.png)
You'll see a pop-up that will ask for the plan name, icon, and price. Fill out the info for your plan.
![paddle-plans-02.png](https://cdn.devdojo.com/images/april2021/paddle-plans-02.png)
Scroll down to the bottom and click the **Save Plan** button.
![paddle-plans-03.png](https://cdn.devdojo.com/images/april2021/paddle-plans-03.png)
After creating your new plan, you'll see the **Plan ID** you need to associate with the Wave Plan you create from the previous step.
![paddle-plans-04.png](https://cdn.devdojo.com/images/april2021/paddle-plans-04.png)
After adding all your plans, we're ready to [test out the billing process](/docs/features/billing#test-billing).
---
Next, we'll talk about User Roles. Remember every Plan is associated with a User Role, and this is how we will determine what a user has access to in your application.

View File

@@ -0,0 +1,24 @@
# Themes
Wave has full theme support, which means you can separate your views into separate themes. This will make it easier to create new versions of your site and revert back if needed. This will also help you separate a lot of your back-end logic with the front-end.
In this section you will learn where the themes are located and how to activate a specific theme.
## Theme Location
Every theme is located inside of the `resources/views/themes` folder. When you install Wave there will only be 1 theme available, the `tailwind` theme. If you <a href="https://devdojo.com/wave#pro" target="_blank">Upgrade to a Pro account</a>, you will gain access to the Wave Pro repo, which currently has another theme available, the `tallstack` theme. Each theme is responsible for managing their own assets. In each theme you will find a `package.json` which contains the front-end dependencies to run webpack and build each one.
## Theme Assets
To compile a theme's assets you can navigate into the theme folder and run `npm install`, after you install the node dependencies you can run `npm run watch` to start your asset watcher and develop your theme. When you are ready to compile and minify your assets for production you will want to run `npm run production`.
## Activating Themes
If you are logged in as an admin user and you visit visit the <a href="/admin/themes" target="_blank">`/admin/themes`</a> section of your application youll see the current themes available in your app.
![themes](https://cdn.devdojo.com/images/may2021/themes.png)
To activate a Theme you can simply click the Activate button for the current theme you would like to activate, and that will be the current active theme.
For more information on customizing and modifying themes, you may want to check out the <a href="https://devdojo.com/wave/videos" target="_blank">Wave Videos</a> to learn more about how you can customize and build new themes for your application.

View File

@@ -0,0 +1,20 @@
# User Impersonations
With user impersonations you can easily impersonate any user on your site. This will come in handy when you need to debug an issue that a specific user is experiencing.
Impersonating a user will allow you to login to your application acting as a specific user.
- [Impersonate a User](#impersonate)
<a name="impersonate"></a>
## Impersonate a User
To impersonate a user you can visit your users section in your application at `/admin/users`. Find the user you want to impersonate and click on the Impersonate button.
![impersonate-1.png](https://cdn.devdojo.com/images/april2021/impersonate-1.png)
You will now see that you are logged in as that specific user. You can click the user menu dropdown and you'll see a new **Leave Impersonation** button to exit that user account and log back in as your original admin user.
![impersonate-2.png](https://cdn.devdojo.com/images/april2021/impersonate-2.png)
Impersonations... 🍰 Piece of cake, right?

View File

@@ -0,0 +1,98 @@
# User Profiles
When building your SAAS application you may want your users to provide more information. With profiles and profile fields this couldnt be easier. Lets dig into how this works.
---
- [User Profile Page](#profile-page)
- [User Profile Settings](#profile-settings)
- [Custom Profile Fields](#custom-profile-fields)
- [Profile Field Types](#profile-field-types)
<a name="profile-page"></a>
### User Profile Page
Every user in your application will have a public profile page. The user will be able to visit `/@username` and view their profile. By default the profile page is public, which means anyone can visit that user profile.
![admin-view](https://cdn.devdojo.com/images/april2021/admin-view.png)
In some applications you may not have a need for a profile page. In that case, you can include the following route to your applications `routes/web.php`
```php
Route::redirect('@{username}', '/');
```
This will disable user profiles and redirect any user profile page back to the homepage.
> {warning} When disabling user profiles, the route must be placed after the `Wave::routes();` line.
---
<a name="profile-settings"></a>
### User Profile Settings
When a user registers for an account they will be able to edit their profile information by clicking on the settings in their user drop down.
On the user profile page the user can update their avatar, name, and email address. You will also see one more field, called `about`, this is an example of a custom profile field. Let's learn more about custom profile fields below.
![wave-profile.png](https://cdn.devdojo.com/images/april2021/wave-profile-2.png)
---
<a name="custom-profile-fields"></a>
### Custom Profile Fields
Custom profile fields allow you to add new fields in your user settings page. In the current theme you'll see a custom field called **about**. The **about** text_area can be generated with the following code:
```php
echo profile_field('text_area', 'about')
```
> {primary} This line of code can be found in each theme, which is located at: `resources/views/themes/{theme_name}/settings/partials/profile.blade.php`.
The `profile_field($type, $key)` function takes 2 arguments. The **type** of field, and the **key**.
We can then use the **key** to reference the value of the users custom profile value. For instance to display the user's **about** value we can do the following:
```php
auth()->user()->profile('about');
```
---
The *about* field uses a *text_area* type to display a text area. In the next part we will list the different types of profile fields you can display.
<a name="profile-field-types"></a>
### Profile Field Types
- **checkbox** - display a form check box
- **code_editor** - display a code editor (may require additional js libraries)
- **color** - display a color picker
- **date** - display a date picker (may require additional js libs)
- **file** - display a file input
- **hidden** - display a hidden input
- **image** - display an image input
- **markdown_editor** - display a markdown editor (more js required)
- **multiple_images** - display multiple image input
- **number** - display a number input
- **password** - display a password input
- **radio_btn** - display a radio button input
- **rich_text_box** - display a rich text editor (requires tinymce js)
- **select_dropdown** - display a select dropdown input
- **text** - display a textbox input
- **text_area** - display a text area input
You can use any of the profile field types above in the **first argument** of the ```profile_field($type, $key)``` function, and use any **key** (string) as the **second argument**.
Then, you can reference the value by calling:
```php
$user = User::find(1);
$user->profile($key);
```
Or you can retrieve the profile value from the authenticated user like so:
```php
auth()->user()->profile($key);
```

View File

@@ -0,0 +1,91 @@
# User Roles
Each user in your app will have a primary role and every role has permissions to allow or deny access to content. In this section we will talk about User Roles and how to utilize roles in your application.
This functionality is also documented in Voyager; although, its important to re-cap the functionality since it ties directly with a Subscription Plan.
> If you are unfamiliar with Voyager, I would recommend checking out the documentation at https://voyager-docs.devdojo.com/
- [🍞 The BREAD System](#bread)
- [Adding Roles & Permissions](#roles-permissions)
- [Checking Permissions](#checking-permissions)
---
<a name="bread"></a>
### 🍞 The BREAD System
Wave uses the BREAD (browse, read, edit, add, and delete) system as opposed to the CRUD (create, read, update, and delete) system.
By using the BREAD system we can specify what type of permissions the User Role has in relation to any content on your site. The user role can have permissions to either Browse, Read, Edit, Add, or Delete any data on your website.
> Here's a quick example: If we were to create a new role called **editor** and then assign the **editor** permissions to **Browse**, **Read**, and **Add** Posts, they will only have permission to those particular actions. Meaning that user can only Browse posts, Read posts, and Add posts. The user will not have permissions to **Edit** or **Delete** posts. Pretty straight forward, right?
Since each Subscription Plan is associated with a Role. We can say that each plan has a specific set of permissions to Browse, Read, Edit, Add, or Delete content within your application.
<a name="roles-permissions"></a>
### Adding Roles & Permissions
In your application you can view or add Roles in your application by visiting `/admin/roles`. To add a new role you can click on the `Add New` button:
![add-role](https://cdn.devdojo.com/images/april2021/add-role.png)
You can give the role a name and then specify the BREAD permissions for all the content on your site.
![add-role-bread](https://cdn.devdojo.com/images/april2021/add-role-bread.png)
<a name="checking-permissions"></a>
### Checking Permissions
Next if you would like to check for permissions you can use a few helpers. Here is how you can check user permissions from a user object.
```php
// via user object
$canViewPost = $user->can('read', $post);
$canViewPost = Auth::user()->can('read', $post);
// via controller
$canViewPost = $this->authorize('read', $post);
```
You may also choose to use the Voyager facade and pass the permission as a string:
```php
$canBrowsePost = Voyager::can('browse_posts');
$canViewPost = Voyager::can('read_posts');
$canEditPost = Voyager::can('edit_posts');
$canAddPost = Voyager::can('add_posts');
$canDeletePost = Voyager::can('delete_posts');
```
Lastly, you can use the blade syntax inside of your views to check whether a user can edit a particular post, like so:
```
@can('edit', $post)
I can edit this post!
@endcan
```
---
You may also pass the Model to check for permissions:
```
@can('browse', new TCG\Voyager\Models\Post)
I can browse posts!
@endcan
```
Be sure to note that the permission will be tied to the Model specified in the Voyager Bread section.
![edit-post-bread](https://cdn.devdojo.com/images/april2021/edit-post-bread.png)
You can then choose to change the location of your model. For instance, you may want to create a new model inside of your app folder, and swap out the namespace with `App\Post`.
---
Ok, next let's move on to talking about notifications.

147
wave/docs/index.blade.php Normal file
View File

@@ -0,0 +1,147 @@
@php
include base_path().'/wave/docs/load.php';
@endphp
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta charset="UTF-8">
<title>{{ $title }}</title>
<link rel="stylesheet" href="/wave/docs/assets/css/app.css">
<style>.algolia-autocomplete{width:100%}</style>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.6.0/styles/night-owl.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.6.0/highlight.min.js"></script>
<!-- at the end of the HEAD -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.css" />
</head>
<body>
<div class="absolute inset-0 z-10 flex items-center justify-center w-full h-full bg-white"><svg class="w-5 h-5 text-gray-900 animate-spin" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
</div>
<!-- Full page fadeout -->
<div class="fixed inset-0 z-50 w-screen h-screen transition duration-200 ease-in bg-white" x-data="{ backToSite: true }" x-init="() => { $el.classList.add('opacity-0'); setTimeout(function(){ $el.remove() }, 200); }"></div>
<!-- Mobile Header -->
<div class="relative z-10 flex items-center justify-center block h-20 px-10 mb-10 border-b border-gray-100 cursor-pointer md:px-24 lg:hidden">
<svg onclick="openSidebar()" class="absolute left-0 w-6 h-6 ml-10 text-gray-500 cursor-pointer md:ml-20" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h8m-8 6h16"></path></svg>
<svg class="w-9 h-9" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 208 206"><defs></defs><defs><linearGradient id="a" x1="100%" x2="0%" y1="45.596%" y2="45.596%"><stop offset="0%" stop-color="#5D63FB"></stop><stop offset="100%" stop-color="#0769FF"></stop></linearGradient><linearGradient id="b" x1="50%" x2="50%" y1="0%" y2="100%"><stop offset="0%" stop-color="#39BEFF"></stop><stop offset="100%" stop-color="#0769FF"></stop></linearGradient><linearGradient id="c" x1="0%" x2="99.521%" y1="50%" y2="50%"><stop offset="0%" stop-color="#38BCFF"></stop><stop offset="99.931%" stop-color="#91D8FF"></stop></linearGradient></defs><g fill="none" fill-rule="evenodd"><path fill="url(#a)" d="M185.302 38c14.734 18.317 22.742 41.087 22.698 64.545C208 159.68 161.43 206 103.986 206c-39.959-.01-76.38-22.79-93.702-58.605C-7.04 111.58-2.203 69.061 22.727 38a104.657 104.657 0 00-9.283 43.352c0 54.239 40.55 98.206 90.57 98.206 50.021 0 90.571-43.973 90.571-98.206A104.657 104.657 0 00185.302 38z"></path><path fill="url(#b)" d="M105.11 0A84.144 84.144 0 01152 14.21C119.312-.651 80.806 8.94 58.7 37.45c-22.105 28.51-22.105 68.58 0 97.09 22.106 28.51 60.612 38.101 93.3 23.239-30.384 20.26-70.158 18.753-98.954-3.75-28.797-22.504-40.24-61.021-28.47-95.829C36.346 23.392 68.723.002 105.127.006L105.11 0z"></path><path fill="url(#c)" d="M118.98 13c36.39-.004 66.531 28.98 68.875 66.234 2.343 37.253-23.915 69.971-60.006 74.766 29.604-8.654 48.403-38.434 43.99-69.685-4.413-31.25-30.678-54.333-61.459-54.014-30.78.32-56.584 23.944-60.38 55.28v-1.777C49.99 44.714 80.872 13.016 118.98 13z"></path></g></svg>
</div>
<!-- End Mobile Header -->
<div class="relative z-20 flex h-screen antialiased bg-white docs">
<div id="sidebarOverlay" class="fixed inset-0 hidden w-full h-full bg-black opacity-30">
<div class="fixed top-0 right-0 flex items-center justify-center w-12 h-12 mt-4 mr-5 bg-white rounded-full cursor-pointer">
<svg class="w-6 h-6 text-black fill-current" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg>
</div>
</div>
{{-- sidebar --}}
<div id="sidebar" class="fixed top-0 left-0 z-40 flex flex-col w-64 h-screen py-4 pr-3 overflow-scroll transition duration-200 ease-out transform -translate-x-full bg-white border-r border-gray-200 select-none lg:translate-x-0 categories">
<h1 class="px-5 text-sm font-bold text-black">Wave<span class="ml-1 text-xs font-medium text-blue-500 uppercase">docs</span></h1>
<div id="bg-fade" class="fixed inset-0 z-40 invisible w-screen h-full transition duration-150 ease-out bg-gray-900 opacity-0"></div>
<div class="relative z-50 flex items-center w-full pl-4 mt-5 mb-5 text-gray-400">
<svg class="absolute z-20 w-4 h-4 ml-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path></svg>
<input type="text" onfocus="window.searchFocused(true)" onblur="window.searchFocused(false)" class="block search w-full z-10 py-1.5 pt-2 w-full pl-8 pr-4 leading-normal rounded-md text-xs focus:border-transparent focus:outline-none focus:ring-4 border border-gray-100 focus:ring-blue-500 focus:ring-opacity-40 bg-gray-50 text-gray-400" placeholder="Search the docs">
</div>
@foreach($menu_items as $item)
{{-- if the current page is in this menu we want to have this drawer open --}}
@php $isOpen = false; @endphp
@foreach($item->sections as $index => $section)
@if(Request::getRequestUri() && Request::getRequestUri() == $section->url)
@php $isOpen = true; @endphp
@endif
@endforeach
<div x-data="{ open: '{{ $isOpen }}' }" class="relative text-xs font-semibold">
<div @click="open=!open" class="flex justify-between py-2 pl-5 pr-3 transition duration-150 ease-in-out rounded-r-lg cursor-pointer hover:bg-gray-50 group hover:text-gray-800">
<div class="text-gray-700 uppercase">{{ $item->title }}</div>
<svg class="w-4 h-4 text-gray-400 transform group-hover:text-gray-800" :class="{ '-rotate-180' : open }" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path></svg>
</div>
<div x-show="open" class="mt-2 space-y-0.5" x-cloak>
@foreach($item->sections as $index => $section)
<a href="{{ $section->url }}" @if(isset($section->attributes)){!! $section->attributes !!}@endif class="block cursor-pointer rounded-r-lg pl-6 py-2 @if(Request::getRequestUri() && Request::getRequestUri() == $section->url){{ 'bg-blue-50 text-blue-500' }}@else{{ 'text-gray-400 hover:text-gray-800' }}@endif">{{ $section->title }}</a>
@if(intval($index+1) >= count((array)$item->sections))
<div class="w-full h-5"></div>
@endif
@endforeach
</div>
</div>
@endforeach
<div class="relative flex flex-col items-start justify-between mt-auto">
<a href="https://devdojo.com/course/wave" target="_blank" class="flex items-center justify-between w-full py-2 pl-5 pr-3 transition duration-150 ease-in-out rounded-r-lg cursor-pointer hover:bg-wave-100 bg-wave-50 group hover:text-gray-800">
<span class="flex items-center">🍿
<span class="ml-2 text-sm font-medium text-wave-500">Video Tutorials</span>
</span>
<svg class="w-4 h-4 ml-1 align-end text-wave-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M11 3a1 1 0 100 2h2.586l-6.293 6.293a1 1 0 101.414 1.414L15 6.414V9a1 1 0 102 0V4a1 1 0 00-1-1h-5z"></path><path d="M5 5a2 2 0 00-2 2v8a2 2 0 002 2h8a2 2 0 002-2v-3a1 1 0 10-2 0v3H5V7h3a1 1 0 000-2H5z"></path></svg>
</a>
<a id="backToSiteBtn" href="{{ url('/') }}" class="flex items-center pl-5 mt-4 text-xs font-bold text-blue-500 no-underline hover:text-black">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"></path></svg>
Back to My Site
</a>
</div>
</div>
{{-- end sidebar --}}
<div class="w-full px-10 md:px-20 lg:ml-64 xl:px-0">
@if($home)
<div class="w-full max-w-4xl mx-auto">
<div class="hidden max-w-lg lg:mt-8 lg:-mb-8 lg:block">
<img src="../../wave/img/docs/2.0/wave-docs.png" class="w-full mb-0 ml-0">
</div>
</div>
@endif
<div class="max-w-4xl py-0 pb-20 mx-auto prose prose-xl lg:pt-10 lg:prose-xl lg:px-0">
{!! Illuminate\Support\Str::markdown($file) !!}
</div>
</div>
</div>
<script src="/wave/docs/assets/js/app.js"></script>
<!-- at the end of the BODY -->
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.js"></script>
<script type="text/javascript"> docsearch({
apiKey: '57b9a8aca979f9716f86aa3d2b75a415',
indexName: 'devdojo',
inputSelector: '.search',
debug: false // Set debug to true if you want to inspect the dropdown
});
</script>
<script>
hljs.initHighlightingOnLoad();
function openSidebar(){
document.getElementById('sidebar').classList.remove('-translate-x-full')
document.getElementById('sidebarOverlay').classList.remove('hidden');
}
function closeSidebar(){
document.getElementById('sidebar').classList.add('-translate-x-full')
document.getElementById('sidebarOverlay').classList.add('hidden');
}
window.addEventListener('DOMContentLoaded', (event) => {
document.getElementById('sidebarOverlay').addEventListener('click', function(){
closeSidebar();
});
});
</script>
</body>
</html>

168
wave/docs/installation.md Normal file
View File

@@ -0,0 +1,168 @@
# Installation
- [Install Wave](#install-wave)
- [Create a New Repo](#create-repo)
- [Deploy to DigitalOcean](#deploy-to-digitalocean)
- [Logging into Your Application](#login)
---
<a name="install-wave"></a>
## Install Wave
Before installing wave you will need to make sure you have the minimum <a href="https://laravel.com/docs/deployment#server-requirements" target="_blank">server requirements</a> and then you'll want to clone the repo to your machine.
### Clone the Repo
You can clone the repo onto your local machine with the following command:
```
git clone https://github.com/thedevdojo/wave.git project_name
```
Change `project_name` with the name of your project. Optionally, you may want to create a [new Github Repo for your project](#create-repo).
---
Ok, now we can easily install Wave with these **4 simple steps**:
### 1. Create a New Database
During the installation we need to use a MySQL database. You will need to create a new database and save the credentials for the next step.
### 2. Copy the `.env.example` file
We need to specify our Environment variables for our application. You will see a file named `.env.example`, you will need to duplicate that file and rename it to `.env`.
Then, open up the `.env` file and update your *DB_DATABASE*, *DB_USERNAME*, and *DB_PASSWORD* in the appropriate fields. You will also want to update the *APP_URL* to the URL of your application.
```bash
APP_URL=http://wave.test
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=wave
DB_USERNAME=root
DB_PASSWORD=
```
### 3. Add Composer Dependencies
Next, we will need to install all our composer dependencies by running the following command:
```php
composer install
```
### 4. Run Migrations and Seeds
We need to migrate our database structure into our database, which we can do by running:
```php
php artisan migrate
```
<br>
Finally, we will need to seed our database with the following command:
```php
php artisan db:seed
```
<br>
🎉 And that's it! You will now be able to visit your URL and see your Wave application up and running.
> For security measures you may want to regenerate your application key, be sure to run the following command below to secure your site before going live.
```php
php artisan key:generate
```
---
<a name="create-repo"></a>
## Create a New Repo
In most cases it's a good idea to create a separate repo for your new project. This will also make it easier to [deploy our application to DigitalOcean](#deploy-to-do).
If you are logged into your Github account, you can go to <a href="https://github.com/new" target="_blank">https://github.com/new</a> to create a new repository. Give it a name associated with your SAAS and click **Create Repository**
![create-repo.png](https://cdn.devdojo.com/images/march2021/create-repo.png)
After you click on create repo, you will need to open up the command line and `cd` into your `project_name` folder and run the following commands, replacing `tnylea/project_name` with the name of your repo:
```
rm -rf .git/
git init
git add --all
git commit -m "first commit for my SAAS"
git branch -M main
git remote add origin https://github.com/tnylea/project_name.git
git push -u origin main
```
If you refresh your Github Repository you should see that it now contains the files for your new SAAS application.
![repo-new.png](https://cdn.devdojo.com/images/march2021/repo-new.png)
---
<a name="deploy-to-digitalocean"></a>
## Deploy to Digital Ocean
![](https://cdn.devdojo.com/images/march2021/wave-on-do.png)
If you use Digital Ocean, you're in luck. You can easily start surfing the Wave(s) on DigitalOcean with our <a href="https://www.digitalocean.com/products/app-platform/" target="_blank">DO App Platform</a> integration. Not using DigitalOcean? <a href="https://m.do.co/c/dc19b9819d06" target="_blank">Get $100 in free DigitalOcean credit here</a>. 💵
Here are 3 simple steps to get started with your new SAAS on Digital Ocean.
1. [🔑 Get Your DO API Key](#api-key)
2. [🚀 Deploy Your App](#deploy-app)
3. [🤓 Start Building Your SAAS](#start-building)
---
<a name="api-key"></a>
### 1. 🔑 Get Your DO API Key
In order to deploy to DigitalOcean you'll need to get your API Key from the following URL: [https://cloud.digitalocean.com/account/api/tokens](https://cloud.digitalocean.com/account/api/tokens)
![do-api-key-page.png](https://cdn.devdojo.com/images/april2021/do-api-key-page.png)
Click on the **Generate New Token**, button and save your new token for the next step.
<a name="deploy-app"></a>
### 2. 🚀 Deploy Your App
Ok, now you're ready to deploy your application to DigitalOcean. Login to your application admin and click on the **Deploy Now** button in the first card:
![admin-screen-1.png](https://cdn.devdojo.com/images/april2021/admin-screen-1.png)
Next, you'll see another page where you need to enter in your **repo**, **give DO access to your Repo**, and then enter in your **api key**.
![admin-screen-2.png](https://cdn.devdojo.com/images/april2021/admin-screen-2.png)
After you enter those fields and press deploy, you will see a success message. Now you can navigate to your digital ocean app platform dashboard and you'll see your new application.
<a name="start-building"></a>
### 3. 🤓 Start Building Your SAAS
That's it! You are now ready to start building your SAAS and deploy it to DigitalOcean.
---
If you want to learn more about setting up Wave and support the ongoing development of Wave you may want to consider becoming a <a href="https://devdojo.com/pro">DevDojo Pro</a> user. Together we can make this project even more awesome 😎
<a name="login"></a>
## Logging into your Application
After installing Wave you can login with the following default credentials:
- **email**: admin@admin.com
- **password**: password
After logging in you can feel free to change the admin email, username, and password by visiting the settings section in the user menu.

188
wave/docs/load.php Normal file
View File

@@ -0,0 +1,188 @@
<?php
$pages = [
'welcome' => 'welcome.md',
'installation' => 'installation.md',
'configurations' => 'configurations.md',
'upgrading' => 'upgrading.md',
'features/authentication' => 'features/authentication.md',
'features/user-profiles' => 'features/user-profiles.md',
'features/user-impersonation' => 'features/user-impersonation.md',
'features/billing' => 'features/billing.md',
'features/subscription-plans' => 'features/subscription-plans.md',
'features/user-roles' => 'features/user-roles.md',
'features/notifications' => 'features/notifications.md',
'features/announcements' => 'features/announcements.md',
'features/blog' => 'features/blog.md',
'features/api' => 'features/api.md',
'features/admin' => 'features/admin.md',
'features/themes' => 'features/themes.md',
'concepts/routing' => 'concepts/routing.md',
'concepts/themes' => 'concepts/themes.md',
'concepts/structure' => 'concepts/structure.md',
];
$menu_items = [
(object)[
'title' => 'Getting Started',
'sections' => (object)[
(object)[
'title' => 'Welcome',
'url' => '/docs'
],
(object)[
'title' => 'Installation',
'url' => '/docs/installation'
],
(object)[
'title' => 'Configurations',
'url' => '/docs/configurations'
],
(object)[
'title' => 'Upgrading',
'url' => '/docs/upgrading'
]
]
],
(object)[
'title' => 'Features',
'sections' => (object)[
(object)[
'title' => 'Authentication',
'url' => '/docs/features/authentication'
],
(object)[
'title' => 'User Profiles',
'url' => '/docs/features/user-profiles'
],
(object)[
'title' => 'User Impersonation',
'url' => '/docs/features/user-impersonation'
],
(object)[
'title' => 'Billing',
'url' => '/docs/features/billing'
],
(object)[
'title' => 'Subscription Plans',
'url' => '/docs/features/subscription-plans'
],
(object)[
'title' => 'User Roles',
'url' => '/docs/features/user-roles'
],
(object)[
'title' => 'Notifications',
'url' => '/docs/features/notifications'
],
(object)[
'title' => 'Announcements',
'url' => '/docs/features/announcements'
],
(object)[
'title' => 'Blog',
'url' => '/docs/features/blog'
],
(object)[
'title' => 'API',
'url' => '/docs/features/api'
],
(object)[
'title' => 'Admin',
'url' => '/docs/features/admin'
],
(object)[
'title' => 'Themes',
'url' => '/docs/features/themes'
]
]
],
(object)[
'title' => 'Basic Concepts',
'sections' => (object)[
(object)[
'title' => 'Routing',
'url' => '/docs/concepts/routing'
],
(object)[
'title' => 'Themes',
'url' => '/docs/concepts/themes'
],
(object)[
'title' => 'Structure',
'url' => '/docs/concepts/structure'
]
]
],
(object)[
'title' => 'Resources',
'sections' => (object)[
(object)[
'title' => 'Videos',
'url' => 'https://devdojo.com/course/wave',
'attributes' => 'target="_blank"'
],
(object)[
'title' => 'Support',
'url' => 'https://devdojo.com/wave#pro',
'attributes' => 'target="_blank"'
],
(object)[
'title' => 'Laravel',
'url' => 'https://laravel.com',
'attributes' => 'target="_blank"'
],
(object)[
'title' => 'Voyager',
'url' => 'https://voyager.devdojo.com',
'attributes' => 'target="_blank"'
],
(object)[
'title' => 'DigitalOcean',
'url' => 'https://digitalocean.com',
'attributes' => 'target="_blank"'
]
]
],
];
$uri = trim(str_replace('/docs', '', Request::getRequestUri()), '/');
// Get the requested page and check if we are at home.
$home = false;
if($uri == "")
{
$page = 'welcome.md';
$home = true;
}
else
{
if( !isset( $pages[$uri] ) ){
abort(404);
}
$page = $pages[$uri];
}
$title = 'Welcome to Wave';
foreach($menu_items as $item){
foreach($item->sections as $index => $section){
if(Request::getRequestUri() && Request::getRequestUri() == $section->url){
$title = $section->title . ' - Wave SAAS Starter Kit';
}
}
}
$file = file_get_contents( base_path() . '/wave/docs/' . $page );
?>

8
wave/docs/overview.md Normal file
View File

@@ -0,0 +1,8 @@
# Overview
---
[Visit the Welcome section to get started](/docs/welcome)
Thanks for visiting the Wave docs.

33
wave/docs/package.json Normal file
View File

@@ -0,0 +1,33 @@
{
"private": true,
"scripts": {
"dev": "mix",
"watch": "mix watch",
"watch-poll": "mix watch -- --watch-options-poll=1000",
"hot": "mix watch --hot",
"production": "mix --production"
},
"devDependencies": {
"@tailwindcss/forms": "^0.4.0",
"axios": "^0.21",
"cross-env": "^5.1",
"laravel-mix": "^6.0.39",
"less": "^3.12.2",
"less-loader": "^6.2.0",
"lodash": "^4.17.19",
"resolve-url-loader": "^4.0.0",
"sass": "^1.26.10",
"sass-loader": "^12.3.0",
"tailwindcss": "^3.0.0",
"vue-template-compiler": "^2.6.11"
},
"dependencies": {
"@tailwindcss/typography": "^0.5.0",
"alpinejs": "^2.6.0",
"autoprefixer": "^10.2.4",
"glob-all": "^3.1.0",
"laravel-mix-purgecss": "^6.0.0",
"laravel-mix-tailwind": "^0.1.2",
"postcss": "^8.4.4"
}
}

View File

@@ -0,0 +1,3 @@
# Support
Wave is meant to serve as a starter kit, that will save you hundreds of hours, which is used to quickly create your SAAS app. When your application continues to grow you may wish to extend you application beyond Wave's features. In the events that your features conflict with the core features, support may be limited.

View File

@@ -0,0 +1,36 @@
module.exports = {
purge: [
'./**/*.php',
'./*.php',
'./assets/**/*.scss',
'./assets/**/*.js',
],
darkMode: false, // or 'media' or 'class'
theme: {
extend: {
colors: {
'wave': {
50: '#F2F8FF',
100: '#E6F0FF',
200: '#BFDAFF',
300: '#99C3FF',
400: '#4D96FF',
500: '#0069FF',
600: '#005FE6',
700: '#003F99',
800: '#002F73',
900: '#00204D',
},
}
},
},
variants: {
extend: {},
},
plugins: [
require('@tailwindcss/forms'),
require('@tailwindcss/typography')
]
}

34
wave/docs/upgrading.md Normal file
View File

@@ -0,0 +1,34 @@
# Upgrading
Upgrading Wave is very simple. Follow the steps below to upgrade.
- [Upgrade Steps](#steps)
- [Theme Upgrade](#theme-upgrade)
---
<a name="steps"></a>
### Upgrade Steps
Download a copy of the latest version. In the root folder you should see another folder named `wave`, you can simply replace this folder with the `wave` folder in your project.
You will then need to re-autoload your dependencies by running:
```php
composer dump-autoload
```
You may also need to clear the cache by running:
```php
php artisan cache:clear
```
And you should be updated to the latest version :)
<a name="theme-upgrade"></a>
### Theme Upgrade
Upgrading the core of Wave is very simple; however, upgrading your current theme may be a bit more complicated based on the modifications you have made.
Typically you will not need to upgrade your theme, it will have all base features and you can build on top of those. If there is a new feature that gets released which has corresponding views, then you may have a few files that you need to manually move into your project.

22
wave/docs/webpack.mix.js Normal file
View File

@@ -0,0 +1,22 @@
let mix = require('laravel-mix');
const glob = require('glob-all');
require('laravel-mix-tailwind');
require('laravel-mix-purgecss');
/*
|--------------------------------------------------------------------------
| Mix Asset Management
|--------------------------------------------------------------------------
|
| Mix provides a clean, fluent API for defining some Webpack build steps
| for your Laravel application. By default, we are compiling the Sass
| file for the application as well as bundling up all the JS files.
|
*/
mix.setPublicPath('./assets/')
.sass('assets/app.scss', 'css')
.js('assets/app.js', 'js')
.tailwind('./tailwind.config.js');

80
wave/docs/welcome.md Normal file
View File

@@ -0,0 +1,80 @@
Wave is a SAAS framework built using [Laravel](https://laravel.com) and [Voyager](https://voyager.devdojo.com)
<br>
- [Welcome](#welcome)
- [Support](#support)
- [Features](#features)
- [Demo](#demo)
- [Installation](#installation)
<br>
<a name="welcome"></a>
## 👋 Welcome
Welcome to the Wave documentation. These docs will help you navigate the open seas of SAAS creation. They will help you learn how to install, configure, and use Wave. This will be your guide on your journey to creating your own money-making Software as a Service.
---
<a name="support"></a>
## 🚀 Support and Pro Access
Wave is an Open Source project, which means that you can use it for free; however, we still need a way to keep this project going strong. Here's how you can help make this happen.
<a href="https://devdojo.com/pro" target="_blank">Signup for a DevDojo Pro account</a>, to get the following:
- Gain access to the <a href="https://devdojo.com/wave#pro" target="_blank">Wave Private Repo</a> to discuss issues and improvements.
- Gain access to <a href="https://devdojo.com/wave/pro" target="_blank">Tails</a> and build an awesome landing page for your SAAS
- Do your part in making this project even more awesome ✌️
- And <a href="https://devdojo.com/pro" target="_blank">many more perks</a>!
Let's set sail and build this together ⛵
---
<a name="features"></a>
## ⚒️ Features
Wave has some bad-ass features that I think you'll really dig. Here is a list of those features as well as a quick link to each section.
- [**Authentication**](/docs/features/authentication) - Fully loaded authentication, email verification, and password reset.
- [**User Profiles**](/docs/features/user-profiles) - Easily Customizable User Profiles.
- [**User Impersonation**](/docs/features/user-impersonation) - Login as another user to resolve an issue/bug.
- [**Billing**](/docs/features/billing) - Allow users to pay for your service.
- [**Subscription Plans**](/docs/features/subscription-plans) - Subscription plans with different features.
- [**User Roles**](/docs/features/user-roles) - Assign a role and permissions to a specific plan.
- [**Notifications**](/docs/features/notifications) - Ready-to-use Notification System.
- [**Announcements**](/docs/features/announcements) - Notify users about new features or updates.
- [**Blog**](/docs/features/blog) - Equipped with a fully-functional blog.
- [**API**](/docs/features/api) - Ready-to-consume API for your application
- [**Admin**](/docs/features/admin) - Voyager Admin feature set.
- [**Themes**](/docs/features/themes) - Fully configurable themes.
---
<a name="demo"></a>
## 🏄‍♂️ Demo
Would you like to see a demo of Wave? <a href="https://wave.devdojo.com" target="_blank">Click here</a> to check out the official <a href="https://wave.devdojo.com" target="_blank">Wave Demo</a>.
If you would like to get additional help and show your support for the ongoing development of this project, be sure to signup for a <a href="https://devdojo.com/pro" target="_blank">DevDojo Pro Account</a>
---
<a name="installation"></a>
## ⚙️ Installation
Ready to get started? Let's move on to the next section where you will learn how to [install Wave](/docs/installation).