Reworked site setup, added SingleOrFail()

This commit is contained in:
Deon George 2021-07-01 19:41:12 +10:00
parent 036ab07329
commit c34da6bfb8
No known key found for this signature in database
GPG Key ID: 7670E8DC27415254
12 changed files with 663 additions and 486 deletions

View File

@ -0,0 +1,78 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use App\Models\{Service,SiteDetails};
class AdminController extends Controller
{
public function service(Service $o)
{
return View('a.service',['o'=>$o]);
}
/**
* Site setup
*
* @note This method is protected by the routes
* @param Request $request
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Http\RedirectResponse
*/
public function setup(Request $request)
{
if ($request->post()) {
$validated = $request->validate([
'site_name' => 'required|string|max:255',
'site_email' => 'required|string|email|max:255',
'site_address1' => 'required|string|max:255',
'site_address2' => 'nullable|string|max:255',
'site_city' => 'required|string|max:64',
'site_state' => 'required|string|max:32',
'site_postcode' => 'required|string|max:8',
'site_description' => 'nullable|string|min:5',
'site_phone' => 'nullable|regex:/[0-9 ]+/|min:6|max:12',
'site_fax' => 'nullable|regex:/[0-9 ]+/|min:6|max:12',
'site_tax' => 'required|regex:/[0-9 ]+/|size:14',
'social' => 'nullable|array',
'top_menu' => 'nullable|array',
'site_logo' => 'nullable|image',
]);
$so = config('SITE_SETUP');
// @todo - not currently rendered in the home page
$validated['social'] = [];
$validated['top_menu'] = [];
// Handle the images
foreach(['site_logo','email_logo'] as $key)
if (array_key_exists($key,$validated))
$validated[$key] = ($x=$validated[$key])->storeAs('site/'.config('SITE_SETUP')->site_id,$x->getClientOriginalName(),'public');
foreach ($so->details as $oo)
if (array_key_exists($oo->key,$validated)) {
$oo->value = Arr::get($validated,$oo->key);
$oo->save();
unset($validated[$oo->key]);
}
// Left over values to be created.
foreach ($validated as $k=>$v) {
$oo = new SiteDetails;
$oo->key = $k;
$oo->value = $v ?: '';
$so->details()->save($oo);
}
return redirect()->back()
->with('success','Settings saved');
}
return view('a.setup');
}
}

View File

@ -1,82 +0,0 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Mail;
use App\Mail\{OrderRequestApprove,OrderRequestReject};
use App\Models\{Service,SiteDetails};
class AdminHomeController extends Controller
{
public function service(Service $o)
{
return View('a.service',['o'=>$o]);
}
public function setup()
{
return view('a.setup');
}
public function setup_update(Request $request)
{
$request->validate([
'site_name' => 'required|string|max:255',
'site_email' => 'required|string|email|max:255',
'site_address1' => 'required|string|max:255',
'site_address2' => 'nullable|string|max:255',
'site_city' => 'required|string|max:64',
'site_state' => 'required|string|max:32',
'site_postcode' => 'required|string|max:8',
'site_phone' => 'nullable|regex:/[0-9 ]+/|min:6|max:12',
'site_fax' => 'nullable|regex:/[0-9 ]+/|min:6|max:12',
]);
// If we are more input that sample data, reject the update.
if (config('SITE_SETUP')->allowed_keys(array_keys($request->except('_token'))))
return redirect()->back()
->withInput()
->withErrors('Invalid configuration - values not expected.');
foreach ($request->except('_token') as $key => $value)
{
if (! $value) {
SiteDetails::where('site_id',config('SITE_SETUP')->id)->where('key',$key)->delete();
} else {
try {
if ($key == 'site_logo' AND $value instanceof UploadedFile)
{
$path = $value->storeAs('site/'.config('SITE_SETUP')->id,$value->getClientOriginalName(),'public');
SiteDetails::updateOrCreate([
'site_id'=>config('SITE_SETUP')->id,
'key'=>$key,
],[
'value'=>$path,
]);
} else {
// Update or create our config record.
SiteDetails::updateOrCreate([
'site_id'=>config('SITE_SETUP')->id,
'key'=>$key,
],[
'value'=>$value,
]);
}
} catch (\Exception $e) {
Log::debug($e->getMessage(),['k'=>$key,'v'=>$value]);
}
}
}
return redirect()->back()
->with('success','Setup Updated!');;
}
}

View File

@ -26,19 +26,26 @@ class SetSite
*/
public function handle($request, Closure $next)
{
// @todo Figure out how to know if this is an API call - and deny it if it's not in the database.
$so = new Site;
if ($so->getTable() AND Schema::hasTable($so->getTable()))
$so = Site::where('url',$request->root())->first();
$so = Site::where('url',$request->root())->single();
if ($so && ! $so->active)
abort(404);
// If we dont exist, we'll return a fake model.
if ((! $so) || (! $so->exists))
$so = (new Site)->sample();
if (! $so) {
if ($request->ajax())
abort(404);
$so = (new Site);
}
// Set who we are in SETUP.
Config::set('SITE_SETUP',$so);
View::share('so',$so);
if (! $request->ajax())
View::share('so',$so);
return $next($request);
}

