mirror of
https://github.com/prurigro/hypothetical.git
synced 2024-12-22 01:40:22 -05:00
Update + add in dashboard functionality, and document how to setup the dashboard in the readme
This commit is contained in:
parent
9bff17c34f
commit
79824835de
64 changed files with 3705 additions and 427 deletions
|
@ -4,7 +4,7 @@ SITE_DESC="A website template"
|
|||
APP_ENV=local
|
||||
APP_DEBUG=true
|
||||
APP_KEY=random_string
|
||||
APP_URL=http://template.hypothetic.al
|
||||
APP_URL=http://localhost
|
||||
|
||||
DB_HOST=localhost
|
||||
DB_DATABASE=hypothetical
|
||||
|
@ -17,6 +17,9 @@ CACHE_DRIVER=file
|
|||
SESSION_DRIVER=file
|
||||
QUEUE_DRIVER=sync
|
||||
|
||||
MAILCHIMP_APIKEY=
|
||||
MAILCHIMP_LISTID=
|
||||
|
||||
MAIL_SENDTO=null
|
||||
|
||||
MAIL_DRIVER=smtp
|
||||
|
@ -26,3 +29,5 @@ MAIL_ADDRESS=null
|
|||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=tls
|
||||
|
||||
REGISTRATION=true
|
||||
|
|
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -4,4 +4,9 @@
|
|||
/public/build
|
||||
/public/css
|
||||
/public/js
|
||||
/public/fonts/FontAwesome.otf
|
||||
/public/fonts/fontawesome-webfont.*
|
||||
/public/fonts/glyphicons-halflings-regular.*
|
||||
/public/uploads
|
||||
/storage/exports
|
||||
.env
|
||||
|
|
|
@ -40,6 +40,20 @@ class AuthController extends Controller
|
|||
$this->middleware('guest', ['except' => 'logout']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the application registration form.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function showRegistrationForm()
|
||||
{
|
||||
if (env('REGISTRATION', false)) {
|
||||
return view('auth.register');
|
||||
} else {
|
||||
header('Location: /login');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a validator for an incoming registration request.
|
||||
*
|
||||
|
@ -49,8 +63,8 @@ class AuthController extends Controller
|
|||
protected function validator(array $data)
|
||||
{
|
||||
return Validator::make($data, [
|
||||
'name' => 'required|max:255',
|
||||
'email' => 'required|email|max:255|unique:users',
|
||||
'name' => 'required|max:255',
|
||||
'email' => 'required|email|max:255|unique:users',
|
||||
'password' => 'required|confirmed|min:6',
|
||||
]);
|
||||
}
|
||||
|
@ -63,10 +77,12 @@ class AuthController extends Controller
|
|||
*/
|
||||
protected function create(array $data)
|
||||
{
|
||||
return User::create([
|
||||
'name' => $data['name'],
|
||||
'email' => $data['email'],
|
||||
'password' => bcrypt($data['password']),
|
||||
]);
|
||||
if (env('REGISTRATION', false)) {
|
||||
return User::create([
|
||||
'name' => $data['name'],
|
||||
'email' => $data['email'],
|
||||
'password' => bcrypt($data['password']),
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,12 +14,11 @@ class ContactController extends Controller
|
|||
'message' => 'required'
|
||||
]);
|
||||
|
||||
$contact = new Contact;
|
||||
|
||||
$name = $request['name'];
|
||||
$email = $request['email'];
|
||||
$message = $request['message'];
|
||||
|
||||
$contact = new Contact;
|
||||
$contact->name = $name;
|
||||
$contact->email = $email;
|
||||
$contact->message = $message;
|
||||
|
|
216
app/Http/Controllers/DashboardController.php
Normal file
216
app/Http/Controllers/DashboardController.php
Normal file
|
@ -0,0 +1,216 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests;
|
||||
use Illuminate\Http\Request;
|
||||
use Image;
|
||||
use Excel;
|
||||
|
||||
use App\Models\Contact;
|
||||
use App\Models\Subscriptions;
|
||||
|
||||
class DashboardController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the application dashboard.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('dashboard.home', [
|
||||
'heading' => 'Dashboard Home'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dashboard View
|
||||
*/
|
||||
public function getContact()
|
||||
{
|
||||
return view('dashboard.view', [
|
||||
'heading' => 'Contact Form Submissions',
|
||||
'model' => 'contact',
|
||||
'rows' => Contact::getContactSubmissions(),
|
||||
'cols' => [
|
||||
[ 'Date', 'created_at' ],
|
||||
[ 'Name', 'name' ],
|
||||
[ 'Email', 'email' ],
|
||||
[ 'Message', 'message' ]
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
public function getSubscriptions()
|
||||
{
|
||||
return view('dashboard.view', [
|
||||
'heading' => 'Subscriptions',
|
||||
'model' => 'subscriptions',
|
||||
'rows' => Subscriptions::getSubscriptions(),
|
||||
'cols' => [
|
||||
[ 'Date', 'created_at' ],
|
||||
[ 'Email', 'email' ],
|
||||
[ 'Name', 'name' ],
|
||||
[ 'Postal / Zip', 'location' ]
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dashboard Edit
|
||||
*/
|
||||
|
||||
/**
|
||||
* Dashboard Export: Export data as a spreadsheet
|
||||
*/
|
||||
public function getExport($model)
|
||||
{
|
||||
// set the name of the spreadsheet
|
||||
$sheet_name = ucfirst($model);
|
||||
|
||||
// set the model using the 'model' request argument
|
||||
switch ($model) {
|
||||
case 'contact':
|
||||
$headings = [ 'Date', 'Name', 'Email', 'Message' ];
|
||||
$items = Contact::select('created_at', 'name', 'email', 'message')->get();
|
||||
break;
|
||||
case 'subscriptions':
|
||||
$headings = [ 'Date', 'Email', 'Name', 'Postal / Zip' ];
|
||||
$items = Subscriptions::select('created_at', 'email', 'name', 'location')->get();
|
||||
break;
|
||||
default:
|
||||
abort(404);
|
||||
}
|
||||
|
||||
Excel::create($sheet_name, function($excel) use($sheet_name, $headings, $items) {
|
||||
$excel->sheet($sheet_name, function($sheet) use($sheet_name, $headings, $items) {
|
||||
$sheet->fromArray($items);
|
||||
$sheet->row(1, $headings);
|
||||
});
|
||||
})->store('xls')->export('xls');
|
||||
}
|
||||
|
||||
/**
|
||||
* Dashboard Image Upload: Upload images
|
||||
*/
|
||||
public function postImageUpload(Request $request)
|
||||
{
|
||||
if ($request->hasFile('file')) {
|
||||
$file = base_path() . '/public/uploads/' . $request['model'] . '/' . $request['id'] . '.jpg';
|
||||
$image = Image::make($request->file('file'));
|
||||
$image->save($file);
|
||||
} else {
|
||||
return 'file-upload-fail';
|
||||
}
|
||||
|
||||
return 'success';
|
||||
}
|
||||
|
||||
/**
|
||||
* Dashboard Edit: Create and edit rows
|
||||
*/
|
||||
public function postEdit(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'id' => 'required',
|
||||
'model' => 'required',
|
||||
'columns' => 'required'
|
||||
]);
|
||||
|
||||
// store the id request variable for easy access
|
||||
$id = $request['id'];
|
||||
|
||||
// set the model using the 'model' request argument
|
||||
switch ($request['model']) {
|
||||
default:
|
||||
return 'model-access-fail';
|
||||
}
|
||||
|
||||
// populate the eloquent object with the remaining items in $request
|
||||
foreach ($request['columns'] as $column) {
|
||||
$item->$column = $request[$column];
|
||||
}
|
||||
|
||||
// save the new or updated item
|
||||
$item->save();
|
||||
|
||||
// return the id number in the format '^id:[0-9][0-9]*$' on success
|
||||
return 'id:' . $item->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dashboard Reorder: Reorder rows
|
||||
*/
|
||||
public function postReorder(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'order' => 'required',
|
||||
'column' => 'required',
|
||||
'model' => 'required'
|
||||
]);
|
||||
|
||||
$order = $request['order'];
|
||||
$column = $request['column'];
|
||||
|
||||
// set the model using the 'model' request argument
|
||||
switch ($request['model']) {
|
||||
default:
|
||||
return 'model-access-fail';
|
||||
}
|
||||
|
||||
// update each row with the new order
|
||||
foreach (array_keys($order) as $order_id) {
|
||||
$item = $items::find($order_id);
|
||||
$item->$column = $order[$order_id];
|
||||
$item->save();
|
||||
}
|
||||
|
||||
return 'success';
|
||||
}
|
||||
|
||||
/**
|
||||
* Dashboard Delete: Delete rows
|
||||
*/
|
||||
public function deleteDelete(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'id' => 'required',
|
||||
'model' => 'required'
|
||||
]);
|
||||
|
||||
// set the model using the 'model' request argument
|
||||
switch ($request['model']) {
|
||||
default:
|
||||
return 'model-access-fail';
|
||||
}
|
||||
|
||||
// delete the row with the id using the 'id' request argument
|
||||
if ($items::where('id', $request['id'])->exists()) {
|
||||
$items::where('id', $request['id'])->delete();
|
||||
} else {
|
||||
return 'row-delete-fail';
|
||||
}
|
||||
|
||||
// delete the associated image if one exists
|
||||
$image_file = base_path() . '/public/uploads/' . $request['model'] . '/' . $request['id'] . '.jpg';
|
||||
if (file_exists($image_file)) {
|
||||
if (!unlink($image_file)) {
|
||||
return 'image-delete-fail';
|
||||
}
|
||||
}
|
||||
|
||||
// Return a success
|
||||
return 'success';
|
||||
}
|
||||
}
|
39
app/Http/Controllers/SubscriptionController.php
Normal file
39
app/Http/Controllers/SubscriptionController.php
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?php namespace App\Http\Controllers;
|
||||
|
||||
use Newsletter;
|
||||
use App\Models\Subscriptions;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class SubscriptionController extends Controller
|
||||
{
|
||||
public function postSubscriptionSubmit(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'name' => 'required',
|
||||
'email' => 'required|email',
|
||||
'address' => array('required', 'regex:/^([A-Za-z][0-9][A-Za-z] *[0-9][A-Za-z][0-9]|[0-9][0-9][0-9][0-9][0-9])$/')
|
||||
]);
|
||||
|
||||
$name = $request['name'];
|
||||
$fname = preg_replace('/ .*$/', '', $name);
|
||||
$lname = preg_match('/. ./', $name) === 1 ? preg_replace('/^[^ ][^ ]* /', '', $name) : '';
|
||||
$email = $request['email'];
|
||||
$address = $request['address'];
|
||||
|
||||
// Submit the subscription request
|
||||
Newsletter::subscribe($email, [
|
||||
'FNAME' => $fname,
|
||||
'LNAME' => $lname,
|
||||
'ADDRESS' => $address
|
||||
]);
|
||||
|
||||
// Save to the database on success
|
||||
$subscriptions = new Subscriptions;
|
||||
$subscriptions->name = $name;
|
||||
$subscriptions->email = $email;
|
||||
$subscriptions->location = $address;
|
||||
$subscriptions->save();
|
||||
|
||||
return 'success';
|
||||
}
|
||||
}
|
|
@ -44,9 +44,9 @@ class Kernel extends HttpKernel
|
|||
* @var array
|
||||
*/
|
||||
protected $routeMiddleware = [
|
||||
'auth' => \App\Http\Middleware\Authenticate::class,
|
||||
'auth' => \App\Http\Middleware\Authenticate::class,
|
||||
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
|
||||
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
|
||||
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
|
||||
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||
];
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ class Authenticate
|
|||
if ($request->ajax()) {
|
||||
return response('Unauthorized.', 401);
|
||||
} else {
|
||||
return redirect()->guest('auth/login');
|
||||
return redirect()->guest('/login');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ class RedirectIfAuthenticated
|
|||
public function handle($request, Closure $next, $guard = null)
|
||||
{
|
||||
if (Auth::guard($guard)->check()) {
|
||||
return redirect('/');
|
||||
return redirect('/dashboard');
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
|
|
|
@ -1,34 +1,47 @@
|
|||
<?php
|
||||
|
||||
Route::group(['middleware' => ['web']], function () {
|
||||
Route::group(['middleware' => 'web'], function () {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Public Routes
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Route::get('/', function () {
|
||||
return view('website.home');
|
||||
Route::get('/', function() {
|
||||
Head::setTitle('Home');
|
||||
return view('website.index');
|
||||
});
|
||||
|
||||
Route::get('/contact', function() {
|
||||
Head::setTitle('Contact');
|
||||
return view('website.contact');
|
||||
});
|
||||
|
||||
Route::post('/contact-submit', 'ContactController@postContactSubmit');
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Content Management Routes
|
||||
| Post Routes
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// Authentication
|
||||
Route::get('auth/login', 'Auth\AuthController@getLogin');
|
||||
Route::post('auth/login', 'Auth\AuthController@postLogin');
|
||||
Route::get('auth/logout', 'Auth\AuthController@getLogout');
|
||||
Route::post('/contact-submit', 'ContactController@postContactSubmit');
|
||||
Route::post('/subscription-submit', 'SubscriptionController@postSubscriptionSubmit');
|
||||
|
||||
// Registration
|
||||
Route::get('auth/register', 'Auth\AuthController@getRegister');
|
||||
Route::post('auth/register', 'Auth\AuthController@postRegister');
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Authentication Routes
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Route::auth();
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Dashboard Routes
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Route::group(['prefix' => 'dashboard'], function() {
|
||||
Route::get('/', 'DashboardController@index');
|
||||
Route::controller('', DashboardController::class);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
<?php namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
|
@ -8,4 +6,10 @@ class Contact extends Model
|
|||
{
|
||||
// the contact table
|
||||
protected $table = 'contact';
|
||||
|
||||
// returns the list of all contact submissions
|
||||
public static function getContactSubmissions()
|
||||
{
|
||||
return self::orderBy('created_at', 'desc')->get();
|
||||
}
|
||||
}
|
||||
|
|
15
app/Models/Subscriptions.php
Normal file
15
app/Models/Subscriptions.php
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?php namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Subscriptions extends Model
|
||||
{
|
||||
// the subscriptions table
|
||||
protected $table = 'subscriptions';
|
||||
|
||||
// returns the list of all subscriptions
|
||||
public static function getSubscriptions()
|
||||
{
|
||||
return self::orderBy('created_at', 'desc')->get();
|
||||
}
|
||||
}
|
|
@ -7,6 +7,12 @@
|
|||
"description": "A hypothetical website template",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bootstrap": "~3.3.6"
|
||||
"bootstrap": "~3.3.6",
|
||||
"font-awesome": "~4.5.0",
|
||||
"awesome-bootstrap-checkbox": "~0.3.5",
|
||||
"Sortable": "~1.4.2",
|
||||
"simplemde": "~1.9.0",
|
||||
"datetimepicker": "~2.4.5",
|
||||
"SpinKit": "~1.2.5"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,10 @@
|
|||
"laravel/framework": "5.2.*",
|
||||
"radic/blade-extensions": "~6.0",
|
||||
"erusev/parsedown": "~1.5",
|
||||
"gwnobots/laravel-head": "dev-master"
|
||||
"gwnobots/laravel-head": "dev-master",
|
||||
"spatie/laravel-newsletter": "^2.2",
|
||||
"intervention/image": "^2.3",
|
||||
"maatwebsite/excel": "~2.0.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"fzaninotto/faker": "~1.4",
|
||||
|
|
704
composer.lock
generated
704
composer.lock
generated
|
@ -4,8 +4,8 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"hash": "909b8a65ce3c9081674735483be15837",
|
||||
"content-hash": "a72eccf8b74633ef449571150228ba0e",
|
||||
"hash": "1c79203a020edce6fbdbf7c0f5ce5905",
|
||||
"content-hash": "b4d80c4f47f54b01adf0017122832a48",
|
||||
"packages": [
|
||||
{
|
||||
"name": "anahkiasen/underscore-php",
|
||||
|
@ -357,6 +357,64 @@
|
|||
],
|
||||
"time": "2015-03-11 15:46:37"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/psr7",
|
||||
"version": "1.2.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/psr7.git",
|
||||
"reference": "4d0bdbe1206df7440219ce14c972aa57cc5e4982"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/4d0bdbe1206df7440219ce14c972aa57cc5e4982",
|
||||
"reference": "4d0bdbe1206df7440219ce14c972aa57cc5e4982",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4.0",
|
||||
"psr/http-message": "~1.0"
|
||||
},
|
||||
"provide": {
|
||||
"psr/http-message-implementation": "1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"GuzzleHttp\\Psr7\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/functions_include.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Michael Dowling",
|
||||
"email": "mtdowling@gmail.com",
|
||||
"homepage": "https://github.com/mtdowling"
|
||||
}
|
||||
],
|
||||
"description": "PSR-7 message implementation",
|
||||
"keywords": [
|
||||
"http",
|
||||
"message",
|
||||
"stream",
|
||||
"uri"
|
||||
],
|
||||
"time": "2015-11-03 01:34:55"
|
||||
},
|
||||
{
|
||||
"name": "gwnobots/laravel-head",
|
||||
"version": "dev-master",
|
||||
|
@ -405,6 +463,68 @@
|
|||
],
|
||||
"time": "2015-03-09 05:14:57"
|
||||
},
|
||||
{
|
||||
"name": "intervention/image",
|
||||
"version": "2.3.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Intervention/image.git",
|
||||
"reference": "9f29360b8ab94585cb9e80cf9045abd5b85feb89"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Intervention/image/zipball/9f29360b8ab94585cb9e80cf9045abd5b85feb89",
|
||||
"reference": "9f29360b8ab94585cb9e80cf9045abd5b85feb89",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-fileinfo": "*",
|
||||
"guzzlehttp/psr7": "~1.1",
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "~0.9.2",
|
||||
"phpunit/phpunit": "3.*"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-gd": "to use GD library based image processing.",
|
||||
"ext-imagick": "to use Imagick based image processing.",
|
||||
"intervention/imagecache": "Caching extension for the Intervention Image library"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.3-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Intervention\\Image\\": "src/Intervention/Image"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Oliver Vogel",
|
||||
"email": "oliver@olivervogel.net",
|
||||
"homepage": "http://olivervogel.net/"
|
||||
}
|
||||
],
|
||||
"description": "Image handling and manipulation library with support for Laravel integration",
|
||||
"homepage": "http://image.intervention.io/",
|
||||
"keywords": [
|
||||
"gd",
|
||||
"image",
|
||||
"imagick",
|
||||
"laravel",
|
||||
"thumbnail",
|
||||
"watermark"
|
||||
],
|
||||
"time": "2016-01-02 19:15:13"
|
||||
},
|
||||
{
|
||||
"name": "jakub-onderka/php-console-color",
|
||||
"version": "0.1",
|
||||
|
@ -552,16 +672,16 @@
|
|||
},
|
||||
{
|
||||
"name": "laravel/framework",
|
||||
"version": "v5.2.6",
|
||||
"version": "v5.2.10",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/framework.git",
|
||||
"reference": "b774c304ee81fcf5402fa06b261b364ba8f29cf0"
|
||||
"reference": "93dc5b0089eef468157fd7200e575c3861ec59a5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/b774c304ee81fcf5402fa06b261b364ba8f29cf0",
|
||||
"reference": "b774c304ee81fcf5402fa06b261b364ba8f29cf0",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/93dc5b0089eef468157fd7200e575c3861ec59a5",
|
||||
"reference": "93dc5b0089eef468157fd7200e575c3861ec59a5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -676,7 +796,61 @@
|
|||
"framework",
|
||||
"laravel"
|
||||
],
|
||||
"time": "2015-12-31 17:41:58"
|
||||
"time": "2016-01-13 20:29:10"
|
||||
},
|
||||
{
|
||||
"name": "laravelcollective/html",
|
||||
"version": "v5.2.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/LaravelCollective/html.git",
|
||||
"reference": "add2c74b144d0a25ba27a1506b7ce84e6bcadd64"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/LaravelCollective/html/zipball/add2c74b144d0a25ba27a1506b7ce84e6bcadd64",
|
||||
"reference": "add2c74b144d0a25ba27a1506b7ce84e6bcadd64",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/http": "5.2.*",
|
||||
"illuminate/routing": "5.2.*",
|
||||
"illuminate/session": "5.2.*",
|
||||
"illuminate/support": "5.2.*",
|
||||
"illuminate/view": "5.2.*",
|
||||
"php": ">=5.5.9"
|
||||
},
|
||||
"require-dev": {
|
||||
"illuminate/database": "5.2.*",
|
||||
"mockery/mockery": "~0.9",
|
||||
"phpunit/phpunit": "~4.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Collective\\Html\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/helpers.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylorotwell@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Adam Engebretson",
|
||||
"email": "adam@laravelcollective.com"
|
||||
}
|
||||
],
|
||||
"description": "HTML and Form Builders for the Laravel Framework",
|
||||
"homepage": "http://laravelcollective.com",
|
||||
"time": "2016-01-15 21:59:03"
|
||||
},
|
||||
{
|
||||
"name": "league/flysystem",
|
||||
|
@ -762,6 +936,119 @@
|
|||
],
|
||||
"time": "2015-12-19 20:16:43"
|
||||
},
|
||||
{
|
||||
"name": "maatwebsite/excel",
|
||||
"version": "v2.0.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Maatwebsite/Laravel-Excel.git",
|
||||
"reference": "bd9428da19fb3de9bbdd80f18f31b744485dc250"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Maatwebsite/Laravel-Excel/zipball/bd9428da19fb3de9bbdd80f18f31b744485dc250",
|
||||
"reference": "bd9428da19fb3de9bbdd80f18f31b744485dc250",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/cache": "~5.0|~5.1",
|
||||
"illuminate/config": "~5.0|~5.1",
|
||||
"illuminate/filesystem": "~5.0|~5.1",
|
||||
"illuminate/support": "~5.0|~5.1",
|
||||
"nesbot/carbon": "~1.0",
|
||||
"php": ">=5.3.0",
|
||||
"phpoffice/phpexcel": "~1.8.0",
|
||||
"tijsverkoyen/css-to-inline-styles": "~1.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "~0.9",
|
||||
"orchestra/testbench": "~3.0.0",
|
||||
"phpseclib/phpseclib": ">=0.3.7",
|
||||
"phpunit/phpunit": "~4.0"
|
||||
},
|
||||
"suggest": {
|
||||
"illuminate/http": "~5.0|~5.1",
|
||||
"illuminate/routing": "~5.0|~5.1",
|
||||
"illuminate/view": "~5.0|~5.1"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/Maatwebsite/Excel",
|
||||
"tests/TestCase.php"
|
||||
],
|
||||
"psr-0": {
|
||||
"Maatwebsite\\Excel\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"LGPL"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Maatwebsite.nl",
|
||||
"email": "patrick@maatwebsite.nl"
|
||||
}
|
||||
],
|
||||
"description": "An eloquent way of importing and exporting Excel and CSV in Laravel 4 with the power of PHPExcel",
|
||||
"keywords": [
|
||||
"PHPExcel",
|
||||
"batch",
|
||||
"csv",
|
||||
"excel",
|
||||
"export",
|
||||
"import",
|
||||
"laravel"
|
||||
],
|
||||
"time": "2015-10-26 10:15:37"
|
||||
},
|
||||
{
|
||||
"name": "mailchimp/mailchimp",
|
||||
"version": "2.0.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://bitbucket.org/mailchimp/mailchimp-api-php.git",
|
||||
"reference": "7ac99b5ac746d5875c5c350ad7e3b83674c83ec1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://bitbucket.org/mailchimp/mailchimp-api-php/get/7ac99b5ac746d5875c5c350ad7e3b83674c83ec1.zip",
|
||||
"reference": "7ac99b5ac746d5875c5c350ad7e3b83674c83ec1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"apigen/apigen": "dev-master"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Mailchimp": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "MailChimp Devs",
|
||||
"email": "api@mailchimp.com",
|
||||
"homepage": "http://mailchimp.com",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "API client library for the MailChimp bulk email as a service platform",
|
||||
"homepage": "https://bitbucket.org/mailchimp/mailchimp-api-php",
|
||||
"keywords": [
|
||||
"api",
|
||||
"email"
|
||||
],
|
||||
"time": "2014-10-30 20:38:12"
|
||||
},
|
||||
{
|
||||
"name": "monolog/monolog",
|
||||
"version": "1.17.2",
|
||||
|
@ -983,16 +1270,16 @@
|
|||
},
|
||||
{
|
||||
"name": "paragonie/random_compat",
|
||||
"version": "1.1.4",
|
||||
"version": "1.1.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/paragonie/random_compat.git",
|
||||
"reference": "d762ee5b099a29044603cd4649851e81aa66cb47"
|
||||
"reference": "dd8998b7c846f6909f4e7a5f67fabebfc412a4f7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/d762ee5b099a29044603cd4649851e81aa66cb47",
|
||||
"reference": "d762ee5b099a29044603cd4649851e81aa66cb47",
|
||||
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/dd8998b7c846f6909f4e7a5f67fabebfc412a4f7",
|
||||
"reference": "dd8998b7c846f6909f4e7a5f67fabebfc412a4f7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1027,7 +1314,7 @@
|
|||
"pseudorandom",
|
||||
"random"
|
||||
],
|
||||
"time": "2015-12-10 14:48:13"
|
||||
"time": "2016-01-06 13:31:20"
|
||||
},
|
||||
{
|
||||
"name": "patchwork/utf8",
|
||||
|
@ -1088,6 +1375,112 @@
|
|||
],
|
||||
"time": "2015-12-15 15:34:15"
|
||||
},
|
||||
{
|
||||
"name": "phpoffice/phpexcel",
|
||||
"version": "1.8.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHPOffice/PHPExcel.git",
|
||||
"reference": "372c7cbb695a6f6f1e62649381aeaa37e7e70b32"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHPOffice/PHPExcel/zipball/372c7cbb695a6f6f1e62649381aeaa37e7e70b32",
|
||||
"reference": "372c7cbb695a6f6f1e62649381aeaa37e7e70b32",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-xml": "*",
|
||||
"ext-xmlwriter": "*",
|
||||
"php": ">=5.2.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"PHPExcel": "Classes/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"LGPL"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Maarten Balliauw",
|
||||
"homepage": "http://blog.maartenballiauw.be"
|
||||
},
|
||||
{
|
||||
"name": "Mark Baker"
|
||||
},
|
||||
{
|
||||
"name": "Franck Lefevre",
|
||||
"homepage": "http://blog.rootslabs.net"
|
||||
},
|
||||
{
|
||||
"name": "Erik Tilt"
|
||||
}
|
||||
],
|
||||
"description": "PHPExcel - OpenXML - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine",
|
||||
"homepage": "http://phpexcel.codeplex.com",
|
||||
"keywords": [
|
||||
"OpenXML",
|
||||
"excel",
|
||||
"php",
|
||||
"spreadsheet",
|
||||
"xls",
|
||||
"xlsx"
|
||||
],
|
||||
"time": "2015-05-01 07:00:55"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-message",
|
||||
"version": "1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/http-message.git",
|
||||
"reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298",
|
||||
"reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Http\\Message\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for HTTP messages",
|
||||
"keywords": [
|
||||
"http",
|
||||
"http-message",
|
||||
"psr",
|
||||
"psr-7",
|
||||
"request",
|
||||
"response"
|
||||
],
|
||||
"time": "2015-05-04 20:22:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/log",
|
||||
"version": "1.0.0",
|
||||
|
@ -1257,16 +1650,16 @@
|
|||
},
|
||||
{
|
||||
"name": "sebwite/support",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.10",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://bitbucket.org/sebwitepackages/sebwite-support.git",
|
||||
"reference": "f731cbdf8f7c608fd79c6373b5e50c4c9efdfd9e"
|
||||
"reference": "e93caad0a5a1c89847d2c0c02e49f986945fce45"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://bitbucket.org/sebwitepackages/sebwite-support/get/f731cbdf8f7c608fd79c6373b5e50c4c9efdfd9e.zip",
|
||||
"reference": "f731cbdf8f7c608fd79c6373b5e50c4c9efdfd9e",
|
||||
"url": "https://bitbucket.org/sebwitepackages/sebwite-support/get/e93caad0a5a1c89847d2c0c02e49f986945fce45.zip",
|
||||
"reference": "e93caad0a5a1c89847d2c0c02e49f986945fce45",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1277,8 +1670,11 @@
|
|||
"illuminate/console": "~5.1",
|
||||
"illuminate/filesystem": "~5.1",
|
||||
"illuminate/support": "~5.1",
|
||||
"laravelcollective/html": "~5.1",
|
||||
"php": ">=5.5.9",
|
||||
"symfony/filesystem": "~2.7",
|
||||
"radic/blade-extensions": "~6.1",
|
||||
"symfony/filesystem": "~2.7|~3.0",
|
||||
"symfony/options-resolver": "~2.0|~3.0",
|
||||
"webmozart/path-util": "~1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
|
@ -1313,7 +1709,58 @@
|
|||
"structure",
|
||||
"support"
|
||||
],
|
||||
"time": "2015-12-28 19:20:17"
|
||||
"time": "2016-01-13 11:02:15"
|
||||
},
|
||||
{
|
||||
"name": "spatie/laravel-newsletter",
|
||||
"version": "2.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/spatie/laravel-newsletter.git",
|
||||
"reference": "cdfe4de92f4c822904bfaee5f85a98d495ca56d3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/spatie/laravel-newsletter/zipball/cdfe4de92f4c822904bfaee5f85a98d495ca56d3",
|
||||
"reference": "cdfe4de92f4c822904bfaee5f85a98d495ca56d3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/support": "~5.0",
|
||||
"mailchimp/mailchimp": "~2.0",
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "0.9.*",
|
||||
"phpunit/phpunit": "4.*",
|
||||
"scrutinizer/ocular": "~1.1"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Spatie\\Newsletter\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Freek Van der Herten",
|
||||
"email": "freek@spatie.be",
|
||||
"homepage": "https://murze.be",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "Manage newsletters in Laravel 5",
|
||||
"homepage": "https://github.com/spatie/laravel-newsletter",
|
||||
"keywords": [
|
||||
"laravel",
|
||||
"mailchimp",
|
||||
"newsletter"
|
||||
],
|
||||
"time": "2015-12-21 22:48:10"
|
||||
},
|
||||
{
|
||||
"name": "swiftmailer/swiftmailer",
|
||||
|
@ -1428,6 +1875,59 @@
|
|||
"homepage": "https://symfony.com",
|
||||
"time": "2015-12-22 10:39:06"
|
||||
},
|
||||
{
|
||||
"name": "symfony/css-selector",
|
||||
"version": "v3.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/css-selector.git",
|
||||
"reference": "4613311fd46e146f506403ce2f8a0c71d402d2a3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/css-selector/zipball/4613311fd46e146f506403ce2f8a0c71d402d2a3",
|
||||
"reference": "4613311fd46e146f506403ce2f8a0c71d402d2a3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.5.9"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\CssSelector\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jean-François Simon",
|
||||
"email": "jeanfrancois.simon@sensiolabs.com"
|
||||
},
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony CssSelector Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2015-12-05 17:45:07"
|
||||
},
|
||||
{
|
||||
"name": "symfony/debug",
|
||||
"version": "v3.0.1",
|
||||
|
@ -1547,25 +2047,25 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/filesystem",
|
||||
"version": "v2.8.1",
|
||||
"version": "v3.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/filesystem.git",
|
||||
"reference": "a7ad724530a764d70c168d321ac226ba3d2f10fc"
|
||||
"reference": "c2e59d11dccd135dc8f00ee97f34fe1de842e70c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/a7ad724530a764d70c168d321ac226ba3d2f10fc",
|
||||
"reference": "a7ad724530a764d70c168d321ac226ba3d2f10fc",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/c2e59d11dccd135dc8f00ee97f34fe1de842e70c",
|
||||
"reference": "c2e59d11dccd135dc8f00ee97f34fe1de842e70c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.9"
|
||||
"php": ">=5.5.9"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.8-dev"
|
||||
"dev-master": "3.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -1592,7 +2092,7 @@
|
|||
],
|
||||
"description": "Symfony Filesystem Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2015-12-22 10:25:57"
|
||||
"time": "2015-12-22 10:39:06"
|
||||
},
|
||||
{
|
||||
"name": "symfony/finder",
|
||||
|
@ -1777,6 +2277,60 @@
|
|||
"homepage": "https://symfony.com",
|
||||
"time": "2015-12-26 16:46:13"
|
||||
},
|
||||
{
|
||||
"name": "symfony/options-resolver",
|
||||
"version": "v3.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/options-resolver.git",
|
||||
"reference": "8e68c053a39e26559357cc742f01a7182ce40785"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/8e68c053a39e26559357cc742f01a7182ce40785",
|
||||
"reference": "8e68c053a39e26559357cc742f01a7182ce40785",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.5.9"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\OptionsResolver\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony OptionsResolver Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"config",
|
||||
"configuration",
|
||||
"options"
|
||||
],
|
||||
"time": "2015-11-18 13:48:51"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.0.1",
|
||||
|
@ -2194,6 +2748,53 @@
|
|||
],
|
||||
"time": "2015-12-05 11:13:14"
|
||||
},
|
||||
{
|
||||
"name": "tijsverkoyen/css-to-inline-styles",
|
||||
"version": "1.5.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/tijsverkoyen/CssToInlineStyles.git",
|
||||
"reference": "9753fc340726e327e4d48b7c0604f85475ae0bc3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/9753fc340726e327e4d48b7c0604f85475ae0bc3",
|
||||
"reference": "9753fc340726e327e4d48b7c0604f85475ae0bc3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0",
|
||||
"symfony/css-selector": "~2.1|~3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.5.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"TijsVerkoyen\\CssToInlineStyles\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Tijs Verkoyen",
|
||||
"email": "css_to_inline_styles@verkoyen.eu",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "CssToInlineStyles is a class that enables you to convert HTML-pages/files into HTML-pages/files with inline styles. This is very useful when you're sending emails.",
|
||||
"homepage": "https://github.com/tijsverkoyen/CssToInlineStyles",
|
||||
"time": "2015-12-08 16:14:14"
|
||||
},
|
||||
{
|
||||
"name": "vlucas/phpdotenv",
|
||||
"version": "v2.2.0",
|
||||
|
@ -3352,59 +3953,6 @@
|
|||
"homepage": "https://github.com/sebastianbergmann/version",
|
||||
"time": "2015-06-21 13:59:46"
|
||||
},
|
||||
{
|
||||
"name": "symfony/css-selector",
|
||||
"version": "v3.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/css-selector.git",
|
||||
"reference": "4613311fd46e146f506403ce2f8a0c71d402d2a3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/css-selector/zipball/4613311fd46e146f506403ce2f8a0c71d402d2a3",
|
||||
"reference": "4613311fd46e146f506403ce2f8a0c71d402d2a3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.5.9"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\CssSelector\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jean-François Simon",
|
||||
"email": "jeanfrancois.simon@sensiolabs.com"
|
||||
},
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony CssSelector Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2015-12-05 17:45:07"
|
||||
},
|
||||
{
|
||||
"name": "symfony/dom-crawler",
|
||||
"version": "v3.0.1",
|
||||
|
|
|
@ -160,6 +160,9 @@ return [
|
|||
*/
|
||||
Radic\BladeExtensions\BladeExtensionsServiceProvider::class,
|
||||
Gwnobots\LaravelHead\LaravelHeadServiceProvider::class,
|
||||
Spatie\Newsletter\NewsletterServiceProvider::class,
|
||||
Intervention\Image\ImageServiceProvider::class,
|
||||
Maatwebsite\Excel\ExcelServiceProvider::class,
|
||||
|
||||
],
|
||||
|
||||
|
@ -206,6 +209,13 @@ return [
|
|||
'Validator' => Illuminate\Support\Facades\Validator::class,
|
||||
'View' => Illuminate\Support\Facades\View::class,
|
||||
|
||||
],
|
||||
/*
|
||||
* Custom Class Aliases...
|
||||
*/
|
||||
'Newsletter' => Spatie\Newsletter\NewsletterFacade::class,
|
||||
'Image' => Intervention\Image\Facades\Image::class,
|
||||
'Excel' => Maatwebsite\Excel\Facades\Excel::class,
|
||||
|
||||
]
|
||||
|
||||
];
|
||||
|
|
683
config/excel.php
Normal file
683
config/excel.php
Normal file
|
@ -0,0 +1,683 @@
|
|||
<?php
|
||||
|
||||
return array(
|
||||
|
||||
'cache' => array(
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Enable/Disable cell caching
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'enable' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Caching driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Set the caching driver
|
||||
|
|
||||
| Available methods:
|
||||
| memory|gzip|serialized|igbinary|discISAM|apc|memcache|temp|wincache|sqlite|sqlite3
|
||||
|
|
||||
*/
|
||||
'driver' => 'memory',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cache settings
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'settings' => array(
|
||||
|
||||
'memoryCacheSize' => '32MB',
|
||||
'cacheTime' => 600
|
||||
|
||||
),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Memcache settings
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'memcache' => array(
|
||||
|
||||
'host' => 'localhost',
|
||||
'port' => 11211,
|
||||
|
||||
),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cache dir (for discISAM)
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
'dir' => storage_path('cache')
|
||||
),
|
||||
|
||||
'properties' => array(
|
||||
'creator' => env('SITE_NAME', 'Dashboard'),
|
||||
'lastModifiedBy' => env('SITE_NAME', 'Dashboard'),
|
||||
'title' => 'Spreadsheet Export',
|
||||
'description' => 'Exported Spreadsheet Data',
|
||||
'subject' => 'Spreadsheet export',
|
||||
'keywords' => 'excel, export',
|
||||
'category' => 'Excel',
|
||||
'manager' => env('SITE_NAME', 'Dashboard'),
|
||||
'company' => env('SITE_NAME', 'Dashboard'),
|
||||
),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Sheets settings
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'sheets' => array(
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default page setup
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'pageSetup' => array(
|
||||
'orientation' => 'portrait',
|
||||
'paperSize' => '9',
|
||||
'scale' => '100',
|
||||
'fitToPage' => false,
|
||||
'fitToHeight' => true,
|
||||
'fitToWidth' => true,
|
||||
'columnsToRepeatAtLeft' => array('', ''),
|
||||
'rowsToRepeatAtTop' => array(0, 0),
|
||||
'horizontalCentered' => false,
|
||||
'verticalCentered' => false,
|
||||
'printArea' => null,
|
||||
'firstPageNumber' => null,
|
||||
),
|
||||
),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Creator
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The default creator of a new Excel file
|
||||
|
|
||||
*/
|
||||
|
||||
'creator' => env('SITE_NAME', 'Dashboard'),
|
||||
|
||||
'csv' => array(
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Delimiter
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The default delimiter which will be used to read out a CSV file
|
||||
|
|
||||
*/
|
||||
|
||||
'delimiter' => ',',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Enclosure
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
'enclosure' => '"',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Line endings
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
'line_ending' => "\r\n"
|
||||
),
|
||||
|
||||
'export' => array(
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Autosize columns
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Disable/enable column autosize or set the autosizing for
|
||||
| an array of columns ( array('A', 'B') )
|
||||
|
|
||||
*/
|
||||
'autosize' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Autosize method
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| --> PHPExcel_Shared_Font::AUTOSIZE_METHOD_APPROX
|
||||
| The default is based on an estimate, which does its calculation based
|
||||
| on the number of characters in the cell value (applying any calculation
|
||||
| and format mask, and allowing for wordwrap and rotation) and with an
|
||||
| "arbitrary" adjustment based on the font (Arial, Calibri or Verdana,
|
||||
| defaulting to Calibri if any other font is used) and a proportional
|
||||
| adjustment for the font size.
|
||||
|
|
||||
| --> PHPExcel_Shared_Font::AUTOSIZE_METHOD_EXACT
|
||||
| The second method is more accurate, based on actual style formatting as
|
||||
| well (bold, italic, etc), and is calculated by generating a gd2 imagettf
|
||||
| bounding box and using its dimensions to determine the size; but this
|
||||
| method is significantly slower, and its accuracy is still dependent on
|
||||
| having the appropriate fonts installed.
|
||||
|
|
||||
*/
|
||||
'autosize-method' => PHPExcel_Shared_Font::AUTOSIZE_METHOD_APPROX,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Auto generate table heading
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If set to true, the array indices (or model attribute names)
|
||||
| will automatically be used as first row (table heading)
|
||||
|
|
||||
*/
|
||||
'generate_heading_by_indices' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Auto set alignment on merged cells
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'merged_cell_alignment' => 'left',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Pre-calculate formulas during export
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'calculate' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Include Charts during export
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'includeCharts' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default sheet settings
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'sheets' => array(
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default page margin
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| 1) When set to false, default margins will be used
|
||||
| 2) It's possible to enter a single margin which will
|
||||
| be used for all margins.
|
||||
| 3) Alternatively you can pass an array with 4 margins
|
||||
| Default order: array(top, right, bottom, left)
|
||||
|
|
||||
*/
|
||||
'page_margin' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Value in source array that stands for blank cell
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'nullValue' => null,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Insert array starting from this cell address as the top left coordinate
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'startCell' => 'A1',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Apply strict comparison when testing for null values in the array
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'strictNullComparison' => false
|
||||
),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Store settings
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
'store' => array(
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The path we want to save excel file to
|
||||
|
|
||||
*/
|
||||
'path' => storage_path('exports'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Return info
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Whether we want to return information about the stored file or not
|
||||
|
|
||||
*/
|
||||
'returnInfo' => false
|
||||
|
||||
),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| PDF Settings
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'pdf' => array(
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| PDF Drivers
|
||||
|--------------------------------------------------------------------------
|
||||
| Supported: DomPDF, tcPDF, mPDF
|
||||
*/
|
||||
'driver' => 'DomPDF',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| PDF Driver settings
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'drivers' => array(
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| DomPDF settings
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'DomPDF' => array(
|
||||
'path' => base_path('vendor/dompdf/dompdf/')
|
||||
),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| tcPDF settings
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'tcPDF' => array(
|
||||
'path' => base_path('vendor/tecnick.com/tcpdf/')
|
||||
),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| mPDF settings
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'mPDF' => array(
|
||||
'path' => base_path('vendor/mpdf/mpdf/')
|
||||
),
|
||||
)
|
||||
)
|
||||
),
|
||||
|
||||
'filters' => array(
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Register read filters
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
'registered' => array(
|
||||
'chunk' => 'Maatwebsite\Excel\Filters\ChunkReadFilter'
|
||||
),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Enable certain filters for every file read
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
'enabled' => array()
|
||||
),
|
||||
|
||||
'import' => array(
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Has heading
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The sheet has a heading (first) row which we can use as attribute names
|
||||
|
|
||||
| Options: true|false|slugged|slugged_with_count|ascii|numeric|hashed|trans|original
|
||||
|
|
||||
*/
|
||||
|
||||
'heading' => 'slugged',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| First Row with data or heading of data
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If the heading row is not the first row, or the data doesn't start
|
||||
| on the first row, here you can change the start row.
|
||||
|
|
||||
*/
|
||||
|
||||
'startRow' => 1,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cell name word separator
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The default separator which is used for the cell names
|
||||
| Note: only applies to 'heading' settings 'true' && 'slugged'
|
||||
|
|
||||
*/
|
||||
|
||||
'separator' => '_',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Include Charts during import
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
'includeCharts' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Sheet heading conversion
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Convert headings to ASCII
|
||||
| Note: only applies to 'heading' settings 'true' && 'slugged'
|
||||
|
|
||||
*/
|
||||
|
||||
'to_ascii' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Import encoding
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
'encoding' => array(
|
||||
|
||||
'input' => 'UTF-8',
|
||||
'output' => 'UTF-8'
|
||||
|
||||
),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Calculate
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| By default cells with formulas will be calculated.
|
||||
|
|
||||
*/
|
||||
|
||||
'calculate' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Ignore empty cells
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| By default empty cells are not ignored
|
||||
|
|
||||
*/
|
||||
|
||||
'ignoreEmpty' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Force sheet collection
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| For a sheet collection even when there is only 1 sheets.
|
||||
| When set to false and only 1 sheet found, the parsed file will return
|
||||
| a row collection instead of a sheet collection.
|
||||
| When set to true, it will return a sheet collection instead.
|
||||
|
|
||||
*/
|
||||
'force_sheets_collection' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Date format
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The format dates will be parsed to
|
||||
|
|
||||
*/
|
||||
|
||||
'dates' => array(
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Enable/disable date formatting
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'enabled' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default date format
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If set to false, a carbon object will return
|
||||
|
|
||||
*/
|
||||
'format' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Date columns
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'columns' => array()
|
||||
),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Import sheets by config
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'sheets' => array(
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Example sheet
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Example sheet "test" will grab the firstname at cell A2
|
||||
|
|
||||
*/
|
||||
|
||||
'test' => array(
|
||||
|
||||
'firstname' => 'A2'
|
||||
|
||||
)
|
||||
|
||||
)
|
||||
),
|
||||
|
||||
'views' => array(
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Styles
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The default styles which will be used when parsing a view
|
||||
|
|
||||
*/
|
||||
|
||||
'styles' => array(
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Table headings
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'th' => array(
|
||||
'font' => array(
|
||||
'bold' => true,
|
||||
'size' => 12,
|
||||
)
|
||||
),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Strong tags
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'strong' => array(
|
||||
'font' => array(
|
||||
'bold' => true,
|
||||
'size' => 12,
|
||||
)
|
||||
),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Bold tags
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'b' => array(
|
||||
'font' => array(
|
||||
'bold' => true,
|
||||
'size' => 12,
|
||||
)
|
||||
),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Italic tags
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'i' => array(
|
||||
'font' => array(
|
||||
'italic' => true,
|
||||
'size' => 12,
|
||||
)
|
||||
),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Heading 1
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'h1' => array(
|
||||
'font' => array(
|
||||
'bold' => true,
|
||||
'size' => 24,
|
||||
)
|
||||
),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Heading 2
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'h2' => array(
|
||||
'font' => array(
|
||||
'bold' => true,
|
||||
'size' => 18,
|
||||
)
|
||||
),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Heading 2
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'h3' => array(
|
||||
'font' => array(
|
||||
'bold' => true,
|
||||
'size' => 13.5,
|
||||
)
|
||||
),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Heading 4
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'h4' => array(
|
||||
'font' => array(
|
||||
'bold' => true,
|
||||
'size' => 12,
|
||||
)
|
||||
),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Heading 5
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'h5' => array(
|
||||
'font' => array(
|
||||
'bold' => true,
|
||||
'size' => 10,
|
||||
)
|
||||
),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Heading 6
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'h6' => array(
|
||||
'font' => array(
|
||||
'bold' => true,
|
||||
'size' => 7.5,
|
||||
)
|
||||
),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Hyperlinks
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'a' => array(
|
||||
'font' => array(
|
||||
'underline' => true,
|
||||
'color' => array('argb' => 'FF0000FF'),
|
||||
)
|
||||
),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Horizontal rules
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'hr' => array(
|
||||
'borders' => array(
|
||||
'bottom' => array(
|
||||
'style' => 'thin',
|
||||
'color' => array('FF000000')
|
||||
),
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
)
|
||||
|
||||
);
|
20
config/image.php
Normal file
20
config/image.php
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
return array(
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Image Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Intervention Image supports "GD Library" and "Imagick" to process images
|
||||
| internally. You may choose one of them according to your PHP
|
||||
| configuration. By default PHP's "GD Library" implementation is used.
|
||||
|
|
||||
| Supported: "gd", "imagick"
|
||||
|
|
||||
*/
|
||||
|
||||
'driver' => 'gd'
|
||||
|
||||
);
|
|
@ -102,7 +102,7 @@ return array(
|
|||
|
|
||||
*/
|
||||
|
||||
'responsive' => true,
|
||||
'responsive' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
64
config/laravel-newsletter.php
Normal file
64
config/laravel-newsletter.php
Normal file
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
|
||||
'mailChimp' => [
|
||||
|
||||
/*
|
||||
* The api key of a MailChimp account. You can find yours here:
|
||||
* https://us10.admin.mailchimp.com/account/api-key-popup/
|
||||
*/
|
||||
'apiKey' => env('MAILCHIMP_APIKEY'),
|
||||
|
||||
/*
|
||||
* Here you can define properties of the lists you want to
|
||||
* send campaigns.
|
||||
*/
|
||||
'lists' => [
|
||||
|
||||
/*
|
||||
* This key is used to identify this list. It can be used
|
||||
* in the various methods provided by this package.
|
||||
*
|
||||
* You can set it to any string you want and you can add
|
||||
* as many lists as you want.
|
||||
*/
|
||||
'subscribers' => [
|
||||
|
||||
/*
|
||||
* A mail chimp list id. Check the mailchimp docs if you don't know
|
||||
* how to get this value:
|
||||
* http://kb.mailchimp.com/lists/managing-subscribers/find-your-list-id
|
||||
*/
|
||||
'id' => env('MAILCHIMP_LISTID'),
|
||||
|
||||
/*
|
||||
* These values will be used when creating a new campaign.
|
||||
*/
|
||||
'createCampaign' => [
|
||||
'fromEmail' => '',
|
||||
'fromName' => '',
|
||||
'toName' => '',
|
||||
],
|
||||
|
||||
/*
|
||||
* These values will be used when subscribing to a list.
|
||||
*/
|
||||
'subscribe' => [
|
||||
'emailType' => 'html',
|
||||
'requireDoubleOptin' => false,
|
||||
'updateExistingUser' => false,
|
||||
],
|
||||
|
||||
/*
|
||||
* These values will be used when unsubscribing from a list.
|
||||
*/
|
||||
'unsubscribe' => [
|
||||
'deletePermanently' => false,
|
||||
'sendGoodbyeEmail' => false,
|
||||
'sendUnsubscribeEmail' => false,
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddSubscriptionTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('subscriptions', function(Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('name');
|
||||
$table->string('email');
|
||||
$table->string('location');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::drop('subscriptions');
|
||||
}
|
||||
}
|
|
@ -11,6 +11,6 @@ class DatabaseSeeder extends Seeder
|
|||
*/
|
||||
public function run()
|
||||
{
|
||||
// $this->call(UserTableSeeder::class);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
52
gulpfile.js
52
gulpfile.js
|
@ -1,6 +1,6 @@
|
|||
process.env.DISABLE_NOTIFIER = true;
|
||||
|
||||
var gulp = require("gulp"),
|
||||
var gulp = require('gulp'),
|
||||
elixir = require('laravel-elixir'),
|
||||
lessglob = require('less-plugin-glob');
|
||||
|
||||
|
@ -12,37 +12,55 @@ if (!elixir.config.production)
|
|||
elixir.config.autoprefix = {
|
||||
remove: false,
|
||||
cascade: false,
|
||||
browsers: ['last 2 versions']
|
||||
browsers: [ 'last 2 versions' ]
|
||||
};
|
||||
|
||||
// javascript files in resources/assets/js/
|
||||
// javascript files for the dashboard in resources/assets/js/
|
||||
var jsDashboard = [
|
||||
'dashboard.js'
|
||||
];
|
||||
|
||||
// javascript files for the public site in resources/assets/js/
|
||||
var jsLocal = [
|
||||
'site-vars.js',
|
||||
'contact.js',
|
||||
'subscription.js',
|
||||
'app.js'
|
||||
];
|
||||
|
||||
// javascript files in bower_components/
|
||||
// javascript files in bower_components/ for libraries
|
||||
var jsBower = [
|
||||
'jquery/dist/jquery.min.js',
|
||||
'bootstrap/dist/js/bootstrap.min.js'
|
||||
'bootstrap/dist/js/bootstrap.min.js',
|
||||
];
|
||||
|
||||
var jsDashboardBower = [
|
||||
'Sortable/Sortable.js',
|
||||
'datetimepicker/jquery.datetimepicker.js',
|
||||
'simplemde/dist/simplemde.min.js'
|
||||
];
|
||||
|
||||
// less import path locations other than resources/assets/less/
|
||||
var lessPaths = [
|
||||
'bower_components/bootstrap/less'
|
||||
];
|
||||
var lessPaths = [ 'bower_components' ];
|
||||
|
||||
elixir(function(mix) {
|
||||
// elixir mix functions
|
||||
mix.copy('bower_components/bootstrap/dist/fonts/bootstrap/**', 'public/fonts')
|
||||
.less('app.less', 'public/css/app.css', {
|
||||
paths: lessPaths,
|
||||
plugins: [lessglob]
|
||||
})
|
||||
.scripts(jsLocal, 'public/js/app.js', 'resources/assets/js/')
|
||||
.scripts(jsBower, 'public/js/lib.js', 'bower_components/')
|
||||
.version(['css/app.css', 'js/app.js', 'js/lib.js']);
|
||||
// compile the project
|
||||
mix
|
||||
.copy('bower_components/bootstrap/dist/fonts/**', 'public/fonts')
|
||||
.copy('bower_components/font-awesome/fonts/**', 'public/fonts')
|
||||
.less('dashboard.less', 'public/css/dashboard.css', {
|
||||
paths: lessPaths,
|
||||
plugins: [ lessglob ]
|
||||
})
|
||||
.less('app.less', 'public/css/app.css', {
|
||||
paths: lessPaths,
|
||||
plugins: [ lessglob ]
|
||||
})
|
||||
.scripts(jsLocal, 'public/js/app.js', 'resources/assets/js/')
|
||||
.scripts(jsDashboard, 'public/js/dashboard.js', 'resources/assets/js/')
|
||||
.scripts(jsBower, 'public/js/lib.js', 'bower_components/')
|
||||
.scripts(jsDashboardBower, 'public/js/lib-dashboard.js', 'bower_components/')
|
||||
.version([ 'css/dashboard.css', 'css/app.css', 'js/dashboard.js', 'js/app.js', 'js/lib.js', 'js/lib-dashboard.js' ]);
|
||||
|
||||
// start livereload when not production
|
||||
if (!elixir.config.production)
|
||||
|
|
237
readme.md
237
readme.md
|
@ -2,3 +2,240 @@
|
|||
|
||||
A hypothetical website template
|
||||
|
||||
## Dashboard
|
||||
|
||||
Unless otherwise stated all examples in this section are to be added to `app/Http/Controllers/DashboardController.php`.
|
||||
|
||||
### Adding a Viewable Model to the Dashboard
|
||||
|
||||
#### Viewable List of Rows
|
||||
|
||||
First add a function to generate the page:
|
||||
|
||||
```php
|
||||
public function getContact()
|
||||
{
|
||||
return view('dashboard.view', [
|
||||
'heading' => 'Contact Form Submissions',
|
||||
'model' => 'contact',
|
||||
'rows' => Contact::getContactSubmissions(),
|
||||
'cols' => [
|
||||
[ 'Date', 'created_at' ],
|
||||
[ 'Name', 'name' ],
|
||||
[ 'Email', 'email' ],
|
||||
[ 'Message', 'message' ]
|
||||
]
|
||||
]);
|
||||
}
|
||||
```
|
||||
|
||||
* `heading`: The title that will appear for this page
|
||||
* `model`: The model that will be accessed on this page
|
||||
* `rows`: A function returning an array containing the data to be shown on this page
|
||||
* `cols`: An array containing a set of arrays where the first element of each is the visible column name and the second is the column name in the array
|
||||
|
||||
#### Export Functionality
|
||||
|
||||
Viewable models must have an entry in the switch statement of the `getExport` function to make the export button work:
|
||||
|
||||
```php
|
||||
switch ($model) {
|
||||
case 'contact':
|
||||
$headings = [ 'Date', 'Name', 'Email', 'Message' ];
|
||||
$items = Contact::select('created_at', 'name', 'email', 'message')->get();
|
||||
break;
|
||||
default:
|
||||
abort(404);
|
||||
}
|
||||
```
|
||||
|
||||
* `$headings`: The visible column names in the same order as the array containing the items to be exported
|
||||
* `$items`: A function returning an array containing the data to be exported
|
||||
|
||||
### Adding an Editable Model to the Dashboard
|
||||
|
||||
#### Editable List of Rows
|
||||
|
||||
##### Editable List for Unsortable Model
|
||||
|
||||
```php
|
||||
public function getShows()
|
||||
{
|
||||
return view('dashboard.edit-list', [
|
||||
'heading' => 'Shows',
|
||||
'model' => 'shows',
|
||||
'rows' => Shows::getShowsList(),
|
||||
'column' => 'title',
|
||||
'sortcol' => 'false'
|
||||
]);
|
||||
}
|
||||
```
|
||||
|
||||
##### Editable List for Sortable Model
|
||||
|
||||
**NOTE**: Sortable models must have an entry configured in the `postReorder` function (details below)
|
||||
|
||||
```php
|
||||
public function getNews()
|
||||
{
|
||||
return view('dashboard.edit-list', [
|
||||
'heading' => 'News',
|
||||
'model' => 'news',
|
||||
'rows' => News::getNewsList(),
|
||||
'column' => 'title',
|
||||
'sortcol' => 'order'
|
||||
]);
|
||||
}
|
||||
```
|
||||
|
||||
* `heading`: The title that will appear for this page
|
||||
* `model`: The model that will be accessed on this page
|
||||
* `rows`: A function returning an array containing the data to be shown on this page
|
||||
* `column`: The column name in the array that contains the data to display in each row
|
||||
* `sortcol`: The name of the column containing the sort order or `'false'` to disable
|
||||
|
||||
#### Delete Functionality
|
||||
|
||||
Editable models must have an entry in the switch statement of the `deleteDelete` function to make deletion functionality work:
|
||||
|
||||
```php
|
||||
switch ($request['model']) {
|
||||
case 'shows':
|
||||
$items = new Shows();
|
||||
break;
|
||||
case 'news':
|
||||
$items = new News();
|
||||
break;
|
||||
default:
|
||||
return 'model-access-fail';
|
||||
}
|
||||
```
|
||||
|
||||
#### Editable Item
|
||||
|
||||
This function should be named the same as the one above except with `Edit` at the end
|
||||
|
||||
##### Editable Item for Unsortable Model
|
||||
|
||||
```php
|
||||
public function getShowsEdit($id = 'new')
|
||||
{
|
||||
if ($id != 'new') {
|
||||
if (Shows::where('id', $id)->exists()) {
|
||||
$item = Shows::where('id', $id)->first();
|
||||
} else {
|
||||
return view('errors.no-such-record');
|
||||
}
|
||||
} else {
|
||||
$item = null;
|
||||
}
|
||||
|
||||
return view('dashboard.edit-item', [
|
||||
'heading' => 'Shows',
|
||||
'model' => 'shows',
|
||||
'id' => $id,
|
||||
'item' => $item,
|
||||
'help_text' => '<strong>NOTE:</strong> This is some help text for the current page',
|
||||
'columns' => [
|
||||
[ 'name' => 'venue', 'type' => 'text' ],
|
||||
[ 'name' => 'date', 'type' => 'date' ],
|
||||
[ 'name' => 'address', 'type' => 'text' ],
|
||||
[ 'name' => 'phone', 'type' => 'text' ],
|
||||
[ 'name' => 'website', 'type' => 'text' ],
|
||||
[ 'name' => 'cover', 'type' => 'text' ],
|
||||
[ 'name' => 'description', 'type' => 'mkd' ]
|
||||
]
|
||||
]);
|
||||
}
|
||||
```
|
||||
|
||||
##### Editable Item for Sortable Model
|
||||
|
||||
```php
|
||||
public function getNewsEdit($id = 'new')
|
||||
{
|
||||
if ($id != 'new') {
|
||||
if (News::where('id', $id)->exists()) {
|
||||
$item = News::where('id', $id)->first();
|
||||
} else {
|
||||
return view('errors.no-such-record');
|
||||
}
|
||||
} else {
|
||||
$item = new News();
|
||||
$item['order'] = News::count();
|
||||
}
|
||||
|
||||
return view('dashboard.edit-item', [
|
||||
'heading' => 'News',
|
||||
'model' => 'news',
|
||||
'id' => $id,
|
||||
'item' => $item,
|
||||
'imgup' => true,
|
||||
'columns' => [
|
||||
[ 'name' => 'title', 'type' => 'text', 'label' => 'The Title' ],
|
||||
[ 'name' => 'iframe', 'type' => 'text' ],
|
||||
[ 'name' => 'story', 'type' => 'mkd' ],
|
||||
[ 'name' => 'order', 'type' => 'hidden' ]
|
||||
]
|
||||
]);
|
||||
}
|
||||
```
|
||||
|
||||
* `heading`: The title that will appear for this page
|
||||
* `model`: The model that will be accessed on this page
|
||||
* `id`: Always set this to `$id`
|
||||
* `item`: Always set this to `$item`
|
||||
* `imgup`: Set this to `true` to enable image upload, otherwise set to `false`
|
||||
* `help_text`: An optional value that will add a box containing help text above the form if set
|
||||
* `columns`: An array containing a set of arrays where:
|
||||
* `name` is the name of the column to be edited
|
||||
* `type` is the type of column (details below)
|
||||
* `label` is an optional value that overrides the visible column name
|
||||
|
||||
###### Editable Column Types
|
||||
|
||||
The following is a list of possible `types` in the `columns` array for Editable Items:
|
||||
|
||||
* `text`: Text input field for text data
|
||||
* `mkd`: Markdown editor for text data containing markdown
|
||||
* `date`: Date and time selection tool for date/time data
|
||||
* `hidden`: Fields that will contain values to pass to the update function but won't appear on the page (this must be used for the sort column)
|
||||
|
||||
#### Edit Item Functionality
|
||||
|
||||
Editable models must have an entry in the switch statement of the `postEdit` function to make create and edit functionality work:
|
||||
|
||||
```php
|
||||
switch ($request['model']) {
|
||||
case 'shows':
|
||||
$item = $id == 'new' ? new Shows : Shows::find($id);
|
||||
break;
|
||||
case 'news':
|
||||
$item = $id == 'new' ? new News : News::find($id);
|
||||
break;
|
||||
default:
|
||||
return 'model-access-fail';
|
||||
}
|
||||
```
|
||||
|
||||
#### Additional Requirement for Sortable Models
|
||||
|
||||
Sortable models must have an entry in the switch statement of the `postReorder` function to make sorting functionality work:
|
||||
|
||||
```php
|
||||
switch ($request['model']) {
|
||||
case 'news':
|
||||
$items = new News();
|
||||
break;
|
||||
default:
|
||||
return 'model-access-fail';
|
||||
}
|
||||
```
|
||||
|
||||
#### Additional Requirements for Image Upload
|
||||
|
||||
If the value of `imgup` has been set to `true`, ensure `public/uploads/model_name` exists (where `model_name` is the name of the given model) and contains a `.gitkeep` that exists in version control.
|
||||
|
||||
By default, uploaded images are saved in JPEG format with the value of the `id` column of the respective row as its name and `.jpg` as its file extension.
|
||||
|
||||
When a row is deleted, its respective image will be deleted as well if it exists.
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
// run once the document is ready
|
||||
$(document).ready(function() {
|
||||
// initialize the contact form
|
||||
if ($('#contact-form').length)
|
||||
contactFormInit();
|
||||
switch (SiteVars.page) {
|
||||
case '':
|
||||
subscriptionFormInit();
|
||||
break;
|
||||
case 'contact':
|
||||
contactFormInit();
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// contact page functionality
|
||||
// contact form functionality
|
||||
function contactFormInit() {
|
||||
var $form = $('#contact-form'),
|
||||
$input = $form.find(':input'),
|
||||
$notify = $('#notification'),
|
||||
contact = {},
|
||||
submitting = false;
|
||||
|
@ -16,6 +17,7 @@ function contactFormInit() {
|
|||
|
||||
$('#submit').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
var $submit = $(this);
|
||||
|
||||
if (!submitting) {
|
||||
submitting = true;
|
||||
|
@ -30,6 +32,8 @@ function contactFormInit() {
|
|||
$notify.removeClass('visible');
|
||||
|
||||
if (response === 'success') {
|
||||
$input.attr('disabled', true);
|
||||
$submit.addClass('disabled');
|
||||
$notify.text('Thanks for your message!').addClass('success').addClass('visible');
|
||||
} else {
|
||||
var responseJSON = response.responseJSON,
|
||||
|
|
415
resources/assets/js/dashboard.js
Normal file
415
resources/assets/js/dashboard.js
Normal file
|
@ -0,0 +1,415 @@
|
|||
// declare a reverse function for jquery
|
||||
jQuery.fn.reverse = [].reverse;
|
||||
|
||||
// show the confirmation modal and run the supplied command if confirm is pressed
|
||||
function askConfirmation(message, command) {
|
||||
var $confirmationModal = $('#confirmation-modal'),
|
||||
$heading = $confirmationModal.find('.panel-heading'),
|
||||
$cancelButton = $confirmationModal.find('.btn.cancel-button'),
|
||||
$confirmButton = $confirmationModal.find('.btn.confirm-button'),
|
||||
fadeTime = 250;
|
||||
|
||||
// close the confirmation modal and unbind its events
|
||||
var closeConfirmationModal = function() {
|
||||
// unbind events
|
||||
$(document).off('keyup', escapeModal);
|
||||
$cancelButton.off('click', closeConfirmationModal);
|
||||
$confirmButton.off('click', confirmModal);
|
||||
|
||||
// clear the heading
|
||||
$heading.empty();
|
||||
|
||||
// hide the modal
|
||||
$confirmationModal.css({ opacity: 0 });
|
||||
setTimeout(function() { $confirmationModal.css({ visibility: 'hidden' }); }, fadeTime);
|
||||
};
|
||||
|
||||
// close the modal if the escape button is pressed
|
||||
var escapeModal = function(e) {
|
||||
if (e.keyCode == 27)
|
||||
closeConfirmationModal();
|
||||
};
|
||||
|
||||
// functionality to run when clicking the confirm button
|
||||
var confirmModal = function() {
|
||||
command();
|
||||
closeConfirmationModal();
|
||||
};
|
||||
|
||||
// hide the modal when the cancel button is pressed
|
||||
$cancelButton.on('click', closeConfirmationModal);
|
||||
|
||||
// hide the modal when the escape key is pressed
|
||||
$(document).on('keyup', escapeModal);
|
||||
|
||||
// run the command and hide the modal when the confirm button is pressed
|
||||
$confirmButton.on('click', confirmModal);
|
||||
|
||||
// set the heading with the supplied message
|
||||
$heading.text(message);
|
||||
|
||||
// show the confirmation modal
|
||||
$confirmationModal.css({
|
||||
visibility: 'visible',
|
||||
opacity: 1
|
||||
});
|
||||
}
|
||||
|
||||
// show the alert modal and display the provided message until accept is pressed
|
||||
function showAlert(message, command) {
|
||||
var $alertModal = $('#alert-modal'),
|
||||
$message = $alertModal.find('.message'),
|
||||
$acceptButton = $alertModal.find('.btn.accept-button'),
|
||||
fadeTime = 250;
|
||||
|
||||
// close the alert modal and unbind its events
|
||||
var closeAlertModal = function() {
|
||||
// unbind events
|
||||
$(document).off('keyup', escapeModal);
|
||||
$acceptButton.off('click', closeAlertModal);
|
||||
|
||||
// clear the message
|
||||
$message.empty();
|
||||
|
||||
// hide the modal
|
||||
$alertModal.css({ opacity: 0 });
|
||||
setTimeout(function() { $alertModal.css({ visibility: 'hidden' }); }, fadeTime);
|
||||
|
||||
// if a command was passed run it now
|
||||
if (command !== undefined)
|
||||
command();
|
||||
};
|
||||
|
||||
// close the modal if the escape button is pressed
|
||||
var escapeModal = function(e) {
|
||||
if (e.keyCode == 27)
|
||||
closeAlertModal();
|
||||
};
|
||||
|
||||
// hide the modal when the escape key is pressed
|
||||
$(document).on('keyup', escapeModal);
|
||||
|
||||
// hide the modal when the accept button is pressed
|
||||
$acceptButton.on('click', closeAlertModal);
|
||||
|
||||
// set the message with the supplied message
|
||||
$message.text(message);
|
||||
|
||||
// show the alert modal
|
||||
$alertModal.css({
|
||||
visibility: 'visible',
|
||||
opacity: 1
|
||||
});
|
||||
}
|
||||
|
||||
// initialize edit list functionality
|
||||
function editListInit() {
|
||||
var editList = document.getElementById('edit-list'),
|
||||
$editList = $(editList),
|
||||
model = $editList.data('model');
|
||||
|
||||
// initialize new button functionality
|
||||
var newButtonInit = function() {
|
||||
var $newButton = $('.btn.new-button');
|
||||
|
||||
$newButton.on('click', function() {
|
||||
window.location.href = '/dashboard/' + model + '-edit/new';
|
||||
});
|
||||
};
|
||||
|
||||
// initialize edit button functionality
|
||||
var editButtonInit = function() {
|
||||
var $editButtons = $('.btn.edit-button');
|
||||
|
||||
$editButtons.on('click', function() {
|
||||
var $this = $(this),
|
||||
$listItem = $this.closest('.list-group-item'),
|
||||
itemId = $listItem.data('id');
|
||||
|
||||
// go to the edit page
|
||||
window.location.href = '/dashboard/' + model + '-edit/' + itemId;
|
||||
});
|
||||
};
|
||||
|
||||
// initialize delete button functionality
|
||||
var deleteButtonInit = function() {
|
||||
var $deleteButtons = $('.btn.delete-button');
|
||||
|
||||
$deleteButtons.on('click', function() {
|
||||
var $this = $(this),
|
||||
$listItem = $this.closest('.list-group-item'),
|
||||
itemId = $listItem.data('id');
|
||||
|
||||
askConfirmation('Are you sure you want to delete this?', function() {
|
||||
$.ajax({
|
||||
type: 'DELETE',
|
||||
url: '/dashboard/delete',
|
||||
data: {
|
||||
model: model,
|
||||
id: itemId,
|
||||
_token: $('#token').val()
|
||||
}
|
||||
}).always(function(response) {
|
||||
if (response === 'success') {
|
||||
$listItem.slideUp(150, function() { $listItem.remove(); });
|
||||
} else {
|
||||
showAlert('ERROR: Failed to delete record');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// initialize sort functionality if data-sort is set
|
||||
var sortRowInit = function() {
|
||||
if ($editList.attr('data-sort')) {
|
||||
var sortCol = $editList.data('sort'),
|
||||
sortOrder = {};
|
||||
|
||||
var sortable = Sortable.create(editList, {
|
||||
handle: '.sort-icon',
|
||||
onUpdate: function() {
|
||||
// update the sortOrder object based on the updated order
|
||||
$editList.find('.list-group-item').reverse().each(function(index) {
|
||||
var thisId = $(this).data('id');
|
||||
sortOrder[thisId] = index;
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/dashboard/reorder',
|
||||
data: {
|
||||
model: model,
|
||||
order: sortOrder,
|
||||
column: sortCol,
|
||||
_token: $('#token').val()
|
||||
}
|
||||
}).always(function(response) {
|
||||
if (response !== 'success') {
|
||||
showAlert('ERROR: Sorting failed', function() {
|
||||
document.location.reload(true);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
newButtonInit();
|
||||
editButtonInit();
|
||||
deleteButtonInit();
|
||||
sortRowInit();
|
||||
}
|
||||
|
||||
function editItemInit() {
|
||||
var $editItem = $('#edit-item'),
|
||||
$submit = $('#submit'),
|
||||
$backButton = $('#back'),
|
||||
$textInputs = $('.text-input'),
|
||||
$dateTimePickers = $('.date-time-picker'),
|
||||
$mkdEditors = $('.mkd-editor'),
|
||||
$imgUpload = $('#image-upload'),
|
||||
$token = $('#_token'),
|
||||
$spinner = $('#loading-modal'),
|
||||
fadeTime = 250,
|
||||
model = $editItem.data('model'),
|
||||
id = $editItem.data('id'),
|
||||
allowTimes = [],
|
||||
simplemde = [],
|
||||
formData = {},
|
||||
submitting = false;
|
||||
|
||||
// show the loading modal
|
||||
var showLoadingModal = function() {
|
||||
$spinner.css({
|
||||
visibility: 'visible',
|
||||
opacity: 1
|
||||
});
|
||||
};
|
||||
|
||||
// hide the loading modal
|
||||
var hideLoadingModal = function() {
|
||||
$spinner.css({ opacity: 0 });
|
||||
setTimeout(function() { $spinner.css({ visibility: 'hidden' }); }, fadeTime);
|
||||
};
|
||||
|
||||
// fill the formData object with data from all the form fields
|
||||
var getFormData = function() {
|
||||
// function to add a column and value to the formData object
|
||||
var addFormData = function(column, value) {
|
||||
// add the value to a key with the column name
|
||||
formData[column] = value;
|
||||
|
||||
// add the column to the array of columns
|
||||
formData.columns.push(column);
|
||||
};
|
||||
|
||||
// reset the formData object
|
||||
formData = {};
|
||||
|
||||
// add the database model row id and _token
|
||||
formData.model = model;
|
||||
formData.id = id;
|
||||
formData._token = $token.val();
|
||||
|
||||
// create an empty array to contain the list of columns
|
||||
formData.columns = [];
|
||||
|
||||
// add values from the contents of text-input class elements
|
||||
$textInputs.each(function() {
|
||||
var $this = $(this),
|
||||
column = $this.attr('id'),
|
||||
value = $this.val();
|
||||
|
||||
addFormData(column, value);
|
||||
});
|
||||
|
||||
// add values from the contents of date-time-picker class elements
|
||||
$dateTimePickers.each(function() {
|
||||
var $this = $(this),
|
||||
column = $this.attr('id'),
|
||||
value = $this.val() + ':00';
|
||||
|
||||
addFormData(column, value);
|
||||
});
|
||||
|
||||
// add values from the contents of the markdown editor for mkd-editor class elements
|
||||
$mkdEditors.each(function() {
|
||||
var $this = $(this),
|
||||
column = $this.attr('id'),
|
||||
value = simplemde[column].value();
|
||||
|
||||
addFormData(column, value);
|
||||
});
|
||||
};
|
||||
|
||||
var uploadImage = function(row_id) {
|
||||
// functionality to run on success
|
||||
var returnSuccess = function() {
|
||||
hideLoadingModal();
|
||||
window.location.href = '/dashboard/' + model;
|
||||
};
|
||||
|
||||
// add the image from the image upload box for image-upload class elements
|
||||
if ($imgUpload.length && $imgUpload.val() !== '') {
|
||||
var file = new FormData();
|
||||
|
||||
// add the file, id and model to the formData variable
|
||||
file.append('file', $imgUpload[0].files[0]);
|
||||
file.append('id', row_id);
|
||||
file.append('model', model);
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/dashboard/image-upload',
|
||||
data: file,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
beforeSend: function(xhr) { xhr.setRequestHeader('X-CSRF-TOKEN', $token.val()); }
|
||||
}).always(function(response) {
|
||||
if (response === 'success') {
|
||||
returnSuccess();
|
||||
} else {
|
||||
hideLoadingModal();
|
||||
showAlert('ERROR: Failed to upload image');
|
||||
submitting = false;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
returnSuccess();
|
||||
}
|
||||
};
|
||||
|
||||
// allow start time selection to start on the hour and every 15 minutes after
|
||||
for (var hours=0; hours<=23; hours++) {
|
||||
for (var minutes=0; minutes<=3; minutes++) {
|
||||
allowTimes.push(hours + ':' + (minutes === 0 ? '00' : minutes * 15));
|
||||
}
|
||||
}
|
||||
|
||||
// enable the datetimepicker for each element with the date-time-picker class
|
||||
$dateTimePickers.each(function() {
|
||||
$(this).datetimepicker({
|
||||
format: 'Y-m-d H:i',
|
||||
allowTimes: allowTimes,
|
||||
step: 15
|
||||
});
|
||||
});
|
||||
|
||||
// enable the markdown editor for each element with the mkd-editor class
|
||||
$mkdEditors.each(function() {
|
||||
var $this = $(this),
|
||||
column = $this.attr('id');
|
||||
|
||||
simplemde[column] = new SimpleMDE({
|
||||
element: this,
|
||||
toolbar: [
|
||||
'bold',
|
||||
'italic',
|
||||
'|',
|
||||
'heading-1',
|
||||
'heading-2',
|
||||
'heading-3',
|
||||
'|',
|
||||
'quote',
|
||||
'unordered-list',
|
||||
'ordered-list',
|
||||
'link'
|
||||
],
|
||||
blockStyles: { italic: '_' },
|
||||
autoDownloadFontAwesome: false,
|
||||
tabSize: 4
|
||||
});
|
||||
|
||||
setTimeout(function() {
|
||||
simplemde[column].value($this.attr('value'));
|
||||
}, 100);
|
||||
});
|
||||
|
||||
// initialize back button
|
||||
$backButton.on('click', function() {
|
||||
if (!submitting) {
|
||||
askConfirmation('Cancel and return to the ' + model + ' list?', function() {
|
||||
window.location.href = '/dashboard/' + model;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// initialize submit button
|
||||
$submit.on('click', function() {
|
||||
if (!submitting) {
|
||||
submitting = true;
|
||||
|
||||
// show the loading modal
|
||||
showLoadingModal();
|
||||
|
||||
// populate the formData object
|
||||
getFormData();
|
||||
|
||||
// submit the update
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/dashboard/edit',
|
||||
data: formData
|
||||
}).always(function(response) {
|
||||
if (/^id:[0-9][0-9]*$/.test(response)) {
|
||||
uploadImage(response.replace(/^id:/, ''));
|
||||
} else {
|
||||
hideLoadingModal();
|
||||
showAlert('ERROR: Failed to update record');
|
||||
submitting = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// run once the document is ready
|
||||
$(document).ready(function() {
|
||||
if ($('#edit-list').length) {
|
||||
editListInit();
|
||||
} else if ($('#edit-item').length) {
|
||||
editItemInit();
|
||||
}
|
||||
});
|
63
resources/assets/js/subscription.js
Normal file
63
resources/assets/js/subscription.js
Normal file
|
@ -0,0 +1,63 @@
|
|||
// subscription form functionality
|
||||
function subscriptionFormInit() {
|
||||
var $form = $('#subscription-form'),
|
||||
$input = $form.find(':input'),
|
||||
$notify = $('#notification'),
|
||||
subscribe = {},
|
||||
submitting = false;
|
||||
|
||||
var getSubscribeData = function() {
|
||||
subscribe = {
|
||||
name: $('#name').val(),
|
||||
email: $('#email').val(),
|
||||
address: $('#address').val(),
|
||||
_token: $('#token').val()
|
||||
};
|
||||
};
|
||||
|
||||
$('#submit').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
var $submit = $(this);
|
||||
|
||||
if (!submitting) {
|
||||
submitting = true;
|
||||
getSubscribeData();
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/subscription-submit',
|
||||
data: subscribe
|
||||
}).always(function(response) {
|
||||
$form.find('.error').removeClass('error');
|
||||
$notify.removeClass('visible').removeClass('error');
|
||||
|
||||
if (response === 'success') {
|
||||
$form.addClass('success');
|
||||
|
||||
setTimeout(function() {
|
||||
$notify.text('Thanks for subscribing!').addClass('success').addClass('visible');
|
||||
$input.fadeOut(150);
|
||||
}, 1000);
|
||||
} else {
|
||||
var responseJSON = response.responseJSON,
|
||||
errors = 0;
|
||||
|
||||
// add the error class to fields that haven't been filled out
|
||||
for (var prop in responseJSON) {
|
||||
if (responseJSON.hasOwnProperty(prop)) {
|
||||
$('#' + prop).addClass('error');
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
// if there are no errors with form fields then there must have been an API error
|
||||
if (errors === 0)
|
||||
$notify.text('An error occurred. Are you already subscribed?').addClass('error').addClass('visible');
|
||||
|
||||
// re-enable submitting
|
||||
submitting = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
7
resources/assets/less/app.less
vendored
7
resources/assets/less/app.less
vendored
|
@ -1,11 +1,8 @@
|
|||
// Core
|
||||
@import "bootstrap";
|
||||
@import "bootstrap/less/bootstrap";
|
||||
@import "var";
|
||||
@import "fonts";
|
||||
|
||||
// Base
|
||||
@import "auth";
|
||||
|
||||
// Supplementary
|
||||
@import "elements/**";
|
||||
@import "pages/**";
|
||||
|
@ -21,6 +18,8 @@ html, body {
|
|||
height: 100%;
|
||||
}
|
||||
|
||||
html.no-scroll { overflow-y: hidden; }
|
||||
|
||||
body {
|
||||
min-width: 300px;
|
||||
margin: 0;
|
||||
|
|
33
resources/assets/less/auth.less
vendored
33
resources/assets/less/auth.less
vendored
|
@ -1,33 +0,0 @@
|
|||
.auth-container {
|
||||
form {
|
||||
margin-top: 50px;
|
||||
padding: 25px 25px 50px 25px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid darken(@c_accent, 5%);
|
||||
background-color: @c_accent;
|
||||
|
||||
.form-field {
|
||||
label {
|
||||
float: left;
|
||||
min-width: 125px;
|
||||
}
|
||||
|
||||
.input {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
margin-bottom: 10px;
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
height: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
position: absolute;
|
||||
right: 41px;
|
||||
bottom: 25px;
|
||||
}
|
||||
}
|
||||
}
|
356
resources/assets/less/dashboard.less
vendored
Normal file
356
resources/assets/less/dashboard.less
vendored
Normal file
|
@ -0,0 +1,356 @@
|
|||
// Core
|
||||
@import "bootstrap/less/bootstrap";
|
||||
@import "font-awesome/less/font-awesome";
|
||||
@import "awesome-bootstrap-checkbox/awesome-bootstrap-checkbox";
|
||||
@import (inline) "datetimepicker/jquery.datetimepicker.css";
|
||||
@import (inline) "simplemde/dist/simplemde.min.css";
|
||||
@import (inline) "SpinKit/css/spinners/11-folding-cube.css";
|
||||
@import "var";
|
||||
@import "fonts";
|
||||
@import "classes";
|
||||
@fa-font-path: "../../fonts";
|
||||
|
||||
* {
|
||||
outline: none !important;
|
||||
.font_sans;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
body { min-width: 350px; }
|
||||
|
||||
nav.navbar {
|
||||
background-color: @c_dashboard_dark;
|
||||
.navbar-brand { font-weight: bold; }
|
||||
|
||||
#spark-navbar-collapse {
|
||||
box-shadow: none;
|
||||
border: none;
|
||||
|
||||
.dropdown {
|
||||
.dropdown-toggle .caret { margin-left: 4px; }
|
||||
|
||||
&.open .dropdown-toggle {
|
||||
background-color: darken(@c_dashboard_dark, 5%);
|
||||
color: @c_dashboard_light;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
top: calc(100% ~"-" 1px);
|
||||
right: -1px;
|
||||
background-color: @c_dashboard_dark;
|
||||
& > li > a:hover, & > li > a:focus { background-color: transparent; }
|
||||
& > li > a { &, &:hover, &:focus { color: #fff; } }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.navbar-brand, .navbar-default .navbar-nav > li > a, .navbar-nav > li > a {
|
||||
&, &:hover, &:focus { color: @c_dashboard_light; }
|
||||
}
|
||||
|
||||
.navbar-toggle {
|
||||
position: relative;
|
||||
bottom: 0px;
|
||||
left: 10px;
|
||||
border: none;
|
||||
&, &:hover, &:focus { background-color: transparent; }
|
||||
|
||||
.icon-bar {
|
||||
width: 27px;
|
||||
height: 4px;
|
||||
background-color: @c_dashboard_light;
|
||||
transition: background-color 100ms;
|
||||
}
|
||||
|
||||
&:hover .icon-bar { background-color: darken(@c_dashboard_dark, 15%); }
|
||||
}
|
||||
}
|
||||
|
||||
.panel-default {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 40px;
|
||||
|
||||
.panel-body {
|
||||
padding-bottom: 0px;
|
||||
background-color: lighten(@c_dashboard_light, 1%);
|
||||
|
||||
.help-text {
|
||||
padding: 5px 10px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid darken(@c_dashboard_dark, 5%);
|
||||
background-color: @c_dashboard_dark;
|
||||
color: @c_text_light;
|
||||
}
|
||||
}
|
||||
|
||||
& > .panel-heading {
|
||||
border-top: 1px solid darken(@c_dashboard_dark, 5%);
|
||||
border-right: 1px solid darken(@c_dashboard_dark, 5%);
|
||||
border-left: 1px solid darken(@c_dashboard_dark, 5%);
|
||||
background-color: @c_dashboard_dark;
|
||||
color: @c_dashboard_light;
|
||||
font-weight: bold;
|
||||
|
||||
.btn {
|
||||
float: right;
|
||||
position: relative;
|
||||
bottom: 3px;
|
||||
min-width: 70px;
|
||||
height: 26px;
|
||||
padding-top: 1px;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: @c_text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.form-control {
|
||||
&:focus {
|
||||
border-color: @c_dashboard_dark;
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px fade(@c_dashboard_dark, 60%);
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
border-color: darken(@c_dashboard_dark, 5%);
|
||||
background-color: @c_dashboard_dark;
|
||||
transition: background-color 100ms;
|
||||
&:hover { background-color: darken(@c_dashboard_dark, 5%); }
|
||||
&:focus { background-color: lighten(@c_dashboard_dark, 5%); }
|
||||
|
||||
&.btn-warning {
|
||||
border-color: darken(@c_dashboard_edit, 10%);
|
||||
background-color: @c_dashboard_edit;
|
||||
&:hover { background-color: darken(@c_dashboard_edit, 5%); }
|
||||
&:focus { background-color: lighten(@c_dashboard_edit, 5%); }
|
||||
}
|
||||
|
||||
&.btn-danger {
|
||||
border-color: darken(@c_dashboard_delete, 10%);
|
||||
background-color: @c_dashboard_delete;
|
||||
&:hover { background-color: darken(@c_dashboard_delete, 5%); }
|
||||
&:focus { background-color: lighten(@c_dashboard_delete, 5%); }
|
||||
}
|
||||
|
||||
&.btn-default {
|
||||
border-color: darken(@c_dashboard_light, 10%);
|
||||
background-color: @c_dashboard_light;
|
||||
color: @c_text;
|
||||
&:hover { background-color: darken(@c_dashboard_light, 5%); }
|
||||
&:focus { background-color: lighten(@c_dashboard_light, 5%); }
|
||||
}
|
||||
|
||||
&.btn-link { color: @c_dashboard_light; }
|
||||
&, &:hover, &:focus { text-decoration: none; }
|
||||
}
|
||||
|
||||
.table {
|
||||
& > thead > tr > th { border-bottom: 1px solid #666; }
|
||||
|
||||
@media (max-width: (@screen-sm - 1)) {
|
||||
tr.heading-row { display: none; }
|
||||
tr:not(:first-child) { border-top: 1px solid #ddd; }
|
||||
|
||||
& > tbody > tr > td {
|
||||
&:first-child { padding-top: 20px; }
|
||||
&:last-child { padding-bottom: 20px; }
|
||||
}
|
||||
|
||||
& > tbody > tr:first-child > td:first-child { padding-top: 0px; }
|
||||
& > tbody > tr:last-child > td:last-child { padding-bottom: 0px; }
|
||||
|
||||
& > tbody > tr > td {
|
||||
display: block;
|
||||
border-top: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: @screen-sm) {
|
||||
& > tbody > tr > td { padding: 20px 8px; }
|
||||
& > tbody > tr:last-child > td { padding-bottom: 0px; }
|
||||
.mobile-heading { display: none; }
|
||||
}
|
||||
}
|
||||
|
||||
.list-group {
|
||||
margin-bottom: 0px;
|
||||
padding-bottom: 15px;
|
||||
|
||||
&.linked-list {
|
||||
margin-bottom: 0px;
|
||||
|
||||
.list-group-item {
|
||||
padding: 0px;
|
||||
|
||||
a {
|
||||
display: block;
|
||||
padding: 10px 15px;
|
||||
color: @c_dashboard_dark;
|
||||
background-color: #fff;
|
||||
transition: background-color 100ms, color 100ms;
|
||||
&:focus, &:hover { text-decoration: none; }
|
||||
|
||||
&:hover {
|
||||
color: @c_dashboard_light;
|
||||
background-color: @c_dashboard_dark;
|
||||
}
|
||||
}
|
||||
|
||||
&:first-child a {
|
||||
border-top-right-radius: 4px;
|
||||
border-top-left-radius: 4px;
|
||||
}
|
||||
|
||||
&:last-child a {
|
||||
border-bottom-right-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.edit-list {
|
||||
.list-group-item {
|
||||
position: relative;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
|
||||
.sort-icon {
|
||||
display: inline-block;
|
||||
margin-right: 10px;
|
||||
cursor: grab;
|
||||
cursor: -webkit-grabbing;
|
||||
}
|
||||
|
||||
.title-column {
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px;
|
||||
padding-left: 0px;
|
||||
}
|
||||
|
||||
.button-column {
|
||||
text-align: right;
|
||||
padding-right: 0px;
|
||||
padding-left: 0px;
|
||||
|
||||
.btn {
|
||||
min-width: 70px;
|
||||
height: 26px;
|
||||
margin: 3px;
|
||||
padding-top: 1px;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.edit-item {
|
||||
margin-top: 10px;
|
||||
.CodeMirror, .CodeMirror-scroll { min-height: 100px; }
|
||||
.date-time-picker { cursor: pointer; }
|
||||
|
||||
label {
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
input {
|
||||
display: block;
|
||||
width: 100%;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.current-image {
|
||||
width: 125px;
|
||||
height: 125px;
|
||||
background-size: contain;
|
||||
background-position: left center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.back-button { float: left; }
|
||||
.submit-button { float: right; }
|
||||
|
||||
.back-button, .submit-button {
|
||||
margin: 25px 15px 15px 15px;
|
||||
|
||||
@media (max-width: (@screen-sm - 1)) {
|
||||
float: none;
|
||||
width: calc(100% ~"-" 30px);
|
||||
&:first-child { margin: 25px 15px 5px 15px; }
|
||||
&:last-child { margin: 5px 15px 25px 15px; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#loading-modal {
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: fade(lighten(@c_dashboard_light, 1%), 40%);
|
||||
transition: opacity 250ms;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
z-index: 1000;
|
||||
|
||||
.spinner-container {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%) translateY(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
.modal {
|
||||
display: table;
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: fade(lighten(@c_dashboard_light, 1%), 40%);
|
||||
transition: opacity 250ms;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
z-index: 1000;
|
||||
|
||||
.modal-container {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
.panel { margin: 0px; }
|
||||
|
||||
.btn {
|
||||
display: inline-block;
|
||||
margin: 20px 15px;
|
||||
}
|
||||
}
|
||||
|
||||
&#alert-modal {
|
||||
.modal-container {
|
||||
.panel { position: relative; }
|
||||
|
||||
.message {
|
||||
min-height: 50px;
|
||||
padding: 15px 106px 10px 20px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.btn {
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
8
resources/assets/less/elements/footer.less
vendored
8
resources/assets/less/elements/footer.less
vendored
|
@ -1,3 +1,9 @@
|
|||
footer {
|
||||
|
||||
width: 100%;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
padding-left: 10px;
|
||||
background-color: #000;
|
||||
color: @c_text_light;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
|
102
resources/assets/less/elements/nav.less
vendored
102
resources/assets/less/elements/nav.less
vendored
|
@ -1,18 +1,55 @@
|
|||
nav.navbar {
|
||||
background-color: @c_base;
|
||||
height: @nav_height;
|
||||
margin-bottom: 0px;
|
||||
padding-right: 10px;
|
||||
background: linear-gradient(to right, transparent 0%, fade(@c_base, 40%) 25%, fade(@c_base, 50%) 50%, @c_base 100%);
|
||||
border: none;
|
||||
border-radius: 0px;
|
||||
z-index: 1;
|
||||
|
||||
@media (max-width: @grid-float-breakpoint-max) {
|
||||
height: @mobile_nav_height;
|
||||
background: fade(@c_base, 55%);
|
||||
}
|
||||
|
||||
.navbar-logo {
|
||||
top: 25px;
|
||||
left: 15px;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
position: fixed;
|
||||
top: 45px;
|
||||
left: 63px;
|
||||
width: 145px;
|
||||
height: 145px;
|
||||
background-image: url('/img/logo.png');
|
||||
background-size: contain;
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
cursor: pointer;
|
||||
transition: transform 200ms;
|
||||
&:hover { transform: scale(1.03); }
|
||||
|
||||
&:active {
|
||||
transition: transform 100ms;
|
||||
transform: scale(1.01);
|
||||
}
|
||||
|
||||
@media (max-width: @grid-float-breakpoint-max) {
|
||||
top: 5px;
|
||||
left: 10px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
@media (min-width: @grid-float-breakpoint) {
|
||||
@logoAnimSpeed: 400ms;
|
||||
transition: transform 200ms, top @logoAnimSpeed, left @logoAnimSpeed, width @logoAnimSpeed, height @logoAnimSpeed;
|
||||
&:active { transition: transform 100ms, top @logoAnimSpeed, left @logoAnimSpeed, width @logoAnimSpeed, height @logoAnimSpeed; }
|
||||
|
||||
&.scaled {
|
||||
top: 10px;
|
||||
left: 15px;
|
||||
width: @nav_height - 20;
|
||||
height: @nav_height - 20;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#navbar {
|
||||
|
@ -22,20 +59,69 @@ nav.navbar {
|
|||
ul.nav {
|
||||
li {
|
||||
a {
|
||||
padding: 0px 15px;
|
||||
user-select: none;
|
||||
color: @c_text_light;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
text-transform: uppercase;
|
||||
font-size: 36px;
|
||||
font-weight: 500;
|
||||
font-stretch: ultra-condensed;
|
||||
line-height: @nav_height;
|
||||
transition: color 100ms;
|
||||
@media (max-width: 1250px) { font-size: 28px; }
|
||||
@media (max-width: 1050px) { font-size: 24px; }
|
||||
|
||||
&:after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
bottom: calc(50% ~"-" 0.8em);
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: calc(100% ~"-" 20px);
|
||||
height: 3px;
|
||||
background-color: @c_text_light;
|
||||
opacity: 0;
|
||||
transition: opacity 200ms;
|
||||
@media (max-width: @grid-float-breakpoint-max) { bottom: 0px; }
|
||||
}
|
||||
}
|
||||
|
||||
&:hover a { color: @c_text; }
|
||||
&.active a { color: @c_text; }
|
||||
&.active a, &.active:hover a, &:hover a, &:focus a { background-color: transparent; }
|
||||
&:hover a { color: darken(@c_text_light, 25%); }
|
||||
&.active a:after { opacity: 1; }
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: @grid-float-breakpoint-max) {
|
||||
position: relative;
|
||||
bottom: 4px;
|
||||
width: 100vw;
|
||||
padding-bottom: 5px;
|
||||
background-color: fade(@c_base, 55%);
|
||||
|
||||
ul.nav li a {
|
||||
line-height: 40px;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.navbar-toggle {
|
||||
position: relative;
|
||||
bottom: 2px;
|
||||
left: 20px;
|
||||
border: none;
|
||||
&, &:hover, &:focus { background-color: transparent; }
|
||||
|
||||
.icon-bar {
|
||||
width: 27px;
|
||||
height: 4px;
|
||||
background-color: @c_text_light;
|
||||
transition: background-color 150ms;
|
||||
}
|
||||
|
||||
&:hover .icon-bar { background-color: darken(@c_text_light, 25%); }
|
||||
}
|
||||
}
|
||||
|
|
53
resources/assets/less/pages/contact.less
vendored
Normal file
53
resources/assets/less/pages/contact.less
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
body.contact {
|
||||
#contact-form {
|
||||
@trans-speed: 100ms;
|
||||
margin-top: 35px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
input, textarea {
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
padding: 5px 10px;
|
||||
font-size: 14px;
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
border: 2px solid fade(@c_text, 25%);
|
||||
transition: border @trans-speed;
|
||||
&:focus { border: 2px solid fade(@c_base, 60%); }
|
||||
&.error { border: 2px solid @c_error; }
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: none;
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
#submit {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
color: @c_text_light;
|
||||
background-color: lighten(@c_base, 5%);
|
||||
transition: background-color @trans-speed;
|
||||
&:hover { background-color: @c_base; }
|
||||
&.disabled { background-color: @c_base; }
|
||||
}
|
||||
|
||||
#notification {
|
||||
margin: 0px auto 15px auto;
|
||||
padding: 5px 10px;
|
||||
color: @c_text_light;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
opacity: 0;
|
||||
background-color: lighten(@c_error, 15%);
|
||||
transition: opacity @trans-speed;
|
||||
span { font-weight: bold; }
|
||||
&.visible { opacity: 1; }
|
||||
|
||||
&.success {
|
||||
background-color: transparent;
|
||||
color: @c_text;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
20
resources/assets/less/var.less
vendored
20
resources/assets/less/var.less
vendored
|
@ -1,3 +1,12 @@
|
|||
/*
|
||||
|
|
||||
| Overrides
|
||||
|
|
||||
*/
|
||||
|
||||
@grid-float-breakpoint: @screen-sm;
|
||||
@grid-float-breakpoint-max: (@grid-float-breakpoint - 1);
|
||||
|
||||
/*
|
||||
|
|
||||
| Custom Variables
|
||||
|
@ -8,5 +17,14 @@
|
|||
@c_text: #111; // text
|
||||
@c_text_light: #fff; // light text
|
||||
@c_base: #0088cc; // base
|
||||
@c_accent: #f5f5f5; // accent
|
||||
@c_accent: #000; // accent
|
||||
@c_error: #ff0000; // error
|
||||
|
||||
@c_dashboard_dark: #3e6087;
|
||||
@c_dashboard_light: #f1f1f1;
|
||||
@c_dashboard_edit: #87823e;
|
||||
@c_dashboard_delete: #87483e;
|
||||
|
||||
// Sizes
|
||||
@nav_height: 96px;
|
||||
@mobile_nav_height: 50px;
|
||||
|
|
49
resources/assets/less/website/contact.less
vendored
49
resources/assets/less/website/contact.less
vendored
|
@ -1,49 +0,0 @@
|
|||
#contact-form {
|
||||
margin-top: 35px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
input, textarea {
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
padding: 5px 10px;
|
||||
font-size: 14px;
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
border: 2px solid fade(@c_text, 25%);
|
||||
transition: border 100ms;
|
||||
&:focus { border: 2px solid fade(@c_base, 60%); }
|
||||
&.error { border: 2px solid @c_error; }
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: none;
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
#submit {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
color: @c_text_light;
|
||||
background-color: lighten(@c_base, 5%);
|
||||
transition: background-color 100ms;
|
||||
&:hover { background-color: @c_base; }
|
||||
}
|
||||
|
||||
#notification {
|
||||
margin: 0px auto 15px auto;
|
||||
padding: 5px 10px;
|
||||
color: @c_text_light;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
opacity: 0;
|
||||
background-color: lighten(@c_error, 15%);
|
||||
transition: opacity 100ms;
|
||||
&.visible { opacity: 1; }
|
||||
span { font-weight: bold; }
|
||||
|
||||
&.success {
|
||||
background-color: transparent;
|
||||
color: @c_text;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
@extends('base')
|
||||
|
||||
@section('page-content')
|
||||
<div class="container auth-container">
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-md-6 col-md-offset-3">
|
||||
@yield('auth-form')
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
1
resources/views/auth/emails/password.blade.php
Normal file
1
resources/views/auth/emails/password.blade.php
Normal file
|
@ -0,0 +1 @@
|
|||
Click here to reset your password: {{ url('password/reset', $token).'?email='.urlencode($user->getEmailForPasswordReset()) }}
|
|
@ -1,24 +1,65 @@
|
|||
@extends('auth')
|
||||
@extends('layouts.dashboard')
|
||||
|
||||
@section('auth-form')
|
||||
<form method="POST" action="/auth/login">
|
||||
{!! csrf_field() !!}
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-md-offset-2">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Login</div>
|
||||
<div class="panel-body">
|
||||
<form class="form-horizontal" role="form" method="POST" action="{{ url('/login') }}">
|
||||
{!! csrf_field() !!}
|
||||
|
||||
<div class="form-field">
|
||||
<label for="email">Email</label>
|
||||
<div class="input"><input type="email" name="email" value="{{ old('email') }}" /></div>
|
||||
<div class="form-group{{ $errors->has('email') ? ' has-error' : '' }}">
|
||||
<label class="col-md-4 control-label">E-Mail Address</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input type="email" class="form-control" name="email" value="{{ old('email') }}" />
|
||||
|
||||
@if ($errors->has('email'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('email') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}">
|
||||
<label class="col-md-4 control-label">Password</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input type="password" class="form-control" name="password" />
|
||||
|
||||
@if ($errors->has('password'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('password') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-md-6 col-md-offset-4">
|
||||
<div class="checkbox">
|
||||
<input type="checkbox" class="styled" id="remember" name="remember" />
|
||||
<label>Remember Me</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-md-6 col-md-offset-4">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
Login
|
||||
</button>
|
||||
|
||||
<a class="btn btn-link" href="{{ url('/password/reset') }}">Forgot Your Password?</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-field">
|
||||
<label for="password">Password</label>
|
||||
<div class="input"><input type="password" name="password" id="password" /></div>
|
||||
</div>
|
||||
|
||||
<div class="form-field">
|
||||
<label for="remember">Remember Me</label>
|
||||
<input type="checkbox" name="remember" />
|
||||
</div>
|
||||
|
||||
<button type="submit">Login</button>
|
||||
</form>
|
||||
</div>
|
||||
@endsection
|
||||
|
|
46
resources/views/auth/passwords/email.blade.php
Normal file
46
resources/views/auth/passwords/email.blade.php
Normal file
|
@ -0,0 +1,46 @@
|
|||
@extends('layouts.dashboard')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-md-offset-2">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Reset Password</div>
|
||||
<div class="panel-body">
|
||||
@if (session('status'))
|
||||
<div class="alert alert-success">
|
||||
{{ session('status') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form class="form-horizontal" role="form" method="POST" action="{{ url('/password/email') }}">
|
||||
{!! csrf_field() !!}
|
||||
|
||||
<div class="form-group{{ $errors->has('email') ? ' has-error' : '' }}">
|
||||
<label class="col-md-4 control-label">E-Mail Address</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input type="email" class="form-control" name="email" value="{{ old('email') }}" />
|
||||
|
||||
@if ($errors->has('email'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('email') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-md-6 col-md-offset-4">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
Send Password Reset Link
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
70
resources/views/auth/passwords/reset.blade.php
Normal file
70
resources/views/auth/passwords/reset.blade.php
Normal file
|
@ -0,0 +1,70 @@
|
|||
@extends('layouts.dashboard')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-md-offset-2">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Reset Password</div>
|
||||
|
||||
<div class="panel-body">
|
||||
<form class="form-horizontal" role="form" method="POST" action="{{ url('/password/reset') }}">
|
||||
{!! csrf_field() !!}
|
||||
|
||||
<input type="hidden" name="token" value="{{ $token }}" />
|
||||
|
||||
<div class="form-group{{ $errors->has('email') ? ' has-error' : '' }}">
|
||||
<label class="col-md-4 control-label">E-Mail Address</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input type="email" class="form-control" name="email" value="{{ $email or old('email') }}" />
|
||||
|
||||
@if ($errors->has('email'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('email') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}">
|
||||
<label class="col-md-4 control-label">Password</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input type="password" class="form-control" name="password" />
|
||||
|
||||
@if ($errors->has('password'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('password') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group{{ $errors->has('password_confirmation') ? ' has-error' : '' }}">
|
||||
<label class="col-md-4 control-label">Confirm Password</label>
|
||||
<div class="col-md-6">
|
||||
<input type="password" class="form-control" name="password_confirmation" />
|
||||
|
||||
@if ($errors->has('password_confirmation'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('password_confirmation') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-md-6 col-md-offset-4">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
Reset Password
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
|
@ -1,29 +1,82 @@
|
|||
@extends('auth')
|
||||
@extends('layouts.dashboard')
|
||||
|
||||
@section('auth-form')
|
||||
<form method="POST" action="/auth/register">
|
||||
{!! csrf_field() !!}
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-md-offset-2">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Register</div>
|
||||
<div class="panel-body">
|
||||
<form class="form-horizontal" role="form" method="POST" action="{{ url('/register') }}">
|
||||
{!! csrf_field() !!}
|
||||
|
||||
<div class="form-field">
|
||||
<label for="name">Name</label>
|
||||
<div class="input"><input type="text" name="name" value="{{ old('name') }}" /></div>
|
||||
<div class="form-group{{ $errors->has('name') ? ' has-error' : '' }}">
|
||||
<label class="col-md-4 control-label">Name</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input type="text" class="form-control" name="name" value="{{ old('name') }}" />
|
||||
|
||||
@if ($errors->has('name'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('name') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group{{ $errors->has('email') ? ' has-error' : '' }}">
|
||||
<label class="col-md-4 control-label">E-Mail Address</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input type="email" class="form-control" name="email" value="{{ old('email') }}" />
|
||||
|
||||
@if ($errors->has('email'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('email') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}">
|
||||
<label class="col-md-4 control-label">Password</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input type="password" class="form-control" name="password" />
|
||||
|
||||
@if ($errors->has('password'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('password') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group{{ $errors->has('password_confirmation') ? ' has-error' : '' }}">
|
||||
<label class="col-md-4 control-label">Confirm Password</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input type="password" class="form-control" name="password_confirmation" />
|
||||
|
||||
@if ($errors->has('password_confirmation'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('password_confirmation') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-md-6 col-md-offset-4">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
Register
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-field">
|
||||
<label for="email">Email</label>
|
||||
<div class="input"><input type="email" name="email" value="{{ old('email') }}" /></div>
|
||||
</div>
|
||||
|
||||
<div class="form-field">
|
||||
<label for="password">Password</label>
|
||||
<div class="input"><input type="password" name="password" id="password" /></div>
|
||||
</div>
|
||||
|
||||
<div class="form-field">
|
||||
<label for="password_confirmation">Confirm</label>
|
||||
<div class="input"><input type="password" name="password_confirmation" id="password_confirmation" /></div>
|
||||
</div>
|
||||
|
||||
<button type="submit">Register</button>
|
||||
</form>
|
||||
</div>
|
||||
@endsection
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<p>Name: {{ $contact['name'] }}</p>
|
||||
<p>Email: {{ $contact['email'] }}</p>
|
||||
<p>{{ $contact['message'] }}</p>
|
||||
</body>
|
||||
</html>
|
52
resources/views/dashboard/core.blade.php
Normal file
52
resources/views/dashboard/core.blade.php
Normal file
|
@ -0,0 +1,52 @@
|
|||
@extends('layouts.dashboard')
|
||||
|
||||
@section('content')
|
||||
<div class="container spark-screen">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
{{ $heading }}
|
||||
@yield('dashboard-heading')
|
||||
</div>
|
||||
|
||||
<div class="panel-body">
|
||||
@yield('dashboard-body')
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="confirmation-modal" class="modal">
|
||||
<div class="modal-container">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-6 col-sm-offset-3 col-md-4 col-md-offset-4">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"></div>
|
||||
<button type="button" class="cancel-button btn btn-primary">Cancel</button>
|
||||
<button type="button" class="confirm-button btn btn-danger">Confirm</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="alert-modal" class="modal">
|
||||
<div class="modal-container">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-6 col-sm-offset-3 col-md-4 col-md-offset-4">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">ALERT</div>
|
||||
<div class="message"></div>
|
||||
<button type="button" class="accept-button btn btn-primary">OK</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
78
resources/views/dashboard/edit-item.blade.php
Normal file
78
resources/views/dashboard/edit-item.blade.php
Normal file
|
@ -0,0 +1,78 @@
|
|||
@extends('dashboard.core')
|
||||
|
||||
@section('dashboard-body')
|
||||
@if(!empty($help_text))
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<div class="help-text">
|
||||
{!! $help_text !!}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form id="edit-item" class="edit-item" data-id="{{ $id }}" data-model="{{ $model }}">
|
||||
<input type="hidden" name="_token" id="_token" value="{{ csrf_token() }}" />
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
@foreach($columns as $column)
|
||||
@set('value', empty($item->$column['name']) ? '' : $item->$column['name'])
|
||||
|
||||
@if($column['type'] == 'hidden')
|
||||
<input class="text-input" type="hidden" name="{{ $column['name'] }}" id="{{ $column['name'] }}" value="{{ $value }}" />
|
||||
@else
|
||||
<div class="col-xs-12 col-md-2">
|
||||
<label for="{{ $column['name'] }}">{{ empty($column['label']) ? ucfirst($column['name']) : $column['label'] }}:</label>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-md-10">
|
||||
@if($column['type'] == 'text')
|
||||
<input class="text-input" type="text" name="{{ $column['name'] }}" id="{{ $column['name'] }}" value="{{ $value }}" />
|
||||
@elseif($column['type'] == 'date')
|
||||
<input class="date-time-picker" type="text" name="{{ $column['name'] }}" id="{{ $column['name'] }}" value="{{ preg_replace('/:[0-9][0-9]$/', '', $value) }}" />
|
||||
@elseif($column['type'] == 'mkd')
|
||||
<textarea class="mkd-editor" name="{{ $column['name'] }}" id="{{ $column['name'] }}" value="{{ $value }}"></textarea>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
@if(!empty($imgup) && $imgup)
|
||||
<div class="col-xs-12 col-md-2">
|
||||
<label for="{{ $column['name'] }}">Picture:</label>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-md-10">
|
||||
<input class="image-upload" type="file" name="image-upload" id="image-upload" />
|
||||
|
||||
@set('current_image', "/uploads/$model/$id.jpg")
|
||||
@if(file_exists(base_path() . '/public' . $current_image))
|
||||
<div class="current-image" style="background-image: url({{ $current_image }});" />
|
||||
@else
|
||||
<div>(No Image Set)</div>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<button id="back" type="button" class="back-button btn btn-default">Back</button>
|
||||
<button id="submit" type="button" class="submit-button btn btn-primary">{{ $id == 'new' ? 'Create' : 'Update' }} {{ $heading }} Item</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div id="loading-modal">
|
||||
<div class="spinner-container">
|
||||
<div class="sk-folding-cube">
|
||||
<div class="sk-cube1 sk-cube"></div>
|
||||
<div class="sk-cube2 sk-cube"></div>
|
||||
<div class="sk-cube4 sk-cube"></div>
|
||||
<div class="sk-cube3 sk-cube"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
32
resources/views/dashboard/edit-list.blade.php
Normal file
32
resources/views/dashboard/edit-list.blade.php
Normal file
|
@ -0,0 +1,32 @@
|
|||
@extends('dashboard.core')
|
||||
|
||||
@section('dashboard-heading')
|
||||
<button type="button" class="new-button btn btn-default">New</button>
|
||||
@endsection
|
||||
|
||||
@section('dashboard-body')
|
||||
@set('sort_data', $sortcol != 'false' ? "data-sort=$sortcol" : '')
|
||||
@set('sort_icon', $sortcol != 'false' ? '<i class="fa fa-bars sort-icon" title="Click and drag to reorder"></i>' : '')
|
||||
|
||||
<ul id="edit-list" class="list-group edit-list" data-model="{{ $model }}" {{ $sort_data }}>
|
||||
<input type="hidden" name="_token" id="token" value="{{ csrf_token() }}" />
|
||||
|
||||
@foreach($rows as $row)
|
||||
<li class="list-group-item" data-id="{{ $row['id'] }}">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-xs-9 title-column">
|
||||
{!! $sort_icon !!}
|
||||
{{ $row[$column] }}
|
||||
</div>
|
||||
|
||||
<div class="col-xs-3 button-column">
|
||||
<button type="button" class="edit-button btn btn-warning">Edit</button>
|
||||
<button type="button" class="delete-button btn btn-danger">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
@endsection
|
11
resources/views/dashboard/elements/menu.blade.php
Normal file
11
resources/views/dashboard/elements/menu.blade.php
Normal file
|
@ -0,0 +1,11 @@
|
|||
@set('menu', [
|
||||
[ 'Contact', 'contact' ],
|
||||
[ 'Subscriptions', 'subscriptions' ],
|
||||
[ 'Shows', 'shows' ],
|
||||
[ 'News', 'news' ],
|
||||
[ 'Videos', 'videos' ]
|
||||
])
|
||||
|
||||
@foreach($menu as $menu_item)
|
||||
<li class="{{ $menu_class }}"><a href="{{ url('/dashboard/' . $menu_item[1]) }}">{{ $menu_item[0] }}</a></li>
|
||||
@endforeach
|
39
resources/views/dashboard/elements/nav.blade.php
Normal file
39
resources/views/dashboard/elements/nav.blade.php
Normal file
|
@ -0,0 +1,39 @@
|
|||
<nav class="navbar navbar-default">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#spark-navbar-collapse">
|
||||
<span class="sr-only">Toggle Navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
|
||||
<a class="navbar-brand" href="{{ url('/dashboard') }}">
|
||||
{{ env('SITE_NAME') }} Dashboard
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div id="spark-navbar-collapse" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
@if (Auth::guest())
|
||||
<li><a href="{{ url('/login') }}">Login</a></li>
|
||||
@if(env('REGISTRATION', false))
|
||||
<li><a href="{{ url('/register') }}">Register</a></li>
|
||||
@endif
|
||||
@else
|
||||
@set('menu_class', 'nav-item')
|
||||
@include('dashboard.elements.menu')
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">
|
||||
{{ Auth::user()->name }} <span class="caret"></span>
|
||||
</a>
|
||||
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="{{ url('/logout') }}">Logout</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
@endif
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
6
resources/views/dashboard/home.blade.php
Normal file
6
resources/views/dashboard/home.blade.php
Normal file
|
@ -0,0 +1,6 @@
|
|||
@extends('dashboard.core')
|
||||
|
||||
@section('dashboard-body')
|
||||
@set('menu_class', 'list-group-item')
|
||||
<ul class="list-group linked-list">@include('dashboard.elements.menu')</ul>
|
||||
@endsection
|
27
resources/views/dashboard/view.blade.php
Normal file
27
resources/views/dashboard/view.blade.php
Normal file
|
@ -0,0 +1,27 @@
|
|||
@extends('dashboard.core')
|
||||
|
||||
@section('dashboard-heading')
|
||||
<a href="/dashboard/export/{{ $model }}"><button type="button" class="btn btn-default">Export</button></a>
|
||||
@endsection
|
||||
|
||||
@section('dashboard-body')
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr class="heading-row">
|
||||
@foreach($cols as $column)
|
||||
<th>{{ $column[0] }}</th>
|
||||
@endforeach
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
@foreach($rows as $row)
|
||||
<tr>
|
||||
@foreach($cols as $column)
|
||||
<td><strong class="mobile-heading">{{ $column[0] }}: </strong>{{ $row[$column[1]] }}</td>
|
||||
@endforeach
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
@endsection
|
|
@ -1,3 +1 @@
|
|||
<footer>
|
||||
|
||||
</footer>
|
||||
<footer>Copyright © {{ date('Y') }} {{ env('SITE_NAME') }}</footer>
|
||||
|
|
|
@ -1,19 +1,17 @@
|
|||
<nav class="navbar navbar-default">
|
||||
<nav class="navbar navbar-default navbar-fixed-top">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
|
||||
<button type="button" id="navbar-toggle" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
|
||||
<span class="sr-only">Toggle Navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<div class="navbar-logo"></div>
|
||||
<a class="navbar-logo" href="/"></a>
|
||||
</div>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li class="active"><a href="#">Home</a></li>
|
||||
<li><a href="#">About</a></li>
|
||||
<li><a href="#">Contact</a></li>
|
||||
<li class="navlink navlink-section-contact"><a href="/contact" title="Contact">Contact</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
<p><strong>Name:</strong> {{ $contact['name'] }}</p>
|
||||
|
|
|
@ -1,45 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Page Not Found - {{ env('SITE_NAME') }}</title>
|
||||
@extends('layouts.error')
|
||||
|
||||
<style>
|
||||
html, body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
color: #B0BEC5;
|
||||
display: table;
|
||||
font-weight: 100;
|
||||
font-family: Impact, Charcoal, sans-serif;
|
||||
}
|
||||
|
||||
.container {
|
||||
text-align: center;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.content {
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 72px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="content">
|
||||
<div class="title">Page Not Found</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@section('error-title')
|
||||
Page Not Found
|
||||
@endsection
|
||||
|
|
|
@ -1,45 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Be Right Back - {{ env('SITE_NAME') }}</title>
|
||||
@extends('layouts.error')
|
||||
|
||||
<style>
|
||||
html, body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
color: #B0BEC5;
|
||||
display: table;
|
||||
font-weight: 100;
|
||||
font-family: Impact, Charcoal, sans-serif;
|
||||
}
|
||||
|
||||
.container {
|
||||
text-align: center;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.content {
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 72px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="content">
|
||||
<div class="title">Be Right Back</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@section('error-title')
|
||||
Be Right Back
|
||||
@endsection
|
||||
|
|
5
resources/views/errors/no-such-record.blade.php
Normal file
5
resources/views/errors/no-such-record.blade.php
Normal file
|
@ -0,0 +1,5 @@
|
|||
@extends('layouts.error')
|
||||
|
||||
@section('error-title')
|
||||
No Such Record
|
||||
@endsection
|
|
@ -2,9 +2,9 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
{!! Head::render() !!}
|
||||
<link rel="stylesheet" href="{{ elixir('css/app.css') }}">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
|
||||
<script src="{{ elixir('js/lib.js') }}"></script>
|
||||
<script src="{{ elixir('js/app.js') }}"></script>
|
||||
@yield('page-includes')
|
||||
|
||||
@if (Config::get('app.debug'))
|
||||
<script type="text/javascript">
|
||||
|
@ -12,9 +12,13 @@
|
|||
</script>
|
||||
@endif
|
||||
</head>
|
||||
<body class="{{ Request::path() == "/" ? "index" : preg_replace('/\//', '-', Request::path()) }}">
|
||||
<body class="{{ Request::path() == '/' ? 'index' : preg_replace('/\/.*/', '', Request::path()) }}">
|
||||
@yield('page-top')
|
||||
@yield('page-content')
|
||||
|
||||
<div id="page-content">
|
||||
@yield('content')
|
||||
</div>
|
||||
|
||||
@yield('page-bottom')
|
||||
</body>
|
||||
</html>
|
11
resources/views/layouts/dashboard.blade.php
Normal file
11
resources/views/layouts/dashboard.blade.php
Normal file
|
@ -0,0 +1,11 @@
|
|||
@extends('layouts.base')
|
||||
|
||||
@section('page-includes')
|
||||
<script src="{{ elixir('js/lib-dashboard.js') }}"></script>
|
||||
<script src="{{ elixir('js/dashboard.js') }}"></script>
|
||||
<link rel="stylesheet" href="{{ elixir('css/dashboard.css') }}" />
|
||||
@endsection
|
||||
|
||||
@section('page-top')
|
||||
@include('dashboard.elements.nav')
|
||||
@endsection
|
45
resources/views/layouts/error.blade.php
Normal file
45
resources/views/layouts/error.blade.php
Normal file
|
@ -0,0 +1,45 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>@yield('error-title') - {{ env('SITE_NAME') }}</title>
|
||||
|
||||
<style>
|
||||
html, body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
color: #B0BEC5;
|
||||
display: table;
|
||||
font-weight: 100;
|
||||
font-family: Impact, Charcoal, sans-serif;
|
||||
}
|
||||
|
||||
.container {
|
||||
text-align: center;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.content {
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 72px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="content">
|
||||
<div class="title">@yield('error-title')</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
14
resources/views/layouts/public.blade.php
Normal file
14
resources/views/layouts/public.blade.php
Normal file
|
@ -0,0 +1,14 @@
|
|||
@extends('layouts.base')
|
||||
|
||||
@section('page-includes')
|
||||
<script src="{{ elixir('js/app.js') }}"></script>
|
||||
<link rel="stylesheet" href="{{ elixir('css/app.css') }}" />
|
||||
@endsection
|
||||
|
||||
@section('page-top')
|
||||
@include('elements.nav')
|
||||
@endsection
|
||||
|
||||
@section('page-bottom')
|
||||
@include('elements.footer')
|
||||
@endsection
|
|
@ -1,9 +0,0 @@
|
|||
@extends('base')
|
||||
|
||||
@section('page-top')
|
||||
@include('elements.nav')
|
||||
@endsection
|
||||
|
||||
@section('page-bottom')
|
||||
@include('elements.footer')
|
||||
@endsection
|
|
@ -1,7 +1,6 @@
|
|||
@extends('public')
|
||||
|
||||
@section('page-content')
|
||||
@extends('layouts.public')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
|
@ -10,12 +9,12 @@
|
|||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-md-8 col-md-push-2">
|
||||
<div class="col-xs-12 col-md-8 col-md-offset-2">
|
||||
<div id="contact-form">
|
||||
<form action="#" method="POST" accept-charset="UTF-8">
|
||||
<input type="hidden" name="_token" id="token" value="{{ csrf_token() }}" />
|
||||
<input type="text" name="name" id="name" placeholder="Name" /><br />
|
||||
<input type="text" name="email" id="email" placeholder="Email" /><br />
|
||||
<input type="text" name="name" id="name" placeholder="Name" />
|
||||
<input type="text" name="email" id="email" placeholder="Email" />
|
||||
<textarea name="message" id="message" placeholder="Message"></textarea>
|
||||
|
||||
<input id="submit" type="submit" value="Submit" />
|
||||
|
@ -26,5 +25,4 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
@extends('public')
|
||||
|
||||
@section('page-content')
|
||||
|
||||
<div class="container">
|
||||
<div class="content">
|
||||
<div class="title">Hypothetical Template</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
14
resources/views/website/index.blade.php
Normal file
14
resources/views/website/index.blade.php
Normal file
|
@ -0,0 +1,14 @@
|
|||
@extends('layouts.public')
|
||||
|
||||
@section('content')
|
||||
<div id="subscription-form">
|
||||
<form action="#" method="POST" accept-charset="UTF-8">
|
||||
<input type="hidden" name="_token" id="token" value="{{ csrf_token() }}" />
|
||||
<input type="text" name="email" id="email" placeholder="Email" />
|
||||
<input type="text" name="name" id="name" placeholder="Name" />
|
||||
<input type="text" name="address" id="address" placeholder="Postal / ZIP" />
|
||||
<div id="notification"></div>
|
||||
<input id="submit" type="submit" value="Subscribe" />
|
||||
</form>
|
||||
</div>
|
||||
@endsection
|
Loading…
Reference in a new issue