Compare commits

...

31 Commits
1.1.1 ... 1.2.6

Author SHA1 Message Date
Dennis
448398322f Production mix 2020-11-12 20:42:40 +01:00
Dennis
3a78339396 Merge branch 'develop'
# Conflicts:
#	public/js/10.js
#	public/js/app.js
2020-11-12 20:42:04 +01:00
Dennis
a925a70448 Providers fix 2020-11-12 20:41:41 +01:00
Dennis
e283eacaa3 Production mixed 2020-11-12 13:34:27 +01:00
Dennis
3df6b6baed Merge branch 'develop'
# Conflicts:
#	public/js/0.js
#	public/js/10.js
#	public/js/11.js
#	public/js/12.js
#	public/js/13.js
#	public/js/14.js
#	public/js/15.js
#	public/js/16.js
#	public/js/17.js
#	public/js/18.js
#	public/js/19.js
#	public/js/20.js
#	public/js/21.js
#	public/js/22.js
#	public/js/23.js
#	public/js/24.js
#	public/js/25.js
#	public/js/26.js
#	public/js/27.js
#	public/js/28.js
#	public/js/29.js
#	public/js/30.js
#	public/js/31.js
#	public/js/32.js
#	public/js/33.js
#	public/js/34.js
#	public/js/35.js
#	public/js/36.js
#	public/js/37.js
#	public/js/38.js
#	public/js/39.js
#	public/js/40.js
#	public/js/41.js
#	public/js/42.js
#	public/js/43.js
#	public/js/44.js
#	public/js/45.js
#	public/js/46.js
#	public/js/47.js
#	public/js/48.js
#	public/js/49.js
#	public/js/50.js
#	public/js/52.js
#	public/js/67.js
#	public/js/68.js
#	public/js/69.js
#	public/js/75.js
#	public/js/8.js
#	public/js/9.js
#	public/js/app.js
2020-11-12 13:33:57 +01:00
Dennis
b65526e040 Stripe coupon fix && general updates 2020-11-12 13:33:34 +01:00
Dennis
673bbf73be Responsive progress 2020-11-11 16:27:16 +01:00
Dennis
094d22eaa8 Added API link here 2020-11-11 14:10:29 +01:00
Dennis
0fdba5fdec default to en here 2020-11-11 13:42:05 +01:00
Dennis
cf0730be89 Production mix 2020-11-11 13:09:48 +01:00
Dennis
221e67fd12 Merge branch 'develop' 2020-11-11 13:06:15 +01:00
Dennis
f9074309d1 Added coupon feature 2020-11-11 12:30:33 +01:00
Dennis
b2bdbb9e30 Allow sorting in billing 2020-11-11 12:07:06 +01:00
Dennis
63d0cb9626 Default language setting & fixed norwegian keys 2020-11-11 10:58:19 +01:00
Dennis
e3bb3ae4d1 Merge branch 'develop' 2020-11-06 08:42:09 +01:00
Dennis
31890005ac Fix 2020-11-06 08:41:52 +01:00
Dennis
04a216dee1 Merge branch 'develop' 2020-11-05 11:21:40 +01:00
Dennis
5d403c1202 Fix currency displayer 2020-11-05 11:21:29 +01:00
Dennis
a2d92c67b3 Merge branch 'develop' 2020-11-04 14:00:41 +01:00
Dennis
0fec3d82a3 Ugly bug 2020-11-04 14:00:36 +01:00
Dennis
6530a64f97 Production mixed 2020-11-04 13:42:50 +01:00
Dennis
656f02d652 Merge branch 'develop'
# Conflicts:
#	public/js/0.js
#	public/js/13.js
#	public/js/14.js
#	public/js/18.js
#	public/js/20.js
#	public/js/21.js
#	public/js/22.js
#	public/js/23.js
#	public/js/24.js
#	public/js/25.js
#	public/js/26.js
#	public/js/27.js
#	public/js/28.js
#	public/js/29.js
#	public/js/30.js
#	public/js/31.js
#	public/js/32.js
#	public/js/33.js
#	public/js/34.js
#	public/js/35.js
#	public/js/36.js
#	public/js/37.js
#	public/js/38.js
#	public/js/39.js
#	public/js/40.js
#	public/js/41.js
#	public/js/42.js
#	public/js/43.js
#	public/js/44.js
#	public/js/45.js
#	public/js/46.js
#	public/js/47.js
#	public/js/48.js
#	public/js/49.js
#	public/js/50.js
#	public/js/51.js
#	public/js/52.js
#	public/js/53.js
#	public/js/54.js
#	public/js/55.js
#	public/js/56.js
#	public/js/57.js
#	public/js/58.js
#	public/js/59.js
#	public/js/60.js
#	public/js/61.js
#	public/js/62.js
#	public/js/63.js
#	public/js/64.js
#	public/js/65.js
#	public/js/66.js
#	public/js/67.js
#	public/js/68.js
#	public/js/69.js
#	public/js/70.js
#	public/js/app.js
2020-11-04 13:42:17 +01:00
Dennis
0dbf3bba4d Wip 2020-11-04 13:41:46 +01:00
Dennis
ea47c0c3c6 wip 2020-11-04 12:15:19 +01:00
Dennis
b4072c7892 wip 2020-10-27 10:05:52 +01:00
Dennis
e80cd1990a Added more currencies 2020-10-27 08:40:26 +01:00
Dennis
2585cc1db4 Production mix 2020-10-26 07:51:05 +01:00
Dennis
0225828445 Add Norwegian language 2020-10-26 07:49:58 +01:00
Dennis
63af93592d Keyboard shortcuts disable-able 2020-10-22 14:06:23 +02:00
Dennis
b87fcd0f25 Danish language 2020-10-22 11:54:27 +02:00
Dennis
23a6b3cc55 Tweaks 2020-10-21 09:39:44 +02:00
163 changed files with 4984 additions and 2444 deletions

View File