View File

@ -4,26 +4,34 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
class Site extends Model
{
use HasFactory;
protected $table = 'ab_setup';
public $timestamps = FALSE;
public $incrementing = FALSE;
protected $with = ['details','language'];
protected $casts = [
'address'=>'array',
];
/* RELATIONS */
public function country()
{
return $this->belongsTo(Country::class);
}
public function currency()
{
return $this->belongsTo(Currency::class);
}
public function details()
{
return $this->hasMany(SiteDetails::class);
return $this->hasMany(SiteDetails::class,NULL,'site_id');
}
public function language()
@ -31,258 +39,77 @@ class Site extends Model
return $this->belongsTo(Language::class);
}
/* ATTRIBUTES */
public function getAllowedKeysAttribute(): Collection
{
return $this->_sampledata()->keys();
}
/* METHODS */
public function __get($key)
{
// @todo Not sure if this is functioning correctly?
if ($parent = parent::__get($key))
return $parent;
static $details = NULL;
// Deprecated Items
if (! in_array($key,array_keys($this->_sampledata())))
{
Log::alert('No sample data for Key:',['key'=>$key]);
return NULL;
}
if ($x = parent::__get($key))
return $x;
$detail = $this->getSiteDetailValue($key);
// Get the value from the details table
if (($x=$this->detail_item($key)) !== NULL)
return $x;
return $detail->exists ? $detail->value : $this->getDefaultValue($key);
if (is_null($details))
$details = new SiteDetails;
// Get a default value for this key
$value = $details->sample($key);
// At this point our DB doesnt have this value, we'll log an alert
if ($this->exists)
Log::alert(sprintf('Site is missing value for key [%s] - providing a default [%s]',$key,serialize($value)));
return $value;
}
private function getDefaultValue($key)
/* GENERAL METHODS */
/**
* Get a key from the site_details
*
* @param $key
* @return mixed
*/
private function detail_item($key)
{
$okblank = [
'site_address2',
'site_fax',
'social',
'top_menu'
];
if (($x=$this->details->search(function($item) use ($key) { return $item->key == $key; })) !== FALSE)
return $this->details->get($x)->value;
if (! in_array($key,$okblank))
Log::alert('Returning Default Value for Key:',['key'=>$key]);
// Suppress some default values
$default = [
'block_quotes' => '',
'clients' => '',
'page_tabs' => '',
'services' => '',
'site_description' => '',
'site_fax' => '',
'site_address2' => '',
'site_slider' => '',
'social' => [],
'steps' => '',
'testimonials' => '',
'top_menu' => [],
];
return Arr::get($default,$key);
}
public function getEmailLogoAttribute()
{
//$return = $this->getSiteDetailValue('email_logo')->value;
// @todo Get from the DB.
$return = 'site/1/gthpl-white.png';
return $return ? 'storage/'.$return : '/image/generic/150/20/fff';
}
public function getSiteLogoAttribute()
{
//$return = $this->getSiteDetailValue('site_logo')->value;
// @todo Get from DB.
$return = 'site/1/gth-horseradishfont-full.png';
return $return ? '/storage/'.$return : '/image/generic/150/20/fff';
}
private function getSiteDetailValue($key)
{
$return = $this->details->where('key',$key)->first();
return $return ?: (new SiteDetails);
return NULL;
}
/**
* Pre-load this model with Sample Data, if there is no database record
* Add the path to the mail logo, so it can be displayed.
*
* @return string
*/
private function _sampledata()
public function getEmailLogoAttribute()
{
return [
'aboutus'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
'activity'=>[
['title'=>'Project 1','description'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.','subtitle'=>'Lorem ipsum dolor sit amet','image_small'=>'/image/generic/150/75/a00','image_large'=>'/image/generic/500/400/700'],
['title'=>'Project 2','description'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.','subtitle'=>'Lorem ipsum dolor sit amet','image_small'=>'/image/generic/150/75/b00','image_large'=>'/image/generic/500/400/800'],
['title'=>'Project 3','description'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.','subtitle'=>'Lorem ipsum dolor sit amet','image_small'=>'/image/generic/150/75/c00','image_large'=>'/image/generic/500/400/900'],
['title'=>'Project 4','description'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.','subtitle'=>'Lorem ipsum dolor sit amet','image_small'=>'/image/generic/150/75/d00','image_large'=>'/image/generic/500/400/a00'],
],
'activity_intro'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
'block_quotes'=>[
[
'title'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
'image'=>'/image/generic/150/75/1A3AAA'
],
],
'clients'=>[
[
'image'=>'/image/generic/200/100/999',
'hover'=>'/image/generic/200/100/399',
],
[
'image'=>'/image/generic/200/100/999',
'hover'=>'/image/generic/200/100/499',
],
[
'image'=>'/image/generic/200/100/999',
'hover'=>'/image/generic/200/100/599',
],
[
'image'=>'/image/generic/200/100/999',
'hover'=>'/image/generic/200/100/699',
],
[
'image'=>'/image/generic/200/100/999',
'hover'=>'/image/generic/200/100/689',
],
[
'image'=>'/image/generic/200/100/999',
'hover'=>'/image/generic/200/100/679',
],
[
'image'=>'/image/generic/200/100/999',
'hover'=>'/image/generic/200/100/669',
],
[
'image'=>'/image/generic/200/100/999',
'hover'=>'/image/generic/200/100/659',
],
[
'image'=>'/image/generic/200/100/999',
'hover'=>'/image/generic/200/100/649',
],
],
'clients_intro'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore',
'language_id'=>1,
'page_tabs'=>[
[
'title'=>'Title 1',
'image'=>'/image/generic/200/100/999',
'text'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua',
],
[
'title'=>'Title 2',
'image'=>'/image/generic/200/100/799',
'text'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua',
],
[
'title'=>'Title 3',
'image'=>'/image/generic/200/100/979',
'text'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua',
],
],
'site_slider'=>[
[
'title'=>'Header <br/><span class="carousel-title-normal">and Title</span>',
'text'=>'This is what you were looking for',
'style'=>1,
'image'=>'url(/image/generic/300/300/eee)',
'button'=>['text'=>'Purchase Now','url'=>'#'],
],
[
'title'=>'Header and Title',
'text'=>'This is what you were looking for',
'text2'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit.<br/>Sed est nunc, sagittis at consectetur id.',
'style'=>2,
'image'=>'url(/image/generic/400/400/ddd)',
'button'=>['text'=>'Purchase Now','url'=>'#'],
],
[
'title'=>'Header and Title',
'text'=>'This is what you were looking for',
'text2'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit.<br/>Sed est nunc, sagittis at consectetur id.',
'style'=>2,
'image'=>'url(/image/generic/500/500/eee)',
//'button'=>['text'=>'Purchase Now','url'=>'#'],
],
],
'site_logo'=>route('image',['width'=>128,'height'=>32,'color'=>'eee']),
'site_address1'=>'Building Name',
'site_address2'=>NULL,
'site_city'=>'City',
'site_description'=>'Example Site',
'site_email'=>'nobody@example.com',
'site_fax'=>'+0 1 2345 6789',
'site_name'=>'Example',
'site_phone'=>'+0 1 2345 6789',
'site_postcode'=>'123 456',
'site_state'=>'State',
'site_tax'=>'12 123 123 123',
'services'=>[
['title'=>'Title 1','text'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.','icon'=>'fa fa-location-arrow blue','image'=>NULL],
['title'=>'Title 2','text'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.','icon'=>'fa fa-compress green','image'=>NULL],
['title'=>'Title 3','text'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.','icon'=>'fa fa-check red','image'=>'/image/generic/200/100/999'],
],
'social'=>[
[
'name'=>'facebook',
'url'=>'http://www.facebook.com',
],
[
'name'=>'linkedin',
'url'=>'http://www.linkedin.com',
],
[ 'name'=>'twitter',
'url'=>'http://www.twitter.com',
],
],
'steps'=>[
['title'=>'Title 1','description'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud'],
['title'=>'Title 2','description'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud'],
['title'=>'Title 3','description'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud'],
],
'testimonials'=>[
[
'title'=>'Title 1',
'name'=>'Bart Simpson',
'quote'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud',
'photo'=>'/image/generic/200/100/999',
],
[
'title'=>'Title 2',
'name'=>'Lisa Simpson',
'quote'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud',
'photo'=>'/image/generic/200/100/499',
],
],
'top_menu'=>[
'Home'=>['name'=>'Home','url'=>'/','children'=>[
['name'=>'Link 1','url'=>'#/l2', 'children'=>[]],
['name'=>'Link 2','url'=>'#/l2', 'children'=>[]],
]],
'Option1'=>['name'=>'Option 1','url'=>'/o1','children'=>[]],
'Option2'=>['name'=>'Option 2','url'=>'/o2','children'=>[
['name'=>'O2 Link 1','url'=>'#/o2l1', 'children'=>[]],
['name'=>'O2 Link 1','url'=>'#/o2l2', 'children'=>[]],
]],
],
];
return (($x=$this->detail_item('email_logo')) !== NULL) ? '/storage/'.$x : '/image/generic/150/20/fff';
}
public function sample()
/**
* Add the path to the site logo, so it can be displayed.
*
* @param $value
* @return string
*/
public function getSiteLogoAttribute($value)
{
return $this->forceFill($this->_sampledata());
}
public function aboutus()
{
// @todo To be implemented
return Arr::get($this->_sampledata(),'aboutus');
return (($x=$this->detail_item('site_logo')) !== NULL) ? '/storage/'.$x : '/image/generic/150/20/fff';
}
// @todo - To optimize
private function _address()
{
$return = [];
@ -300,11 +127,7 @@ class Site extends Model
return $return;
}
public function allowed_keys(array $keys=[])
{
return $keys ? array_diff($keys,array_keys($this->_sampledata())) : array_keys($this->_sampledata());
}
// @todo - To optimize
public function address($type='plain')
{
switch ($type)

View File

@ -3,20 +3,256 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Leenooks\Traits\CompositeKeys;
class SiteDetails extends Model
{
use CompositeKeys;
public $fillable = ['site_id','key','value'];
public $incrementing = false;
protected $primaryKey = ['site_id','key'];
public $timestamps = FALSE;
/* RELATIONS */
public function site()
{
return $this->belongsTo(Site::class);
}
/* ATTRIBUTES */
public function getValueAttribute($value)
{
if (! $this->key)
return $value;
switch (gettype($this->_sampledata()->get($this->key))) {
case 'array': return unserialize($value);
default: return $value;
}
}
public function setKeyAttribute($value)
{
if (! $this->_sampledata()->has($value))
throw new \Exception(sprintf('Key [%s] is not expected.',$value));
$this->attributes['key'] = $value;
}
public function setValueAttribute($value)
{
// Check that the value can be set
if (! $this->key)
throw new \Exception('Please set key first');
// Check that the value is of the right type
$x = $this->_sampledata()->get($this->key);
if ($value && (! $this->checkType($value,$x)))
throw new \Exception(sprintf('Value for [%s] is not the of the correct type [%s] for this attribute, expecting [%s].',$this->key,gettype($value),gettype($this->_sampledata()->get($this->key))));
switch (gettype($x)) {
case 'array':
$this->attributes['value'] = serialize($value ?: []);
break;
default:
$this->attributes['value'] = $value ?: '';
}
}
/* GENERAL METHODS */
/**
* Check that two variables are the same type
*
* @param $a
* @param $b
* @return bool
*/
private function checkType($a,$b): bool
{
return gettype($a) == gettype($b);
}
/**
* Pre-load this model with Sample Data, if there is no database record
*/
private function _sampleData(): Collection
{
return collect([
/*
'aboutus'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
'activity'=>[
['title'=>'Project 1','description'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.','subtitle'=>'Lorem ipsum dolor sit amet','image_small'=>'/image/generic/150/75/a00','image_large'=>'/image/generic/500/400/700'],
['title'=>'Project 2','description'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.','subtitle'=>'Lorem ipsum dolor sit amet','image_small'=>'/image/generic/150/75/b00','image_large'=>'/image/generic/500/400/800'],
['title'=>'Project 3','description'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.','subtitle'=>'Lorem ipsum dolor sit amet','image_small'=>'/image/generic/150/75/c00','image_large'=>'/image/generic/500/400/900'],
['title'=>'Project 4','description'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.','subtitle'=>'Lorem ipsum dolor sit amet','image_small'=>'/image/generic/150/75/d00','image_large'=>'/image/generic/500/400/a00'],
],
'activity_intro'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
'block_quotes'=>[
[
'title'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
'image'=>'/image/generic/150/75/1A3AAA'
],
],
'clients'=>[
[
'image'=>'/image/generic/200/100/999',
'hover'=>'/image/generic/200/100/399',
],
[
'image'=>'/image/generic/200/100/999',
'hover'=>'/image/generic/200/100/499',
],
[
'image'=>'/image/generic/200/100/999',
'hover'=>'/image/generic/200/100/599',
],
[
'image'=>'/image/generic/200/100/999',
'hover'=>'/image/generic/200/100/699',
],
[
'image'=>'/image/generic/200/100/999',
'hover'=>'/image/generic/200/100/689',
],
[
'image'=>'/image/generic/200/100/999',
'hover'=>'/image/generic/200/100/679',
],
[
'image'=>'/image/generic/200/100/999',
'hover'=>'/image/generic/200/100/669',
],
[
'image'=>'/image/generic/200/100/999',
'hover'=>'/image/generic/200/100/659',
],
[
'image'=>'/image/generic/200/100/999',
'hover'=>'/image/generic/200/100/649',
],
],
'clients_intro'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore',
'language_id'=>1,
'page_tabs'=>[
[
'title'=>'Title 1',
'image'=>'/image/generic/200/100/999',
'text'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua',
],
[
'title'=>'Title 2',
'image'=>'/image/generic/200/100/799',
'text'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua',
],
[
'title'=>'Title 3',
'image'=>'/image/generic/200/100/979',
'text'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua',
],
],
'site_slider'=>[
[
'title'=>'Header <br/><span class="carousel-title-normal">and Title</span>',
'text'=>'This is what you were looking for',
'style'=>1,
'image'=>'url(/image/generic/300/300/eee)',
'button'=>['text'=>'Purchase Now','url'=>'#'],
],
[
'title'=>'Header and Title',
'text'=>'This is what you were looking for',
'text2'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit.<br/>Sed est nunc, sagittis at consectetur id.',
'style'=>2,
'image'=>'url(/image/generic/400/400/ddd)',
'button'=>['text'=>'Purchase Now','url'=>'#'],
],
[
'title'=>'Header and Title',
'text'=>'This is what you were looking for',
'text2'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit.<br/>Sed est nunc, sagittis at consectetur id.',
'style'=>2,
'image'=>'url(/image/generic/500/500/eee)',
//'button'=>['text'=>'Purchase Now','url'=>'#'],
],
],
'services'=>[
['title'=>'Title 1','text'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.','icon'=>'fa fa-location-arrow blue','image'=>NULL],
['title'=>'Title 2','text'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.','icon'=>'fa fa-compress green','image'=>NULL],
['title'=>'Title 3','text'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.','icon'=>'fa fa-check red','image'=>'/image/generic/200/100/999'],
],
*/
'site_address1' => 'Address line 1',
'site_address2' => 'Address line 2',
'site_description'=>'Example Site',
'site_email' => 'nobody@example.com',
'site_city' => 'City',
'site_fax'=>'+0 1 2345 6789',
'site_name' => 'MY OSB SITE',
'site_state' => 'State',
'site_phone'=>'+0 1 2345 6789',
'site_postcode' => '12345',
'site_tax'=>'12 123 123 123',
'site_logo'=>route('image',['width'=>128,'height'=>32,'color'=>'eee']),
'social'=>[
['name'=>'facebook','url'=>'http://www.facebook.com'],
['name'=>'linkedin','url'=>'http://www.linkedin.com'],
['name'=>'twitter','url'=>'http://www.twitter.com'],
],
/*
'steps'=>[
['title'=>'Title 1','description'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud'],
['title'=>'Title 2','description'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud'],
['title'=>'Title 3','description'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud'],
],
'testimonials'=>[
[
'title'=>'Title 1',
'name'=>'Bart Simpson',
'quote'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud',
'photo'=>'/image/generic/200/100/999',
],
[
'title'=>'Title 2',
'name'=>'Lisa Simpson',
'quote'=>'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud',
'photo'=>'/image/generic/200/100/499',
],
],
*/
'top_menu'=>[
'Home'=>['name'=>'Home','url'=>'/','children'=>[
['name'=>'Link 1','url'=>'#/l2', 'children'=>[]],
['name'=>'Link 2','url'=>'#/l2', 'children'=>[]],
]],
'Option1'=>['name'=>'Option 1','url'=>'/o1','children'=>[]],
'Option2'=>['name'=>'Option 2','url'=>'/o2','children'=>[
['name'=>'O2 Link 1','url'=>'#/o2l1', 'children'=>[]],
['name'=>'O2 Link 1','url'=>'#/o2l2', 'children'=>[]],
]],
],
]);
}
/**
* Get a sample key value
*
* @param $key
* @return mixed
* @throws \Exception
*/
public function sample($key)
{
if (! $x=$this->_sampledata()->get($key))
throw new \Exception('Key doesnt exist: '.$key);
return $x;
}
}

View File

@ -3,9 +3,12 @@
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Leenooks\Traits\SingleOrFail;
class AppServiceProvider extends ServiceProvider
{
use SingleOrFail;
/**
* Register any application services.
*
@ -23,6 +26,6 @@ class AppServiceProvider extends ServiceProvider
*/
public function boot()
{
//
SingleOrFail::bootSingleOrfail();
}
}

6
composer.lock generated
View File

@ -2884,11 +2884,11 @@
},
{
"name": "leenooks/laravel",
"version": "9.0.4",
"version": "9.0.5",
"source": {
"type": "git",
"url": "https://dev.leenooks.net/leenooks/laravel",
"reference": "9798f6aa7dcf507e7ac7179fc348320e36aa160b"
"reference": "45be8553a29f1887273b10a56982f55134bfd9e0"
},
"require": {
"creativeorange/gravatar": "^1.0",
@ -2925,7 +2925,7 @@
"laravel",
"leenooks"
],
"time": "2021-06-29T06:38:19+00:00"
"time": "2021-07-01T01:58:50+00:00"
},
{
"name": "monolog/monolog",

View File

@ -0,0 +1,61 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class RenameSetup extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('ab_setup', function (Blueprint $table) {
$table->dropForeign('fk_set_acc');
$table->dropForeign('fk_set_cty');
$table->dropForeign('fk_set_cur');
$table->dropForeign('fk_set_lan');
});
Schema::table('ab_setup', function (Blueprint $table) {
$table->dropIndex('fk_set_cty_idx');
$table->dropIndex('fk_set_cur_idx');
$table->dropIndex('fk_set_lan_idx');
$table->dropIndex('fk_set_acc_idx');
});
DB::statement('ALTER TABLE ab_setup RENAME TO sites');
DB::statement('ALTER TABLE sites MODIFY url VARCHAR(256) NOT NULL');
DB::statement('ALTER TABLE sites CHANGE COLUMN id site_id INT NOT NULL');
DB::statement('ALTER TABLE sites MODIFY admin_id INT(10) UNSIGNED NOT NULL');
DB::statement('ALTER TABLE sites MODIFY active TINYINT(1) NOT NULL');
Schema::table('sites', function (Blueprint $table) {
$table->index(['site_id']);
$table->dropPrimary(['site_id','country_id','currency_id','url']);
});
Schema::table('sites', function (Blueprint $table) {
$table->integer('id',TRUE)->first();
$table->unique(['site_id','url']);
$table->dropColumn(['login_expire','time_format','date_format','decimal_place','module_config','site_details']);
$table->foreign('country_id')->references('id')->on('ab_country');
$table->foreign('currency_id')->references('id')->on('ab_currency');
$table->foreign('language_id')->references('id')->on('ab_language');
$table->foreign(['admin_id','site_id'])->references(['id','site_id'])->on('users');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
abort(500,'cant go back');
}
}

View File

@ -3,6 +3,9 @@
@section('htmlheader_title')
Setup
@endsection
@section('page_title')
Setup
@endsection
@section('contentheader_title')
{{ $so->site_name }}
@ -12,76 +15,190 @@
@endsection
@section('main-content')
<div class="col-md-9">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">Setup Configuration</h3>
</div>
<div class="row">
<div class="col-12">
<form role="form" method="POST" enctype="multipart/form-data">
{{ csrf_field() }}
@if(session()->has('success'))
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="callout callout-success">
<p>{{ session()->get('success') }}</p>
</div>
</div>
</div>
@endif
@if($errors->any())
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="callout callout-danger">
<p>Some validation errors to look at.</p>
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
</div>
</div>
@endif
<div class="nav-tabs-custom">
<ul class="nav nav-tabs">
<li class="active"><a href="#tab-site" data-toggle="tab">Site Details</a></li>
<li><a href="#tab-other" data-toggle="tab">Other</a></li>
</ul>
<div class="box-body">
<div class="tab-content">
<div class="tab-pane active" id="tab-site">
@include('a.widgets.setup_site_details')
</div>
<div class="tab-pane" id="tab-other">
Other Details
</div>
</div>
</div>
<div class="box-footer">
<button type="submit" class="btn btn-info">Save</button>
</div>
<div class="card">
<div class="card-header">
<h1 class="card-title">Setup Configuration</h1>
@if(session()->has('success'))
<span class="ml-3 pt-0 pb-0 pr-1 pl-1 btn btn-outline-success"><small>{{ session()->get('success') }}</small></span>
@endif
</div>
</form>
<div class="card-body">
<form class="g-0 needs-validation" method="POST" enctype="multipart/form-data" role="form">
@csrf
<div class="row">
<div class="col-4">
<div class="row">
<div class="col-12">
<div class="form-group has-validation">
<label for="site_name">Organisation Name</label>
<input type="text" class="form-control form-control-border @error('site_name') is-invalid @enderror" id="site_name" name="site_name" placeholder="Site Name..." value="{{ old('site_name',$so->site_name) }}" required>
<span class="invalid-feedback" role="alert">
@error('site_name')
{{ $message }}
@else
Organisation Name is required.
@enderror
</span>
<span class="input-helper">System Name used everywhere.</span>
</div>
</div>
</div>
<div class="row">
<div class="col-10">
<div class="form-group has-validation">
<label for="site_logo">Site Logo</label>
<input type="file" class="form-control @error('site_logo') is-invalid @enderror" id="site_logo" name="site_logo"><img class="col-12" src="{{ asset($so->site_logo) }}">
<span class="invalid-feedback" role="alert">
@error('site_logo')
{{ $message }}
@enderror
</span>
</div>
</div>
</div>
</div>
<div class="col-4">
<div class="row">
<div class="col-12">
<div class="form-group has-validation">
<label for="site_address1">Address Lines</label>
<input type="text" class="form-control form-control-border @error('site_address1') is-invalid @enderror" id="site_address1" name="site_address1" placeholder="Address1" value="{{ old('site_address1',$so->site_address1) }}" required>
<input type="text" class="form-control form-control-border" id="site_address2" name="site_address2" placeholder="Address2" value="{{ old('site_address2',$so->site_address2) }}">
<span class="invalid-feedback" role="alert">
@error('site_address1')
{{ $message }}
@else
Atleast 1 address line required.
@enderror
</span>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<div class="form-group has-validation">
<label for="site_address">City</label>
<input type="text" class="form-control form-control-border @error('site_city') is-invalid @enderror" id="site_city" name="site_city" placeholder="City" value="{{ old('site_city',$so->site_city) }}">
<span class="invalid-feedback" role="alert">
@error('site_city')
{{ $message }}
@else
City is required.
@enderror
</span>
</div>
</div>
</div>
<div class="row">
<div class="col-12" style="display: inline-flex;">
<div class="form-group has-validation">
<label for="site_address">State</label>
<input type="text" class="form-control form-control-border @error('site_state') is-invalid @enderror col-5" id="site_state" name="site_state" placeholder="State" value="{{ old('site_state',$so->site_state) }}">
<span class="invalid-feedback" role="alert">
@error('site_state')
{{ $message }}
@else
State is required.
@enderror
</span>
</div>
<div class="form-group has-validation">
<label for="site_address">Postal Code</label>
<input type="text" class="form-control form-control-border @error('site_postcode') is-invalid @enderror col-5" id="site_postcode" name="site_postcode" placeholder="Postal Code" value="{{ old('site_postcode',$so->site_postcode) }}">
<span class="invalid-feedback" role="alert">
@error('site_postcode')
{{ $message }}
@else
Postcode is required.
@enderror
</span>
</div>
</div>
</div>
</div>
<div class="col-4">
<div class="form-group has-validation">
<label for="site_phone">Phone</label>
<input type="text" class="form-control form-control-border @error('site_phone') is-invalid @enderror" id="site_phone" name="site_phone" placeholder="Site Phone" value="{{ old('site_phone',$so->site_phone) }}">
<span class="invalid-feedback" role="alert">
@error('site_phone')
{{ $message }}
@enderror
</span>
</div>
<div class="form-group has-validation">
<label for="site_fax">Fax</label>
<input type="text" class="form-control form-control-border @error('site_fax') is-invalid @enderror" id="site_fax" name="site_fax" placeholder="Site Fax" value="{{ old('site_fax',$so->site_fax) }}">
<span class="invalid-feedback" role="alert">
@error('site_fax')
{{ $message }}
@enderror
</span>
</div>
<div class="form-group has-validation">
<label for="site_email">Email</label>
<input type="email" class="form-control form-control-border @error('site_email') is-invalid @enderror" id="site_email" name="site_email" placeholder="Site Email" value="{{ old('site_email',$so->site_email) }}" required>
<span class="invalid-feedback" role="alert">
@error('site_email')
{{ $message }}
@else
Email required.
@enderror
</span>
</div>
<div class="form-group has-validation">
<label for="site_tax">Tax Number</label>
<span class="input-group-prepend">ABN</span>
<input type="text" class="form-control form-control-border @error('site_tax') is-invalid @enderror" id="site_tax" name="site_tax" placeholder="Site Tax" value="{{ old('site_tax',$so->site_tax) }}" required>
<span class="invalid-feedback" role="alert">
@error('site_tax')
{{ $message }}
@enderror
</span>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<div class="form-group has-validation">
<label for="site_description">Organisation Description</label>
<textarea class="form-control @error('site_description') is-invalid @enderror" id="site_description" name="site_description" placeholder="Site Description...">{{ old('site_description',$so->site_description) }}</textarea>
<span class="input-helper">Brief description of site.</span>
<span class="invalid-feedback" role="alert">
@error('site_description')
{{ $message }}
@enderror
</span>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<a href="{{ url('/') }}" class="btn btn-danger">Cancel</a>
@can('wholesaler')
<button type="submit" name="submit" class="btn btn-success mr-0 float-end">@if ($so->exists)Save @else Add @endif</button>
@endcan
</div>
</div>
</form>
</div>
</div>
</div>
</div>
@endsection
@section('page-scripts')
@js('/js/jqBootstrapValidation.js','jq-validation','jquery')
<script>
$(function () { $("input,select,textarea").not("[type=submit]").jqBootstrapValidation(); } );
</script>
<style>
span.help-block > ul {
color: #9d0000;
padding-left: 5px;
list-style-type: none;
}
</style>
@append
@endsection

View File

@ -1,66 +0,0 @@
<div class="form-group col-sm-12 {{ $errors->has('site_name') ? 'has-error' : '' }}">
<label for="site_name">Site Name</label>
<input type="text" class="form-control" id="site_name" name="site_name" placeholder="Site Name" value="{{ old('site_name',$so->site_name) }}">
<span class="help-block">{{ $errors->first('site_name') }}</span>
</div>
<div class="form-group col-sm-9 {{ $errors->has('site_description') ? 'has-error' : '' }}">
<label for="site_description">Site Description</label>
<textarea class="form-control" id="site_description" name="site_description" placeholder="Site Description" rows="3">{{ old('site_description',$so->site_description) }}</textarea>
<span class="help-block">{{ $errors->first('site_description') }}</span>
</div>
<div class="form-group col-sm-3 {{ $errors->has('site_logo') ? 'has-error' : '' }}">
<label for="site_logo">Site Logo</label>
<input type="file" class="form-control" id="site_logo" name="site_logo"><img class="col-sm-12" src="{{ asset($so->site_logo) }}">
<span class="help-block">{{ $errors->first('site_logo') }}</span>
</div>
<fieldset class="form-group col-sm-12">
<label>Site Address</label>
<div class="form-group col-sm-12 {{ $errors->has('site_address1') ? 'has-error' : '' }}">
<label for="site_address">Site Address Lines</label>
<input type="text" class="form-control" id="site_address1" name="site_address1" placeholder="Address1" value="{{ old('site_address1',$so->site_address1) }}">
<input type="text" class="form-control" id="site_address2" name="site_address2" placeholder="Address2" value="{{ old('site_address2',$so->site_address2) }}">
<span class="help-block">{{ $errors->first('site_address1') }} {{ $errors->first('site_address2') }}</span>
</div>
<div class="form-group col-sm-6 {{ $errors->has('site_city') ? 'has-error' : '' }}">
<label for="site_address">Site City</label>
<input type="text" class="form-control" id="site_city" name="site_city" placeholder="City" value="{{ old('site_city',$so->site_city) }}">
<span class="help-block">{{ $errors->first('site_city') }}</span>
</div>
<div class="form-group col-sm-3 {{ $errors->has('site_state') ? 'has-error' : '' }}">
<label for="site_address">Site State</label>
<input type="text" class="form-control col-sm-3" id="site_state" name="site_state" placeholder="State" value="{{ old('site_state',$so->site_state) }}">
<span class="help-block">{{ $errors->first('site_state') }}</span>
</div>
<div class="form-group col-sm-3 {{ $errors->has('site_postcode') ? 'has-error' : '' }}">
<label for="site_address">Site Post Code</label>
<input type="text" class="form-control col-sm-3" id="site_postcode" name="site_postcode" placeholder="Post Code" value="{{ old('site_postcode',$so->site_postcode) }}">
<span class="help-block">{{ $errors->first('site_postcode') }}</span>
</div>
</fieldset>
<div class="form-group col-sm-6 {{ $errors->has('site_phone') ? 'has-error' : '' }}">
<label for="site_phone">Site Phone</label>
<input class="form-control" id="site_phone" name="site_phone" placeholder="Site Phone" value="{{ old('site_phone',$so->site_phone) }}">
<span class="help-block">{{ $errors->first('site_phone') }}</span>
</div>
<div class="form-group col-sm-6 {{ $errors->has('site_fax') ? 'has-error' : '' }}">
<label for="site_fax">Site Fax</label>
<input class="form-control" id="site_fax" name="site_fax" placeholder="Site Fax" value="{{ old('site_fax',$so->site_fax) }}">
<span class="help-block">{{ $errors->first('site_fax') }}</span>
</div>
<div class="control-group form-group col-sm-6 {{ $errors->has('site_email') ? 'has-error' : '' }}">
<label for="site_email">Site Email</label>
<input type="email" class="form-control" id="site_email" name="site_email" placeholder="Site Email" value="{{ old('site_email',$so->site_email) }}">
<span class="help-block">{{ $errors->first('site_email') }}</span>
</div>
<div class="control-group form-group col-sm-6 {{ $errors->has('site_tax') ? 'has-error' : '' }}">
<label for="site_tax">Site Tax Number</label>
<div class="input-group">
<span class="input-group-addon">ABN</span>
<input type="number" class="form-control" id="site_tax" name="site_tax" minlength="10" maxlength="10" placeholder="Site Tax" value="{{ old('site_tax',$so->site_tax) }}">
</div>
<span class="help-block">{{ $errors->first('site_tax') }}</span>
</div>

View File

@ -2,27 +2,21 @@
<li class="nav-item">
<a href="{{ url('home') }}" class="nav-link @if(preg_match('#^event/summary#',Route::current()->uri())) active @endif">
<i class="nav-icon fas fa-home"></i>
<p>
{{ trans('adminlte_lang::message.home') }}
</p>
<i class="nav-icon fas fa-home"></i> <p>Home</p>
</a>
</li>
<!-- ORDERS -->
<li class="nav-item has-treeview @if(preg_match('#^order/#',Route::current()->uri())) menu-open @endif">
<a href="#" class="nav-link @if(preg_match('#^order/#',Route::current()->uri())) active @endif">
<i class="nav-icon fas fa-cash-register"></i>
<p>
Orders
<i class="fas fa-angle-left right"></i>
</p>
<p>Orders <i class="fas fa-angle-left right"></i></p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item">
<a href="{{ url('order') }}" class="nav-link @if(Route::current()->uri() == 'group/add') active @endif">
<i class="fas fa-tag nav-icon"></i>
<p>New Order</p>
<i class="fas fa-tag nav-icon"></i> <p>New Order</p>
</a>
</li>
</ul>
@ -31,6 +25,12 @@
@can('wholesaler')
<li class="nav-header">ADMIN</li>
<li class="nav-item">
<a href="{{ url('a/setup') }}" class="nav-link @if(preg_match('#^a/setup#',Route::current()->uri())) active @endif">
<i class="nav-icon fas fa-cogs"></i> <p>Site Setup</p>
</a>
</li>
<li class="nav-item has-treeview @if(preg_match('#^a/report/(products)#',request()->path()))menu-open @else menu-closed @endif">
<a href="#" class="nav-link @if(preg_match('#^a/report/(products)#',request()->path())) active @endif">
<i class="nav-icon fas fa-list"></i> <p>REPORT<i class="fas fa-angle-left right"></i></p>
@ -44,4 +44,4 @@
</li>
</ul>
</li>
@endcan
@endcan

View File

@ -1,6 +1,7 @@
<?php
use App\Http\Controllers\{Auth\LoginController,
use App\Http\Controllers\{AdminController,
Auth\LoginController,
CheckoutController,
HomeController,
PaypalController,
@ -32,8 +33,7 @@ Route::get('image/generic/{width}/{height}/{color}/{name?}','MediaController@ima
// Our Admin Routes
Route::group(['middleware'=>['theme:adminlte-be','auth','role:wholesaler'],'prefix'=>'a'],function() {
Route::get('setup','AdminHomeController@setup');
Route::post('setup','AdminHomeController@setup_update');
Route::match(['get','post'],'setup',[AdminController::class,'setup']);
Route::get('service/{o}','AdminHomeController@service');
Route::post('service/{o}','AdminHomeController@service_update');
Route::get('report/products','Wholesale\ReportController@products');