@@ -84,16 +84,46 @@ class Install extends Command
Package::create([
'name' => 'Basic',
'maximum_sites' => 5,
'site_permissions' => [
'create' => true,
'update' => true,
'delete' => true
],
'server_permissions' => [
'create' => false,
'update' => false,
'delete' => false
]
]);
Package::create([
'name' => 'Professional',
'maximum_sites' => 5,
'site_permissions' => [
'create' => true,
'update' => true,
'delete' => true
],
'server_permissions' => [
'create' => false,
'update' => false,
'delete' => false
]
]);
Package::create([
'name' => 'Unlimited',
'maximum_sites' => 0,
'site_permissions' => [
'create' => true,
'update' => true,
'delete' => true
],
'server_permissions' => [
'create' => false,
'update' => false,
'delete' => false
]
]);
}

View File

@@ -0,0 +1,69 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Models\DocumentationItem;
use App\Http\Controllers\Controller;
use App\Models\DocumentationCategory;
use App\Http\Requests\Admin\DocumentationArticleRequest;
class DocumentationArticleController extends Controller
{
public function index()
{
$articles = DocumentationItem::query()->with('category:id,title')->latest()->paginate();
return inertia('Admin/Documentation/Articles/Index', [
'articles' => $articles
]);
}
public function create()
{
$categories = DocumentationCategory::pluck('title', 'id');
return inertia('Admin/Documentation/Articles/Create', [
'categories' => $categories,
]);
}
public function store(DocumentationArticleRequest $request)
{
$article = DocumentationItem::create([
'title' => $request->input('title'),
'content' => $request->input('content')
]);
$article->documentation_category_id = $request->input('category_id');
$article->save();
return redirect()->route('admin.documentation.articles.index')->with('success', __('Documentation article has been created'));
}
public function edit($id)
{
$article = DocumentationItem::findOrFail($id);
$categories = DocumentationCategory::pluck('title', 'id');
return inertia('Admin/Documentation/Articles/Edit', [
'article' => $article,
'categories' => $categories
]);
}
public function update(DocumentationArticleRequest $request, $id)
{
$article = DocumentationItem::findOrFail($id);
$article->update([
'title' => $request->input('title'),
'content' => $request->input('content')
]);
$article->documentation_category_id = $request->input('category_id');
$article->save();
return redirect()->route('admin.documentation.articles.index')->with('success', __('Documentation article has been updated'));
}
}

View File

@@ -3,11 +3,53 @@
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\DocumentationCategory;
use App\Http\Requests\Admin\DocumentationCategoryRequest;
class DocumentationController extends Controller
{
public function index()
{
return inertia('Admin/Documentation/Index');
$categories = DocumentationCategory::query()->latest()->paginate();
return inertia('Admin/Documentation/Index', [
'categories' => $categories
]);
}
public function create()
{
return inertia('Admin/Documentation/Create');
}
public function store(DocumentationCategoryRequest $request)
{
DocumentationCategory::create([
'title' => $request->input('title'),
'description' => $request->input('description')
]);
return redirect()->route('admin.documentation.index')->with('success', __('Documentation category has been created'));
}
public function edit($id)
{
$category = DocumentationCategory::findOrFail($id);
return inertia('Admin/Documentation/Edit', [
'category' => $category
]);
}
public function update(DocumentationCategoryRequest $request, $id)
{
$category = DocumentationCategory::findOrFail($id);
$category->update([
'title' => $request->input('title'),
'description' => $request->input('description'),
]);
return redirect()->route('admin.documentation.index')->with('success', __('Documentation category has been updated'));
}
}

View File

@@ -25,4 +25,13 @@ class ProviderController extends Controller
return redirect()->route('admin.services.index')->with('success', __('Provider has been updated'));
}
public function destroy($id)
{
$provider = Provider::findOrFail($id);
$provider->delete();
return redirect()->route('admin.services.index')->with('success', __('Provider has been deleted'));
}
}

View File

@@ -19,15 +19,18 @@ class SettingController extends Controller
'allow_registration' => setting('allow_registration'),
'default_package' => setting('default_package'),
'receive_email_on_server_creation' => setting('receive_email_on_server_creation'),
'isolate_per_site_per_user' => setting('isolate_per_site_per_user'),
'enable_api' => setting('enable_api'),
'api_token' => setting('api_token') ? decrypt(setting('api_token')) : null,
'default_language' => setting('default_language', 'en')
];
$packages = Package::pluck('name', 'id');
return inertia('Admin/Settings', [
'company_settings' => $settings,
'packages' => $packages
'packages' => $packages,
'languages' => languages()
]);
}
@@ -42,8 +45,10 @@ class SettingController extends Controller
'documentation',
'default_package',
'receive_email_on_server_creation',
'isolate_per_site_per_user',
'enable_api',
'api_token',
'default_language'
]) as $key => $value) {
if ($key === 'api_token') {
$value = encrypt($value);

View File

@@ -31,7 +31,8 @@ class UserController extends Controller
return inertia('Admin/Users/Create', [
'packages' => $packages,
'languages' => languages(),
'defaultPackage' => (string)setting('default_package')
'defaultPackage' => (string)setting('default_package'),
'defaultLanguage' => (string)setting('default_language', 'en'),
]);
}
@@ -54,7 +55,7 @@ class UserController extends Controller
public function show($id)
{
//
// TODO: Implement show feature for a user
}
public function edit($id)

View File

@@ -5,41 +5,83 @@ namespace App\Http\Controllers\Profile;
use Carbon\Carbon;
use App\Models\User;
use App\Models\Package;
use Illuminate\Support\Arr;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Stripe\Exception\InvalidRequestException;
class ProfileBillingController extends Controller
{
public function index()
public function index(Request $request)
{
/* @var $user User */
$user = auth()->user();
$sortByType = array_key_first($request->input('sortBy', []));
$packages = Package::query()
->where(function ($query) {
return $query
->where('price_monthly', '>', 0)
->whereNotNull('plan_id');
})
->when($request->input('sortBy.' . $sortByType), function ($query, $value) use ($sortByType) {
if ($sortByType === 'price') {
return $value === 'asc'
? $query->orderBy('price_monthly', 'asc')
: $query->orderBy('price_monthly', 'desc');
}
if ($sortByType === 'servers') {
return $value === 'asc'
? $query->orderBy('maximum_servers', 'asc')
: $query->orderBy('maximum_servers', 'desc');
}
if ($sortByType === 'sites') {
return $value === 'asc'
? $query->orderBy('maximum_sites', 'asc')
: $query->orderBy('maximum_sites', 'desc');
}
if ($sortByType === 'name') {
return $value === 'asc'
? $query->orderBy('name', 'asc')
: $query->orderBy('name', 'desc');
}
return $query;
}, function ($query) {
return $query->orderBy('price_monthly', 'asc');
})
->get()
->transform(function (Package $package) {
$symbol = $package->currency === Package::CURRENCY_EURO ? '€' : '$';
$currencies = [
Package::CURRENCY_EURO => '€',
Package::CURRENCY_USD => '$',
Package::CURRENCY_NOK => 'KR ',
Package::CURRENCY_CAD => 'CAD $',
Package::CURRENCY_AUD => 'AUD $',
];
$package->price_monthly = $symbol . number_format($package->price_monthly, 2, ',', '.');
$package->price_monthly = ($currencies[$package->currency] ?? '[Unknown currency]') . number_format($package->price_monthly, 2, ',', '.');
return $package;
});
$intent = $user->createSetupIntent();
return inertia('Profile/Billing', [
'packages' => $packages,
'subscription' => $user->subscription('default'),
'public_key' => config('cashier.key'),
'data_client_secret' => $intent->client_secret,
'data_client_secret' => function () use ($user) {
$intent = $user->createSetupIntent();
return $intent->client_secret;
},
'card' => [
'last_four' => $user->card_last_four,
'brand' => $user->card_brand
],
'filters' => [
'sort' => [
$sortByType => $request->input('sortBy.' . $sortByType, 'asc'),
]
]
]);
}
@@ -84,18 +126,27 @@ class ProfileBillingController extends Controller
}
// If the user is already subscribed to the default plan, we have to swap it. Otherwise create a new one.
if ($user->subscribed('default')) {
$user->subscription('default')->swap($planId);
} else {
if ($coupon = $request->input('coupon')) {
$user->newSubscription('default', $planId)
->withCoupon($coupon)
->create($user->defaultPaymentMethod()->id);
try {
if ($user->subscribed('default')) {
$user->subscription('default')->swap($planId);
} else {
$user->newSubscription('default', $planId)->create($user->defaultPaymentMethod()->id);
if ($coupon = $request->input('coupon')) {
$user->newSubscription('default', $planId)
->withCoupon($coupon)
->create($user->defaultPaymentMethod()->id);
} else {
$user->newSubscription('default', $planId)->create($user->defaultPaymentMethod()->id);
}
}
} catch (InvalidRequestException $exception) {
$error = $exception->getJsonBody();
return redirect()->route('profile.billing.index')->with('error', Arr::get($error, 'error.message'));
}
$user->package_id = $plan->id;
$user->save();
return redirect()->route('profile.billing.index')->with('success', sprintf("Your plan has been updated to %s", $plan->name));
}

View File

@@ -4,7 +4,6 @@ namespace App\Http\Controllers\Profile;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use App\Http\Requests\UserProfileRequest;
use App\Http\Resources\UserProfileResource;
@@ -37,22 +36,4 @@ class ProfileController extends Controller
return $mode;
}
public function requestFtpPassword(Request $request)
{
$this->validate($request, ['password' => 'required|string']);
if (!Hash::check($request->input('password'), $request->user()->password)) {
return response([
'message' => 'The given data was invalid',
'errors' => [
'password' => [
trans('auth.failed')
]
]
], 422);
}
return ['ftp_password' => decrypt($request->user()->ftp_password)];
}
}

View File

@@ -12,7 +12,8 @@ class ProfileSettingController extends Controller
{
return inertia('Profile/Settings', [
'profile' => [
'theme' => auth()->user()->theme
'theme' => auth()->user()->theme,
'keyboard_shortcuts' => auth()->user()->keyboard_shortcuts,
]
]);
}
@@ -27,7 +28,10 @@ class ProfileSettingController extends Controller
]
]);
$request->user()->update(['theme' => $request->input('theme')]);
$request->user()->update([
'theme' => $request->input('theme'),
'keyboard_shortcuts' => $request->input('keyboard_shortcuts', true),
]);
return redirect()->route('profile.settings.index')->with('success', __('Instellingen zijn aangepast'));
}

View File

@@ -2,8 +2,6 @@
namespace App\Http\Controllers;
use App\Mail\Admin\Server\AdminServerCreatedEmail;
use App\Models\Server;
use App\Models\User;
use Illuminate\Http\Request;
use App\Jobs\Servers\CreateServer;
@@ -13,6 +11,7 @@ use Illuminate\Support\Facades\Mail;
use App\Http\Resources\ServerResource;
use App\Mail\Server\ServerCreatedEmail;
use App\Http\Requests\ServerUpdateRequest;
use App\Mail\Admin\Server\AdminServerCreatedEmail;
class ServerController extends Controller
{
@@ -54,7 +53,7 @@ class ServerController extends Controller
if (setting('receive_email_on_server_creation')) {
$admins = User::query()->where('role', User::ADMIN)->get();
foreach($admins as $admin){
foreach ($admins as $admin) {
Mail::to($admin)->send(new AdminServerCreatedEmail($request->user(), $server));
}
}

View File

@@ -3,12 +3,13 @@
namespace App\Http\Controllers;
use App\Models\Server;
use Illuminate\Support\Arr;
use Illuminate\Http\Request;
use App\Jobs\Sites\CreateSite;
use App\Jobs\Sites\DeleteSite;
use App\Http\Requests\SiteRequest;
use Illuminate\Support\Facades\DB;
use App\Http\Resources\SiteResource;
use Illuminate\Support\Facades\Hash;
class SiteController extends Controller
{
@@ -76,6 +77,7 @@ class SiteController extends Controller
return inertia('Sites/Show', [
'site' => $site,
'system_user' => $site->getSystemUser(false),
'ip_address' => $site->server->ip
]);
}
@@ -92,4 +94,28 @@ class SiteController extends Controller
return redirect()->route('sites.index')->with('success', __('Your website is deleted'));
}
public function requestFtpPassword(Request $request, $id)
{
if ($request->user()->requires_password_for_ftp) {
$this->validate($request, ['password' => 'required|string']);
if (!Hash::check($request->input('password'), $request->user()->password)) {
return response([
'message' => 'The given data was invalid',
'errors' => [
'password' => [
trans('auth.failed')
]
]
], 422);
}
}
$site = $request->user()->sites()->findOrFail($id);
$systemUser = $site->getSystemUser();
return ['ftp_password' => decrypt(Arr::get($systemUser, 'ftp_password'))];
}
}

View File

@@ -2,11 +2,11 @@
namespace App\Http\Middleware;
use Illuminate\Http\Request;
use Inertia\Middleware;
use Illuminate\Support\Arr;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;
use Inertia\Middleware;
class HandleInertiaRequests extends Middleware
{
@@ -32,7 +32,7 @@ class HandleInertiaRequests extends Middleware
public function share(Request $request)
{
return array_merge(parent::share($request), [
'auth' => function () use($request) {
'auth' => function () use ($request) {
$package = auth()->user()->package ?? [];
$can = $package ? [
@@ -57,6 +57,8 @@ class HandleInertiaRequests extends Middleware
'user_name' => Auth::user()->user_name,
'avatar' => Auth::user()->getGravatar(),
'theme' => Auth::user()->theme,
'keyboard_shortcuts' => Auth::user()->keyboard_shortcuts,
'requires_password_for_ftp' => Auth::user()->requires_password_for_ftp,
] : null,
'package' => auth()->user() && auth()->user()->package ? [
'name' => auth()->user()->package->name,

View File

@@ -0,0 +1,42 @@
<?php
namespace App\Http\Requests\Admin;
use Illuminate\Foundation\Http\FormRequest;
class DocumentationArticleRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return auth()->check() && auth()->user()->isAdmin();
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'title' => [
'required',
'string',
'max:255'
],
'content' => [
'required',
'min:2'
],
'category_id' => [
'required',
'exists:documentation_categories,id'
]
];
}
}

View File

@@ -0,0 +1,38 @@
<?php
namespace App\Http\Requests\Admin;
use Illuminate\Foundation\Http\FormRequest;
class DocumentationCategoryRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return auth()->check() && auth()->user()->isAdmin();
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'title' => [
'required',
'string',
'max:255'
],
'description' => [
'nullable',
'string'
]
];
}
}

View File

@@ -35,7 +35,10 @@ class PackageRequest extends FormRequest
'nullable',
Rule::in([
Package::CURRENCY_USD,
Package::CURRENCY_EURO
Package::CURRENCY_EURO,
Package::CURRENCY_NOK,
Package::CURRENCY_AUD,
Package::CURRENCY_CAD,
])
],
'maximum_sites' => [

View File

@@ -4,6 +4,7 @@ namespace App\Jobs\Sites;
use App\Models\Site;
use App\Services\Ploi\Ploi;
use Illuminate\Support\Arr;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
@@ -35,14 +36,14 @@ class CreateSite implements ShouldQueue
{
$ploi = new Ploi(config('services.ploi.token'));
$owner = $this->site->users()->first();
$systemUser = $this->site->getSystemUser();
$ploiSite = $ploi->server($this->site->server->ploi_id)->sites()->create(
$this->site->domain,
'/public',
'/',
$owner->user_name,
decrypt($owner->ftp_password)
Arr::get($systemUser, 'user_name'),
decrypt(Arr::get($systemUser, 'ftp_password'))
);
$this->site->ploi_id = $ploiSite->data->id;

View File

@@ -2,12 +2,12 @@
namespace App\Mail\Admin\Server;
use App\Models\Server;
use App\Models\User;
use App\Models\Server;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class AdminServerCreatedEmail extends Mailable implements ShouldQueue
{

View File

@@ -0,0 +1,18 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class DocumentationCategory extends Model
{
public $fillable = [
'title',
'description'
];
public function items()
{
return $this->hasMany(DocumentationItem::class);
}
}

View File

@@ -6,5 +6,13 @@ use Illuminate\Database\Eloquent\Model;
class DocumentationItem extends Model
{
//
public $fillable = [
'title',
'content'
];
public function category()
{
return $this->belongsTo(DocumentationCategory::class, 'documentation_category_id');
}
}

View File

@@ -9,6 +9,9 @@ class Package extends Model
{
const CURRENCY_EURO = 'eur';
const CURRENCY_USD = 'usd';
const CURRENCY_NOK = 'nok';
const CURRENCY_AUD = 'aud';
const CURRENCY_CAD = 'cad';
public $fillable = [
'name',

View File

@@ -38,4 +38,20 @@ class Provider extends Model
{
return $this->hasMany(Server::class);
}
public static function booted()
{
static::deleting(function(self $provider){
$provider->regions()->delete();
$provider->plans()->delete();
$provider->packages()->detach();
foreach($provider->servers as $server){
$server->provider_id = null;
$server->provider_plan_id = null;
$server->provider_region_id = null;
$server->save();
}
});
}
}

View File

@@ -65,6 +65,11 @@ class Site extends Model
return $this->morphMany(SystemLog::class, 'model');
}
public function systemUsers()
{
return $this->belongsToMany(SiteSystemUser::class, 'site_system_user_attached');
}
protected function serializeDate(DateTimeInterface $date)
{
return $date->format('Y-m-d H:i:s');
@@ -75,12 +80,42 @@ class Site extends Model
return $this->status === self::STATUS_ACTIVE;
}
public function getSystemUser($withPassword = true)
{
if (setting('isolate_per_site_per_user') && $this->systemUsers()->first()) {
$user = $this->systemUsers()->first();
} else {
$user = $this->users()->first();
}
return [
'user_name' => $user->user_name,
] + ($withPassword ? ['ftp_password' => $user->ftp_password] : []);
}
public static function booted()
{
static::created(function (self $site) {
$site->systemUsers()->create();
});
static::deleting(function (self $site) {
foreach ($site->databases as $database) {
$database->delete();
}
$ids = $site->systemUsers->pluck('id');
// Detach all db users
$site->systemUsers()->detach();
// Loop through ids an remove old users.
foreach ($ids as $id) {
$record = SiteSystemUser::find($id);
if ($record) {
$record->delete();
}
}
$site->redirects()->delete();
$site->cronjobs()->delete();
$site->certificates()->delete();

View File

@@ -0,0 +1,37 @@
<?php
namespace App\Models;
use App\Casts\Encrypted;
use Illuminate\Support\Str;
use Illuminate\Database\Eloquent\Model;
class SiteSystemUser extends Model
{
public $fillable = [
'user_name',
'ftp_password'
];
protected $casts = [
'ftp_password' => Encrypted::class,
];
public function site()
{
return $this->belongsToMany(Site::class, 'site_system_user_attached');
}
public function user()
{
return $this->belongsTo(User::class);
}
protected static function booted()
{
static::creating(function (self $siteSystemUser) {
$siteSystemUser->user_name = strtolower(Str::random(10));
$siteSystemUser->ftp_password = Str::random();
});
}
}

View File

@@ -31,7 +31,9 @@ class User extends Authenticatable implements HasLocalePreference
'notes',
'language',
'blocked',
'theme'
'theme',
'keyboard_shortcuts',
'requires_password_for_ftp'
];
protected $hidden = [
@@ -43,6 +45,8 @@ class User extends Authenticatable implements HasLocalePreference
protected $casts = [
'email_verified_at' => 'datetime',
'ftp_password' => Encrypted::class,
'keyboard_shortcuts' => 'boolean',
'requires_password_for_ftp' => 'boolean'
];
protected $appends = [
@@ -120,6 +124,10 @@ class User extends Authenticatable implements HasLocalePreference
static::creating(function (self $user) {
$user->user_name = strtolower(Str::random(10));
$user->ftp_password = Str::random();
if (!$user->language) {
$user->language = setting('default_language', 'en');
}
});
static::created(function (self $user) {

View File

@@ -83,7 +83,7 @@ class Resource
return $this->server;
}
public function setServer(Server $server): self
public function setServer(Server $server)
{
$this->server = $server;

View File

@@ -43,7 +43,7 @@ class Site extends Resource
return $this->server;
}
public function setServer(Server $server): self
public function setServer(Server $server)
{
$this->server = $server;

View File

@@ -17,7 +17,7 @@ return [
|
*/
'default' => env('LOG_CHANNEL', 'daily'),
'default' => env('LOG_CHANNEL', 'stack'),
/*
|--------------------------------------------------------------------------
@@ -36,8 +36,8 @@ return [
'channels' => [
'stack' => [
'driver' => 'daily',
'channels' => ['single'],
'driver' => 'stack',
'channels' => ['daily'],
'ignore_exceptions' => false,
],

View File

@@ -0,0 +1,32 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddKeyboardShortcutsToUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->boolean('keyboard_shortcuts')->default(true)->after('blocked');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('keyboard_shortcuts');
});
}
}

View File

@@ -0,0 +1,44 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateDocumentationCategoriesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('documentation_categories', function (Blueprint $table) {
$table->id();
$table->string('title')->nullable();
$table->text('description')->nullable();
$table->timestamps();
});
Schema::table('documentation_items', function (Blueprint $table) {
$table->bigInteger('documentation_category_id')->after('content')->unsigned()->nullable();
$table->foreign('documentation_category_id')->references('id')->on('documentation_categories');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('documentation_categories');
Schema::table('documentation_items', function (Blueprint $table) {
$table->dropColumn('documentation_category_id');
});
}
}

View File

@@ -0,0 +1,35 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateSiteSystemUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('site_system_users', function (Blueprint $table) {
$table->id();
$table->string('user_name')->nullable();
$table->text('ftp_password')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('site_system_users');
}
}

View File

@@ -0,0 +1,34 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateSiteSystemUserAttached extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('site_system_user_attached', function (Blueprint $table) {
$table->bigInteger('site_id')->unsigned()->nullable();
$table->foreign('site_id')->references('id')->on('sites');
$table->bigInteger('site_system_user_id')->unsigned()->nullable();
$table->foreign('site_system_user_id')->references('id')->on('site_system_users');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('site_system_user_attached');
}
}

View File

@@ -0,0 +1,32 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddRequiresPasswordForFtpToUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->boolean('requires_password_for_ftp')->after('blocked')->default(true);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('requires_password_for_ftp');
});
}
}

6
package-lock.json generated
View File

@@ -9031,9 +9031,9 @@
}
},
"tailwindcss": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-1.9.1.tgz",
"integrity": "sha512-3faxlyPlcWN8AoNEIVQFNsDcrdXS/D9nOGtdknrXvZp4D4E3AGPO2KRPiGG69B2ZUO0V6RvYiW91L2/n9QnBxg==",
"version": "1.9.6",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-1.9.6.tgz",
"integrity": "sha512-nY8WYM/RLPqGsPEGEV2z63riyQPcHYZUJpAwdyBzVpxQHOHqHE+F/fvbCeXhdF1+TA5l72vSkZrtYCB9hRcwkQ==",
"dev": true,
"requires": {
"@fullhuman/postcss-purgecss": "^2.1.2",

View File

@@ -24,7 +24,7 @@
"resolve-url-loader": "^3.1.0",
"sass": "^1.15.2",
"sass-loader": "^8.0.0",
"tailwindcss": "^1.9.0",
"tailwindcss": "^1.9.6",
"v-click-outside": "^3.0.1",
"vue": "^2.6.11",
"vue-clipboard2": "^0.3.1",

2
public/css/app.css vendored

File diff suppressed because one or more lines are too long

2
public/js/0.js vendored

File diff suppressed because one or more lines are too long

2
public/js/1.js vendored

File diff suppressed because one or more lines are too long

2
public/js/10.js vendored

File diff suppressed because one or more lines are too long

2
public/js/11.js vendored

File diff suppressed because one or more lines are too long

2
public/js/12.js vendored

File diff suppressed because one or more lines are too long

2
public/js/13.js vendored

File diff suppressed because one or more lines are too long

2
public/js/14.js vendored

File diff suppressed because one or more lines are too long

2
public/js/15.js vendored

File diff suppressed because one or more lines are too long

2
public/js/16.js vendored

File diff suppressed because one or more lines are too long

2
public/js/17.js vendored

File diff suppressed because one or more lines are too long

2
public/js/18.js vendored

File diff suppressed because one or more lines are too long

2
public/js/19.js vendored

File diff suppressed because one or more lines are too long

2
public/js/2.js vendored

File diff suppressed because one or more lines are too long

2
public/js/20.js vendored

File diff suppressed because one or more lines are too long

2
public/js/21.js vendored

File diff suppressed because one or more lines are too long

2
public/js/22.js vendored

File diff suppressed because one or more lines are too long

2
public/js/23.js vendored

File diff suppressed because one or more lines are too long

2
public/js/24.js vendored

File diff suppressed because one or more lines are too long

2
public/js/25.js vendored

File diff suppressed because one or more lines are too long

2
public/js/26.js vendored

File diff suppressed because one or more lines are too long

2
public/js/27.js vendored

File diff suppressed because one or more lines are too long

2
public/js/28.js vendored

File diff suppressed because one or more lines are too long

2
public/js/29.js vendored

File diff suppressed because one or more lines are too long

2
public/js/3.js vendored

File diff suppressed because one or more lines are too long

2
public/js/30.js vendored

File diff suppressed because one or more lines are too long

2
public/js/31.js vendored

File diff suppressed because one or more lines are too long

2
public/js/32.js vendored

File diff suppressed because one or more lines are too long

2
public/js/33.js vendored

File diff suppressed because one or more lines are too long

2
public/js/34.js vendored

File diff suppressed because one or more lines are too long

2
public/js/35.js vendored

File diff suppressed because one or more lines are too long

2
public/js/36.js vendored

File diff suppressed because one or more lines are too long

2
public/js/37.js vendored

File diff suppressed because one or more lines are too long

2
public/js/38.js vendored

File diff suppressed because one or more lines are too long

2
public/js/39.js vendored

File diff suppressed because one or more lines are too long

2
public/js/4.js vendored

File diff suppressed because one or more lines are too long

2
public/js/40.js vendored

File diff suppressed because one or more lines are too long

2
public/js/41.js vendored

File diff suppressed because one or more lines are too long

2
public/js/42.js vendored

File diff suppressed because one or more lines are too long

2
public/js/43.js vendored

File diff suppressed because one or more lines are too long

2
public/js/44.js vendored

File diff suppressed because one or more lines are too long

2
public/js/45.js vendored

File diff suppressed because one or more lines are too long

2
public/js/46.js vendored

File diff suppressed because one or more lines are too long

2
public/js/47.js vendored

File diff suppressed because one or more lines are too long

2
public/js/48.js vendored

File diff suppressed because one or more lines are too long

2
public/js/49.js vendored

File diff suppressed because one or more lines are too long

2
public/js/5.js vendored

File diff suppressed because one or more lines are too long

2
public/js/50.js vendored

File diff suppressed because one or more lines are too long

2
public/js/51.js vendored

File diff suppressed because one or more lines are too long

2
public/js/52.js vendored

File diff suppressed because one or more lines are too long

2
public/js/53.js vendored

File diff suppressed because one or more lines are too long

2
public/js/54.js vendored

File diff suppressed because one or more lines are too long

2
public/js/55.js vendored

File diff suppressed because one or more lines are too long

2
public/js/56.js vendored

File diff suppressed because one or more lines are too long

2
public/js/57.js vendored

File diff suppressed because one or more lines are too long

2
public/js/58.js vendored

File diff suppressed because one or more lines are too long

2
public/js/59.js vendored

File diff suppressed because one or more lines are too long

2
public/js/6.js vendored

File diff suppressed because one or more lines are too long

2
public/js/60.js vendored

File diff suppressed because one or more lines are too long

2
public/js/61.js vendored

File diff suppressed because one or more lines are too long

2
public/js/62.js vendored

File diff suppressed because one or more lines are too long

2
public/js/63.js vendored

File diff suppressed because one or more lines are too long

2
public/js/64.js vendored
View File

@@ -1 +1 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[64],{0:function(t,e,n){"use strict";function s(t,e,n,s,i,r,o,a){var c,u="function"==typeof t?t.options:t;if(e&&(u.render=e,u.staticRenderFns=n,u._compiled=!0),s&&(u.functional=!0),r&&(u._scopeId="data-v-"+r),o?(c=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),i&&i.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(o)},u._ssrRegister=c):i&&(c=a?function(){i.call(this,(u.functional?this.parent:this).$root.$options.shadowRoot)}:i),c)if(u.functional){u._injectStyles=c;var d=u.render;u.render=function(t,e){return c.call(e),d(t,e)}}else{var l=u.beforeCreate;u.beforeCreate=l?[].concat(l,c):[c]}return{exports:t,options:u}}n.d(e,"a",(function(){return s}))},82:function(t,e,n){"use strict";n.r(e);var s={data:function(){return{items:[{title:this.__("Overview"),to:this.route("admin.status.index"),active:this.route().current("admin.status.index")}]}}},i=n(0),r=Object(i.a)(s,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("ul",{staticClass:"-ml-4 space-y-1"},t._l(t.items,(function(e){return n("li",[n("inertia-link",{staticClass:"flex items-center h-10 px-4 font-medium text-medium-emphasis",class:{"rounded shadow text-primary bg-surface-3":e.active},attrs:{href:e.to}},[t._v(t._s(e.title)+" "+t._s(e.route))])],1)})),0)}),[],!1,null,null,null);e.default=r.exports}}]);
(window.webpackJsonp=window.webpackJsonp||[]).push([[64],{0:function(t,e,n){"use strict";function i(t,e,n,i,r,o,a,s){var c,u="function"==typeof t?t.options:t;if(e&&(u.render=e,u.staticRenderFns=n,u._compiled=!0),i&&(u.functional=!0),o&&(u._scopeId="data-v-"+o),a?(c=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),r&&r.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(a)},u._ssrRegister=c):r&&(c=s?function(){r.call(this,(u.functional?this.parent:this).$root.$options.shadowRoot)}:r),c)if(u.functional){u._injectStyles=c;var d=u.render;u.render=function(t,e){return c.call(e),d(t,e)}}else{var l=u.beforeCreate;u.beforeCreate=l?[].concat(l,c):[c]}return{exports:t,options:u}}n.d(e,"a",(function(){return i}))},43:function(t,e,n){"use strict";n.r(e);var i={data:function(){return{items:[{title:this.__("Categories"),to:this.route("admin.documentation.index"),active:this.route().current("admin.documentation.index")},{title:this.__("Create category"),to:this.route("admin.documentation.create"),active:this.route().current("admin.documentation.create")},{title:this.__("Articles"),to:this.route("admin.documentation.articles.index"),active:this.route().current("admin.documentation.articles.index")},{title:this.__("Create article"),to:this.route("admin.documentation.articles.create"),active:this.route().current("admin.documentation.articles.create")}]}}},r=n(0),o=Object(r.a)(i,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("ul",{staticClass:"-ml-4 space-y-1"},t._l(t.items,(function(e){return n("li",[n("inertia-link",{staticClass:"flex items-center h-10 px-4 font-medium text-medium-emphasis",class:{"rounded shadow text-primary bg-surface-3":e.active},attrs:{href:e.to}},[t._v(t._s(e.title)+" "+t._s(e.route)+"\n ")])],1)})),0)}),[],!1,null,null,null);e.default=o.exports}}]);

2
public/js/65.js vendored
View File

@@ -1 +1 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[65],{0:function(t,e,n){"use strict";function s(t,e,n,s,i,r,o,a){var u,c="function"==typeof t?t.options:t;if(e&&(c.render=e,c.staticRenderFns=n,c._compiled=!0),s&&(c.functional=!0),r&&(c._scopeId="data-v-"+r),o?(u=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),i&&i.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(o)},c._ssrRegister=u):i&&(u=a?function(){i.call(this,(c.functional?this.parent:this).$root.$options.shadowRoot)}:i),u)if(c.functional){c._injectStyles=u;var d=c.render;c.render=function(t,e){return u.call(e),d(t,e)}}else{var l=c.beforeCreate;c.beforeCreate=l?[].concat(l,u):[u]}return{exports:t,options:c}}n.d(e,"a",(function(){return s}))},56:function(t,e,n){"use strict";n.r(e);var s={data:function(){return{items:[{title:this.__("Overview"),to:this.route("admin.users.index"),active:this.route().current("admin.users.index")},{title:this.__("Create"),to:this.route("admin.users.create"),active:this.route().current("admin.users.create")}]}}},i=n(0),r=Object(i.a)(s,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("ul",{staticClass:"-ml-4 space-y-1"},t._l(t.items,(function(e){return n("li",[n("inertia-link",{staticClass:"flex items-center h-10 px-4 font-medium text-medium-emphasis",class:{"rounded shadow text-primary bg-surface-3":e.active},attrs:{href:e.to}},[t._v(t._s(e.title)+" "+t._s(e.route))])],1)})),0)}),[],!1,null,null,null);e.default=r.exports}}]);
(window.webpackJsonp=window.webpackJsonp||[]).push([[65],{0:function(t,e,n){"use strict";function i(t,e,n,i,s,r,a,o){var c,u="function"==typeof t?t.options:t;if(e&&(u.render=e,u.staticRenderFns=n,u._compiled=!0),i&&(u.functional=!0),r&&(u._scopeId="data-v-"+r),a?(c=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),s&&s.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(a)},u._ssrRegister=c):s&&(c=o?function(){s.call(this,(u.functional?this.parent:this).$root.$options.shadowRoot)}:s),c)if(u.functional){u._injectStyles=c;var d=u.render;u.render=function(t,e){return c.call(e),d(t,e)}}else{var l=u.beforeCreate;u.beforeCreate=l?[].concat(l,c):[c]}return{exports:t,options:u}}n.d(e,"a",(function(){return i}))},56:function(t,e,n){"use strict";n.r(e);var i={data:function(){return{items:[{title:this.__("Overview"),to:this.route("admin.packages.index"),active:this.route().current("admin.packages.index")},{title:this.__("Create"),to:this.route("admin.packages.create"),active:this.route().current("admin.packages.create")}]}}},s=n(0),r=Object(s.a)(i,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("ul",{staticClass:"-ml-4 space-y-1"},t._l(t.items,(function(e){return n("li",[n("inertia-link",{staticClass:"flex items-center h-10 px-4 font-medium text-medium-emphasis",class:{"rounded shadow text-primary bg-surface-3":e.active},attrs:{href:e.to}},[t._v(t._s(e.title)+" "+t._s(e.route))])],1)})),0)}),[],!1,null,null,null);e.default=r.exports}}]);

2
public/js/66.js vendored
View File

@@ -1 +1 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[66],{0:function(e,t,n){"use strict";function a(e,t,n,a,o,r,s,i){var c,d="function"==typeof e?e.options:e;if(t&&(d.render=t,d.staticRenderFns=n,d._compiled=!0),a&&(d.functional=!0),r&&(d._scopeId="data-v-"+r),s?(c=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),o&&o.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(s)},d._ssrRegister=c):o&&(c=i?function(){o.call(this,(d.functional?this.parent:this).$root.$options.shadowRoot)}:o),c)if(d.functional){d._injectStyles=c;var u=d.render;d.render=function(e,t){return c.call(t),u(e,t)}}else{var l=d.beforeCreate;d.beforeCreate=l?[].concat(l,c):[c]}return{exports:e,options:d}}n.d(t,"a",(function(){return a}))},149:function(e,t,n){"use strict";n.r(t);var a=n(1),o=n(6),r=n(7),s=n(8),i=n(9),c=n(10),d=n(2),u=n(11),l=n(12),p=n(4),f=n(5),_={layout:n(3).a,components:{Container:a.a,Content:o.a,Page:r.a,PageHeader:s.a,PageHeaderTitle:i.a,PageBody:c.a,Button:d.a,List:u.a,ListItem:l.a,StatusBubble:p.a,NotificationBadge:f.a}},v=n(0),h=Object(v.a)(_,(function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("Page",[n("Content",[n("Container",[n("PageHeader",{scopedSlots:e._u([{key:"start",fn:function(){return[n("PageHeaderTitle",[e._v("Page not found")])]},proxy:!0}])}),e._v(" "),n("PageBody",[n("div",{staticClass:"space-y-4"},[n("p",[e._v("We were unable to find this page.")]),e._v(" "),n("p",[n("a",{staticClass:"text-primary",attrs:{href:"/"}},[e._v("Go home")])])])])],1)],1)],1)}),[],!1,null,null,null);t.default=h.exports}}]);
(window.webpackJsonp=window.webpackJsonp||[]).push([[66],{0:function(e,t,i){"use strict";function n(e,t,i,n,r,s,o,a){var c,d="function"==typeof e?e.options:e;if(t&&(d.render=t,d.staticRenderFns=i,d._compiled=!0),n&&(d.functional=!0),s&&(d._scopeId="data-v-"+s),o?(c=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),r&&r.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(o)},d._ssrRegister=c):r&&(c=a?function(){r.call(this,(d.functional?this.parent:this).$root.$options.shadowRoot)}:r),c)if(d.functional){d._injectStyles=c;var u=d.render;d.render=function(e,t){return c.call(t),u(e,t)}}else{var l=d.beforeCreate;d.beforeCreate=l?[].concat(l,c):[c]}return{exports:e,options:d}}i.d(t,"a",(function(){return n}))},38:function(e,t,i){"use strict";i.r(t);var n={data:function(){return{items:[{title:this.__("Overview"),to:this.route("admin.services.index"),active:this.route().current("admin.services.index")},{title:this.__("Synchronize servers"),to:this.route("admin.services.servers.index"),active:this.route().current("admin.services.servers.index")},{title:this.__("Synchronize providers"),to:this.route("admin.services.providers.index"),active:this.route().current("admin.services.providers.index")}]}}},r=i(0),s=Object(r.a)(n,(function(){var e=this,t=e.$createElement,i=e._self._c||t;return i("ul",{staticClass:"-ml-4 space-y-1"},e._l(e.items,(function(t){return i("li",[i("inertia-link",{staticClass:"flex items-center h-10 px-4 font-medium text-medium-emphasis",class:{"rounded shadow text-primary bg-surface-3":t.active},attrs:{href:t.to}},[e._v(e._s(t.title)+" "+e._s(t.route))])],1)})),0)}),[],!1,null,null,null);t.default=s.exports}}]);

2
public/js/67.js vendored
View File

@@ -1 +1 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[67],{0:function(t,e,s){"use strict";function n(t,e,s,n,r,i,o,a){var c,u="function"==typeof t?t.options:t;if(e&&(u.render=e,u.staticRenderFns=s,u._compiled=!0),n&&(u.functional=!0),i&&(u._scopeId="data-v-"+i),o?(c=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),r&&r.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(o)},u._ssrRegister=c):r&&(c=a?function(){r.call(this,(u.functional?this.parent:this).$root.$options.shadowRoot)}:r),c)if(u.functional){u._injectStyles=c;var l=u.render;u.render=function(t,e){return c.call(e),l(t,e)}}else{var p=u.beforeCreate;u.beforeCreate=p?[].concat(p,c):[c]}return{exports:t,options:u}}s.d(e,"a",(function(){return n}))},67:function(t,e,s){"use strict";s.r(e);var n={props:{server:Object},data:function(){return{items:[{title:this.__("General"),to:this.route("servers.show",this.server.id),active:this.route().current("servers.show")},{title:this.__("Settings"),to:this.route("servers.settings.show",this.server.id),active:this.route().current("servers.settings.show")}]}}},r=s(0),i=Object(r.a)(n,(function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("ul",{staticClass:"-ml-4 space-y-1"},t._l(t.items,(function(e){return e?s("li",[s(e.type&&"a"===e.type?"a":"inertia-link",{tag:"component",staticClass:"flex items-center h-10 px-4 font-medium text-medium-emphasis",class:{"rounded shadow text-primary bg-surface-3":e.active},attrs:{target:e.type&&"a"===e.type?"_blank":"_self",href:e.to}},[t._v(t._s(e.title)+" "+t._s(e.route))])],1):t._e()})),0)}),[],!1,null,null,null);e.default=i.exports}}]);
(window.webpackJsonp=window.webpackJsonp||[]).push([[67],{0:function(t,e,n){"use strict";function i(t,e,n,i,s,r,o,a){var c,u="function"==typeof t?t.options:t;if(e&&(u.render=e,u.staticRenderFns=n,u._compiled=!0),i&&(u.functional=!0),r&&(u._scopeId="data-v-"+r),o?(c=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),s&&s.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(o)},u._ssrRegister=c):s&&(c=a?function(){s.call(this,(u.functional?this.parent:this).$root.$options.shadowRoot)}:s),c)if(u.functional){u._injectStyles=c;var d=u.render;u.render=function(t,e){return c.call(e),d(t,e)}}else{var l=u.beforeCreate;u.beforeCreate=l?[].concat(l,c):[c]}return{exports:t,options:u}}n.d(e,"a",(function(){return i}))},84:function(t,e,n){"use strict";n.r(e);var i={data:function(){return{items:[{title:this.__("Overview"),to:this.route("admin.support.index"),active:this.route().current("admin.support.index")}]}}},s=n(0),r=Object(s.a)(i,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("ul",{staticClass:"-ml-4 space-y-1"},t._l(t.items,(function(e){return n("li",[n("inertia-link",{staticClass:"flex items-center h-10 px-4 font-medium text-medium-emphasis",class:{"rounded shadow text-primary bg-surface-3":e.active},attrs:{href:e.to}},[t._v(t._s(e.title)+" "+t._s(e.route))])],1)})),0)}),[],!1,null,null,null);e.default=r.exports}}]);

Some files were not shown because too many files have changed in this diff Show More