first commit

This commit is contained in:
2026-10-09 08:21:06 +02:00
parent db7456df87
commit d259c62304
3761 changed files with 896046 additions and 0 deletions
+59
View File
@@ -0,0 +1,59 @@
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title inertia>{{ setting('app_name') }}</title>
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="{{ url('assets/img/icons/apple-touch-icon-144x144.png') }}" />
<link rel="apple-touch-icon-precomposed" sizes="152x152" href="{{ url('assets/img/icons/apple-touch-icon-152x152.png') }}" />
<link rel="icon" type="image/png" href="{{ url('assets/img/icons/favicon-32x32.png') }}" sizes="32x32" />
<link rel="icon" type="image/png" href="{{ url('assets/img/icons/favicon-16x16.png') }}" sizes="16x16" />
<meta name="application-name" content="{{ setting('app_name') }}"/>
<meta name="msapplication-TileColor" content="#FFFFFF" />
<meta name="msapplication-TileImage" content="{{ url('assets/img/icons/mstile-144x144.png') }}" />
{{-- Icon font. Kept as a static asset so plugin authors can keep using
Item::icon('fas fa-server') without pulling Font Awesome through npm. --}}
<link media="all" type="text/css" rel="stylesheet" href="{{ url('assets/css/fontawesome-all.min.css') }}">
{{--
Registration queue for plugin bundles. Installed before anything else so
a plugin script may call Vanguard.plugin() whether it loads before or
after the app bundle; resources/js/vanguard.ts drains the queue on boot.
--}}
<script>
window.Vanguard = window.Vanguard || { _q: [] };
window.Vanguard.plugin = window.Vanguard.plugin || function () {
window.Vanguard._q.push(arguments);
};
</script>
@foreach (\Vanguard\Plugins\Vanguard::assets() as $asset)
@if (! empty($asset['css']))
<link media="all" type="text/css" rel="stylesheet" href="{{ $asset['css'] }}">
@endif
@endforeach
{{--
Ziggy's route list, emitted once per full page load as window.Ziggy.
The ZiggyVue plugin reads it from there, so the ~10KB payload does not
have to ride along with every Inertia navigation as a shared prop.
--}}
@routes
@vite('resources/js/app.ts')
@inertiaHead
</head>
<body>
@inertia
@foreach (\Vanguard\Plugins\Vanguard::assets() as $asset)
@if (! empty($asset['js']))
<script type="module" src="{{ $asset['js'] }}"></script>
@endif
@endforeach
</body>
</html>
@@ -0,0 +1,14 @@
@props(['href' => null, 'disabled' => false])
@php
$classes = 'inline-flex cursor-pointer items-center gap-2 rounded-md bg-primary-600 px-4 py-2 font-medium'
.' text-white transition-colors hover:bg-primary-700 focus-visible:outline-2'
.' focus-visible:outline-offset-2 focus-visible:outline-primary-600'
.' disabled:pointer-events-none disabled:opacity-60';
@endphp
@if ($href && ! $disabled)
<a href="{{ $href }}" {{ $attributes->merge(['class' => $classes]) }}>{{ $slot }}</a>
@else
<button {{ $attributes->merge(['class' => $classes]) }} @disabled($disabled)>{{ $slot }}</button>
@endif
@@ -0,0 +1,7 @@
@props(['title'])
<div class="rounded-lg border border-slate-200 bg-white p-6 shadow-sm">
<h3 class="mb-4 border-b border-slate-100 pb-4 text-xl font-medium text-slate-800">{{ $title }}</h3>
{{ $slot }}
</div>
@@ -0,0 +1,23 @@
@props(['name', 'label', 'type' => 'text', 'hint' => null, 'value' => ''])
<div>
<label for="{{ $name }}" class="mb-1 block text-slate-700">{{ $label }}</label>
<input
type="{{ $type }}"
id="{{ $name }}"
name="{{ $name }}"
{{-- Passwords are never echoed back into the form. --}}
value="{{ $type === 'password' ? '' : old($name, $value) }}"
@class([
'bg-field block w-full rounded-md border px-3 py-2 text-slate-700 shadow-xs',
'transition-colors focus:outline-none focus:ring-2',
'border-red-500 focus:border-red-500 focus:ring-red-100' => $errors->has($name),
'border-slate-300 focus:border-primary-500 focus:ring-primary-100' => ! $errors->has($name),
])
>
<small @class(['mt-1 block', 'text-red-600' => $errors->has($name), 'text-slate-500' => ! $errors->has($name)])>
{{ $errors->first($name) ?: $hint }}
</small>
</div>
@@ -0,0 +1,4 @@
<img src="{{ $src ?? '' }}"
class="{{ $class ?? '' }}"
alt="{{ setting('app_name') }}"
height="{{ $height ?? '50' }}">
@@ -0,0 +1,37 @@
@extends('layouts.install')
@section('content')
@include('install.steps', ['steps' => [
'welcome' => 'selected done',
'requirements' => 'selected done',
'permissions' => 'selected done',
'database' => 'selected done',
'installation' => 'selected done',
'complete' => 'selected'
]])
<x-install.card title="Complete!">
<div class="space-y-2">
<p><strong>Well Done!</strong></p>
<p>You application is now successfully installed! You can login by clicking on "Log In" button below.</p>
@if (is_writable(base_path()))
<div class="flex items-start gap-2 rounded-md border border-amber-200 bg-amber-50 px-4 py-3 text-amber-800">
<i class="fa fa-exclamation-triangle mt-1 shrink-0" aria-hidden="true"></i>
<p>
<strong>Important!</strong> Since your root directory is still writable,
you can change the permissions to 755 to make it writable only by root user.
</p>
</div>
@endif
</div>
<div class="mt-6 flex justify-end">
<x-install.button :href="url('login')">
<i class="fa fa-sign-in" aria-hidden="true"></i>
Log In
</x-install.button>
</div>
</x-install.card>
@stop
@@ -0,0 +1,67 @@
@extends('layouts.install')
@section('content')
@include('install.steps', ['steps' => [
'welcome' => 'selected done',
'requirements' => 'selected done',
'permissions' => 'selected done',
'database' => 'selected'
]])
@if ($errors->any())
<div class="mb-4 rounded-md border border-red-200 bg-red-50 px-4 py-3 text-red-800" role="alert">
<ul class="space-y-1">
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form action="{{ route('install.installation') }}" method="POST">
@csrf
<x-install.card title="Database Info">
<div class="space-y-4">
<x-install.field
name="host"
label="Host"
hint="Database host. Usually you should enter localhost or mysql."
/>
<x-install.field
name="username"
label="Username"
hint="Your database username."
/>
<x-install.field
name="password"
label="Password"
type="password"
hint="Database password for provided username."
/>
<x-install.field
name="database"
label="Database Name"
hint="Name of database where tables should be created."
/>
<x-install.field
name="prefix"
label="Tables Prefix"
hint="Prefix to put in front of database table names. You can leave it blank if you want."
/>
</div>
<div class="mt-6 flex justify-end">
<x-install.button type="submit">
Next
<i class="fa fa-arrow-right" aria-hidden="true"></i>
</x-install.button>
</div>
</x-install.card>
</form>
@stop
+31
View File
@@ -0,0 +1,31 @@
@extends('layouts.install')
@section('content')
@include('install.steps', ['steps' => [
'welcome' => 'selected done',
'requirements' => 'selected done',
'permissions' => 'selected done',
'database' => 'selected done',
'installation' => 'selected done',
'complete' => 'selected error'
]])
<x-install.card title="Whoops!">
<div class="space-y-2">
<p><strong>There was something wrong during the installation!</strong></p>
<p>
Please check your log located inside
<code class="rounded bg-slate-100 px-1.5 py-0.5">storage/logs</code>
directory to see what's going on.
</p>
</div>
<div class="mt-6 flex justify-end">
<x-install.button :href="route('install.start')">
<i class="fa fa-undo" aria-hidden="true"></i>
Try Again
</x-install.button>
</div>
</x-install.card>
@stop
@@ -0,0 +1,32 @@
@extends('layouts.install')
@section('content')
@include('install.steps', ['steps' => [
'welcome' => 'selected done',
'requirements' => 'selected done',
'permissions' => 'selected done',
'database' => 'selected done',
'installation' => 'selected'
]])
<form action="{{ route('install.install') }}" method="POST">
@csrf
<x-install.card title="Installation">
<div class="mb-4 space-y-2">
<p>Vanguard is ready to be installed!</p>
<p>Before you proceed, please provide the name for your application below:</p>
</div>
<x-install.field name="app_name" label="App Name" value="Vanguard" />
<div class="mt-6 flex justify-end">
<x-install.button type="submit" data-loading-text="Installing...">
<i class="fa fa-play" aria-hidden="true"></i>
Install
</x-install.button>
</div>
</x-install.card>
</form>
@stop
@@ -0,0 +1,35 @@
@extends('layouts.install')
@section('content')
@include('install.steps', ['steps' => [
'welcome' => 'selected done',
'requirements' => 'selected done',
'permissions' => 'selected'
]])
<x-install.card title="Permissions">
<ul class="mb-6 divide-y divide-slate-100 rounded-md border border-slate-200">
@foreach($folders as $path => $isWritable)
<li class="flex items-center justify-between gap-3 px-4 py-3 {{ ! $isWritable ? 'bg-red-50 text-red-800' : '' }}">
<span class="break-all">{{ $path }}</span>
<span class="flex shrink-0 items-center gap-2">
<span class="flex size-6 items-center justify-center rounded-full text-xs text-white {{ $isWritable ? 'bg-green-600' : 'bg-red-600' }}">
<i class="fa {{ $isWritable ? 'fa-check' : 'fa-times' }}" aria-hidden="true"></i>
</span>
<span class="rounded-full bg-slate-200 px-2 py-0.5 text-xs font-semibold text-slate-600">775</span>
</span>
</li>
@endforeach
</ul>
<div class="flex justify-end">
<x-install.button :href="route('install.database')">
Next
<i class="fa fa-arrow-right" aria-hidden="true"></i>
</x-install.button>
</div>
</x-install.card>
@stop
@@ -0,0 +1,37 @@
@extends('layouts.install')
@section('content')
@include('install.steps', ['steps' => ['welcome' => 'selected done', 'requirements' => 'selected']])
@if (! $allLoaded)
<div class="mb-4 flex items-start gap-2 rounded-md border border-red-200 bg-red-50 px-4 py-3 text-red-800" role="alert">
<i class="fa fa-times-circle mt-1 shrink-0" aria-hidden="true"></i>
<div>
<strong>Oh snap!</strong> Your system does not meet the requirements.
You have to fix them in order to continue.
</div>
</div>
@endif
<x-install.card title="System Requirements">
<ul class="mb-6 divide-y divide-slate-100 rounded-md border border-slate-200">
@foreach ($requirements as $extension => $loaded)
<li class="flex items-center justify-between px-4 py-3 {{ ! $loaded ? 'bg-red-50 text-red-800' : '' }}">
<span>{{ $extension }}</span>
<span class="flex size-6 items-center justify-center rounded-full text-xs text-white {{ $loaded ? 'bg-green-600' : 'bg-red-600' }}">
<i class="fa {{ $loaded ? 'fa-check' : 'fa-times' }}" aria-hidden="true"></i>
</span>
</li>
@endforeach
</ul>
<div class="flex justify-end">
<x-install.button :href="route('install.permissions')" :disabled="! $allLoaded">
Next
<i class="fa fa-arrow-right" aria-hidden="true"></i>
</x-install.button>
</div>
</x-install.card>
@stop
+23
View File
@@ -0,0 +1,23 @@
@extends('layouts.install')
@section('content')
@include('install.steps', ['steps' => ['welcome' => 'selected']])
<x-install.card title="Welcome">
<div class="space-y-2">
<p>This steps will guide you through few step installation process.</p>
<p>
When this installation process is finished, you will be able
to login and manage your users immediately!
</p>
</div>
<div class="mt-6 flex justify-end">
<x-install.button :href="route('install.requirements')">
Next
<i class="fa fa-arrow-right" aria-hidden="true"></i>
</x-install.button>
</div>
</x-install.card>
@stop
+57
View File
@@ -0,0 +1,57 @@
@php
/**
* The wizard progress bar.
*
* Callers pass $steps keyed by slug with the Bootstrap era token strings
* ("selected", "selected done", "selected error"), which are mapped to a
* state here so the call sites did not all have to change.
*/
$definitions = [
'welcome' => ['label' => 'Welcome', 'icon' => 'fa-home'],
'requirements' => ['label' => 'System Requirements', 'icon' => 'fa-list'],
'permissions' => ['label' => 'Permissions', 'icon' => 'fa-lock'],
'database' => ['label' => 'Database Info', 'icon' => 'fa-database'],
'installation' => ['label' => 'Installation', 'icon' => 'fa-terminal'],
'complete' => ['label' => 'Complete', 'icon' => 'fa-flag-checkered'],
];
$circles = [
'done' => 'bg-primary-600 text-white',
'current' => 'bg-primary-600 text-white ring-4 ring-primary-100',
'error' => 'bg-red-600 text-white ring-4 ring-red-100',
'upcoming' => 'bg-slate-100 text-slate-400',
];
$labels = [
'done' => 'text-slate-600',
'current' => 'text-primary-600 font-medium',
'error' => 'text-red-600 font-medium',
'upcoming' => 'text-slate-400',
];
@endphp
<ol class="mb-8 flex items-start justify-between gap-1">
@foreach ($definitions as $slug => $definition)
@php
$token = $steps[$slug] ?? '';
$state = match (true) {
str_contains($token, 'error') => 'error',
str_contains($token, 'done') => 'done',
str_contains($token, 'selected') => 'current',
default => 'upcoming',
};
@endphp
<li class="flex flex-1 flex-col items-center gap-2 text-center">
<span
class="flex size-10 items-center justify-center rounded-full transition-colors {{ $circles[$state] }}"
@if ($state === 'current') aria-current="step" @endif
>
<i class="fa {{ $state === 'done' ? 'fa-check' : $definition['icon'] }}" aria-hidden="true"></i>
</span>
<span class="text-xs leading-tight {{ $labels[$state] }}">{{ $definition['label'] }}</span>
</li>
@endforeach
</ol>
+46
View File
@@ -0,0 +1,46 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>Installation - {{ setting('app_name') }}</title>
{{-- Icon font, served statically so the installer needs no build of its own. --}}
<link media="all" type="text/css" rel="stylesheet" href="{{ url('assets/css/fontawesome-all.min.css') }}">
{{--
The installer runs before .env exists, so it stays plain Blade and loads
its own stylesheet rather than the Vue application bundle.
--}}
@vite('resources/css/install.css')
@yield('styles')
</head>
<body class="bg-white text-slate-700">
<div class="mx-auto w-full max-w-3xl px-4 py-10">
<div class="mb-8 text-center">
<img src="{{ url('assets/img/logo.png') }}" alt="{{ setting('app_name') }}" height="50" class="inline-block">
</div>
@yield('content')
</div>
<script>
/*
* Replaces the jQuery loader helper: disable the button on submit and
* swap its label, so the install step cannot be triggered twice.
*/
document.querySelectorAll('[data-loading-text]').forEach(function (button) {
button.form?.addEventListener('submit', function () {
button.disabled = true;
button.innerHTML = button.dataset.loadingText;
});
});
</script>
@yield('scripts')
</body>
</html>
@@ -0,0 +1,22 @@
@component('mail::message')
# @lang('Hello!')
@lang('You are receiving this email because we received a password reset request for your account.')
@component('mail::button', ['url' => route('password.reset', ['token' => $token])])
@lang('Reset Password')
@endcomponent
@lang('This password reset link will expire in :count minutes.', [
'count' => config('auth.passwords.users.expire')
])
@lang('If you did not request a password reset, no further action is required.')
@lang('Regards'),<br>
{{ setting('app_name') }}
@endcomponent
@@ -0,0 +1,12 @@
@component('mail::message')
# @lang('Hello!')
@lang('Your account has been approved by administrators. You can now log in now and start using the application.')
<br>
@lang('Regards'),<br>
{{ setting('app_name') }}
@endcomponent
@@ -0,0 +1,19 @@
@component('mail::message')
# @lang('Hello!')
@lang('New user was just registered on :app website.', ['app' => setting('app_name')])
@lang('To view the user details just visit the link below.')
@component('mail::button', ['url' => route('users.show', $user)])
@lang('View User')
@endcomponent
@lang('Regards'),<br>
{{ setting('app_name') }}
@endcomponent
@@ -0,0 +1,18 @@
@component('mail::message')
# @lang('Hello!')
@lang('New user was just registered on :app website.', ['app' => setting('app_name')])
@lang('The user is waiting on your approval to be able to access the website.')
@lang('To view the user details just visit the link below.')
@component('mail::button', ['url' => route('users.edit', $user)])
@lang('View User')
@endcomponent
@lang('Regards'),<br>
{{ setting('app_name') }}
@endcomponent
View File
+19
View File
@@ -0,0 +1,19 @@
<table class="action" align="center" width="100%" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td align="center">
<table width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td align="center">
<table border="0" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td>
<a href="{{ $url }}" class="button button-{{ $color ?? 'brand' }}" target="_blank">{{ $slot }}</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
+11
View File
@@ -0,0 +1,11 @@
<tr>
<td>
<table class="footer" align="center" width="570" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td class="content-cell" align="center">
{{ Illuminate\Mail\Markdown::parse($slot) }}
</td>
</tr>
</table>
</td>
</tr>
+7
View File
@@ -0,0 +1,7 @@
<tr>
<td class="header">
<a href="{{ $url }}">
{{ $slot }}
</a>
</td>
</tr>
+54
View File
@@ -0,0 +1,54 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<style>
@media only screen and (max-width: 600px) {
.inner-body {
width: 100% !important;
}
.footer {
width: 100% !important;
}
}
@media only screen and (max-width: 500px) {
.button {
width: 100% !important;
}
}
</style>
<table class="wrapper" width="100%" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td align="center">
<table class="content" width="100%" cellpadding="0" cellspacing="0" role="presentation">
{{ $header ?? '' }}
<!-- Email Body -->
<tr>
<td class="body" width="100%" cellpadding="0" cellspacing="0">
<table class="inner-body" align="center" width="570" cellpadding="0" cellspacing="0" role="presentation">
<!-- Body content -->
<tr>
<td class="content-cell">
{{ Illuminate\Mail\Markdown::parse($slot) }}
{{ $subcopy ?? '' }}
</td>
</tr>
</table>
</td>
</tr>
{{ $footer ?? '' }}
</table>
</td>
</tr>
</table>
</body>
</html>
+27
View File
@@ -0,0 +1,27 @@
@component('mail::layout')
{{-- Header --}}
@slot('header')
@component('mail::header', ['url' => config('app.url')])
<x-logo />
@endcomponent
@endslot
{{-- Body --}}
{{ $slot }}
{{-- Subcopy --}}
@isset($subcopy)
@slot('subcopy')
@component('mail::subcopy')
{{ $subcopy }}
@endcomponent
@endslot
@endisset
{{-- Footer --}}
@slot('footer')
@component('mail::footer')
© {{ date('Y') }} {{ config('app.name') }}. @lang('All rights reserved.')
@endcomponent
@endslot
@endcomponent
+13
View File
@@ -0,0 +1,13 @@
<table class="panel" width="100%" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td class="panel-content">
<table width="100%" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td class="panel-item">
{{ Illuminate\Mail\Markdown::parse($slot) }}
</td>
</tr>
</table>
</td>
</tr>
</table>
+7
View File
@@ -0,0 +1,7 @@
<table class="promotion" align="center" width="100%" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td align="center">
{{ Illuminate\Mail\Markdown::parse($slot) }}
</td>
</tr>
</table>
@@ -0,0 +1,13 @@
<table width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td align="center">
<table border="0" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td>
<a href="{{ $url }}" class="button button-green" target="_blank">{{ $slot }}</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
+7
View File
@@ -0,0 +1,7 @@
<table class="subcopy" width="100%" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td>
{{ Illuminate\Mail\Markdown::parse($slot) }}
</td>
</tr>
</table>
+3
View File
@@ -0,0 +1,3 @@
<div class="table">
{{ Illuminate\Mail\Markdown::parse($slot) }}
</div>
+307
View File
@@ -0,0 +1,307 @@
/* Base */
body,
body *:not(html):not(style):not(br):not(tr):not(code) {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif,
'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
box-sizing: border-box;
}
body {
background-color: #f8fafc;
color: #74787e;
height: 100%;
hyphens: auto;
line-height: 1.4;
margin: 0;
-moz-hyphens: auto;
-ms-word-break: break-all;
width: 100% !important;
-webkit-hyphens: auto;
-webkit-text-size-adjust: none;
word-break: break-all;
word-break: break-word;
}
p,
ul,
ol,
blockquote {
line-height: 1.4;
text-align: left;
}
a {
color: #3869d4;
}
a img {
border: none;
}
/* Typography */
h1 {
color: #3d4852;
font-size: 19px;
font-weight: bold;
margin-top: 0;
text-align: left;
}
h2 {
color: #3d4852;
font-size: 16px;
font-weight: bold;
margin-top: 0;
text-align: left;
}
h3 {
color: #3d4852;
font-size: 14px;
font-weight: bold;
margin-top: 0;
text-align: left;
}
p {
color: #3d4852;
font-size: 16px;
line-height: 1.5em;
margin-top: 0;
text-align: left;
}
p.sub {
font-size: 12px;
}
img {
max-width: 100%;
}
/* Layout */
.wrapper {
background-color: #f8fafc;
margin: 0;
padding: 0;
width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
}
.content {
margin: 0;
padding: 0;
width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
}
/* Header */
.header {
padding: 25px 0;
text-align: center;
border-top: 5px solid #1c8966;
}
.header a {
color: #bbbfc3;
font-size: 19px;
font-weight: bold;
text-decoration: none;
text-shadow: 0 1px 0 white;
}
/* Body */
.body {
background-color: #ffffff;
border-bottom: 1px solid #edeff2;
border-top: 1px solid #edeff2;
margin: 0;
padding: 0;
width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
}
.inner-body {
background-color: #ffffff;
margin: 0 auto;
padding: 0;
width: 570px;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 570px;
}
/* Subcopy */
.subcopy {
border-top: 1px solid #edeff2;
margin-top: 25px;
padding-top: 25px;
}
.subcopy p {
font-size: 12px;
}
/* Footer */
.footer {
margin: 0 auto;
padding: 0;
text-align: center;
width: 570px;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 570px;
}
.footer p {
color: #aeaeae;
font-size: 12px;
text-align: center;
}
/* Tables */
.table table {
margin: 30px auto;
width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
}
.table th {
border-bottom: 1px solid #edeff2;
padding-bottom: 8px;
margin: 0;
}
.table td {
color: #74787e;
font-size: 15px;
line-height: 18px;
padding: 10px 0;
margin: 0;
}
.content-cell {
padding: 35px;
}
/* Buttons */
.action {
margin: 30px auto;
padding: 0;
text-align: center;
width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
}
.button {
border-radius: 3px;
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.16);
color: #fff;
display: inline-block;
text-decoration: none;
-webkit-text-size-adjust: none;
}
.button-blue,
.button-primary {
background-color: #3490dc;
border-top: 10px solid #3490dc;
border-right: 18px solid #3490dc;
border-bottom: 10px solid #3490dc;
border-left: 18px solid #3490dc;
}
.button-green,
.button-success {
background-color: #38c172;
border-top: 10px solid #38c172;
border-right: 18px solid #38c172;
border-bottom: 10px solid #38c172;
border-left: 18px solid #38c172;
}
.button-red,
.button-error {
background-color: #e3342f;
border-top: 10px solid #e3342f;
border-right: 18px solid #e3342f;
border-bottom: 10px solid #e3342f;
border-left: 18px solid #e3342f;
}
.button-brand {
background-color: #1c8966;
border-top: 10px solid #1c8966;
border-right: 18px solid #1c8966;
border-bottom: 10px solid #1c8966;
border-left: 18px solid #1c8966;
}
/* Panels */
.panel {
margin: 0 0 21px;
}
.panel-content {
background-color: #f1f5f8;
padding: 16px;
}
.panel-item {
padding: 0;
}
.panel-item p:last-of-type {
margin-bottom: 0;
padding-bottom: 0;
}
/* Promotions */
.promotion {
background-color: #ffffff;
border: 2px dashed #9ba2ab;
margin: 0;
margin-bottom: 25px;
margin-top: 25px;
padding: 24px;
width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
}
.promotion h1 {
text-align: center;
}
.promotion p {
font-size: 15px;
text-align: center;
}
code {
background: rgba(0,0,0,.05);
padding: 2px 4px;
border-radius: 2px;
}
+1
View File
@@ -0,0 +1 @@
{{ $slot }}: {{ $url }}
+1
View File
@@ -0,0 +1 @@
{{ $slot }}
+1
View File
@@ -0,0 +1 @@
[{{ $slot }}]({{ $url }})
+9
View File
@@ -0,0 +1,9 @@
{!! strip_tags($header) !!}
{!! strip_tags($slot) !!}
@isset($subcopy)
{!! strip_tags($subcopy) !!}
@endisset
{!! strip_tags($footer) !!}
+27
View File
@@ -0,0 +1,27 @@
@component('mail::layout')
{{-- Header --}}
@slot('header')
@component('mail::header', ['url' => config('app.url')])
{{ config('app.name') }}
@endcomponent
@endslot
{{-- Body --}}
{{ $slot }}
{{-- Subcopy --}}
@isset($subcopy)
@slot('subcopy')
@component('mail::subcopy')
{{ $subcopy }}
@endcomponent
@endslot
@endisset
{{-- Footer --}}
@slot('footer')
@component('mail::footer')
© {{ date('Y') }} {{ config('app.name') }}. @lang('All rights reserved.')
@endcomponent
@endslot
@endcomponent
+1
View File
@@ -0,0 +1 @@
{{ $slot }}
+1
View File
@@ -0,0 +1 @@
{{ $slot }}
@@ -0,0 +1 @@
[{{ $slot }}]({{ $url }})
+1
View File
@@ -0,0 +1 @@
{{ $slot }}
+1
View File
@@ -0,0 +1 @@
{{ $slot }}
@@ -0,0 +1,22 @@
<?php
if (! empty($greeting)) {
echo $greeting, "\n\n";
} else {
echo $level == 'error' ? 'Whoops!' : 'Hello!', "\n\n";
}
if (! empty($introLines)) {
echo implode("\n", $introLines), "\n\n";
}
if (isset($actionText)) {
echo "{$actionText}: {$actionUrl}", "\n\n";
}
if (! empty($outroLines)) {
echo implode("\n", $outroLines), "\n\n";
}
echo 'Regards,', "\n";
echo config('app.name'), "\n";
+193
View File
@@ -0,0 +1,193 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style type="text/css" rel="stylesheet" media="all">
/* Media Queries */
@media only screen and (max-width: 500px) {
.button {
width: 100% !important;
}
}
</style>
</head>
<?php
$style = [
/* Layout ------------------------------ */
'body' => 'margin: 0; padding: 0; width: 100%; background-color: #F2F4F6;',
'email-wrapper' => 'width: 100%; margin: 0; padding: 0; background-color: #F2F4F6; border-top: 5px solid #1c8966;',
/* Masthead ----------------------- */
'email-masthead' => 'padding: 25px 0; text-align: center;',
'email-masthead_name' => 'font-size: 16px; font-weight: bold; color: #2F3133; text-decoration: none; text-shadow: 0 1px 0 white;',
'email-body' => 'width: 100%; margin: 0; padding: 0; border-top: 1px solid #EDEFF2; border-bottom: 1px solid #EDEFF2; background-color: #FFF;',
'email-body_inner' => 'width: auto; max-width: 570px; margin: 0 auto; padding: 0;',
'email-body_cell' => 'padding: 35px;',
'email-footer' => 'width: auto; max-width: 570px; margin: 0 auto; padding: 0; text-align: center;',
'email-footer_cell' => 'color: #AEAEAE; padding: 35px; text-align: center;',
/* Body ------------------------------ */
'body_action' => 'width: 100%; margin: 30px auto; padding: 0; text-align: center;',
'body_sub' => 'margin-top: 25px; padding-top: 25px; border-top: 1px solid #EDEFF2;',
/* Type ------------------------------ */
'anchor' => 'color: #3869D4;',
'header-1' => 'margin-top: 0; color: #2F3133; font-size: 19px; font-weight: bold; text-align: left;',
'paragraph' => 'margin-top: 0; color: #74787E; font-size: 16px; line-height: 1.5em;',
'paragraph-sub' => 'margin-top: 0; color: #74787E; font-size: 12px; line-height: 1.5em;',
'paragraph-center' => 'text-align: center;',
/* Buttons ------------------------------ */
'button' => 'display: block; display: inline-block; width: 200px; min-height: 20px; padding: 10px;
background-color: #3869D4; border-radius: 3px; color: #ffffff; font-size: 15px; line-height: 25px;
text-align: center; text-decoration: none; -webkit-text-size-adjust: none;',
'button--green' => 'background-color: #5cb85c;',
'button--red' => 'background-color: #dc4d2f;',
'button--blue' => 'background-color: #3869D4;',
'button--default' => 'background-color: #1c8966;'
];
?>
<?php $fontFamily = 'font-family: Arial, \'Helvetica Neue\', Helvetica, sans-serif;'; ?>
<body style="{{ $style['body'] }}">
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td style="{{ $style['email-wrapper'] }}" align="center">
<table width="100%" cellpadding="0" cellspacing="0">
<!-- Logo -->
<tr>
<td style="{{ $style['email-masthead'] }}">
<a style="{{ $fontFamily }} {{ $style['email-masthead_name'] }}" href="{{ url('/') }}" target="_blank">
<x-logo height="60" />
{{--{{ config('app.name') }}--}}
</a>
</td>
</tr>
<!-- Email Body -->
<tr>
<td style="{{ $style['email-body'] }}" width="100%">
<table style="{{ $style['email-body_inner'] }}" align="center" width="570" cellpadding="0" cellspacing="0">
<tr>
<td style="{{ $fontFamily }} {{ $style['email-body_cell'] }}">
<!-- Greeting -->
<h1 style="{{ $style['header-1'] }}">
@if (! empty($greeting))
{{ $greeting }}
@else
@if ($level == 'error')
Whoops!
@else
Hello!
@endif
@endif
</h1>
<!-- Intro -->
@foreach ($introLines as $line)
<p style="{{ $style['paragraph'] }}">
{{ $line }}
</p>
@endforeach
<!-- Action Button -->
@if (isset($actionText))
<table style="{{ $style['body_action'] }}" align="center" width="100%" cellpadding="0" cellspacing="0">
<tr>
<td align="center">
<?php
switch ($level) {
case 'success':
$actionColor = 'button--green';
break;
case 'error':
$actionColor = 'button--red';
break;
default:
$actionColor = 'button--default';
}
?>
<a href="{{ $actionUrl }}"
style="{{ $fontFamily }} {{ $style['button'] }} {{ $style[$actionColor] }}"
class="button"
target="_blank">
{{ $actionText }}
</a>
</td>
</tr>
</table>
@endif
<!-- Outro -->
@foreach ($outroLines as $line)
<p style="{{ $style['paragraph'] }}">
{{ $line }}
</p>
@endforeach
<!-- Salutation -->
<p style="{{ $style['paragraph'] }}">
@lang('Regards'),<br>{{ config('app.name') }}
</p>
<!-- Sub Copy -->
@if (isset($actionText))
<table style="{{ $style['body_sub'] }}">
<tr>
<td style="{{ $fontFamily }}">
<p style="{{ $style['paragraph-sub'] }}">
@lang("If you're having trouble clicking the \":button\" button, copy and paste the URL below into your web browser:", ['button' => $actionText])
</p>
<p style="{{ $style['paragraph-sub'] }}">
<a style="{{ $style['anchor'] }}" href="{{ $actionUrl }}" target="_blank">
{{ $actionUrl }}
</a>
</p>
</td>
</tr>
</table>
@endif
</td>
</tr>
</table>
</td>
</tr>
<!-- Footer -->
<tr>
<td>
<table style="{{ $style['email-footer'] }}" align="center" width="570" cellpadding="0" cellspacing="0">
<tr>
<td style="{{ $fontFamily }} {{ $style['email-footer_cell'] }}">
<p style="{{ $style['paragraph-sub'] }}">
&copy; {{ date('Y') }}
<a style="{{ $style['anchor'] }}" href="{{ url('/') }}" target="_blank">{{ config('app.name') }}</a>.
@lang('All rights reserved.')
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
+36
View File
@@ -0,0 +1,36 @@
@if ($paginator->hasPages())
<ul class="pagination">
<!-- Previous Page Link -->
@if ($paginator->onFirstPage())
<li class="page-item disabled"><span class="page-link">&laquo;</span></li>
@else
<li class="page-item"><a class="page-link" href="{{ $paginator->previousPageUrl() }}" rel="prev">&laquo;</a></li>
@endif
<!-- Pagination Elements -->
@foreach ($elements as $element)
<!-- "Three Dots" Separator -->
@if (is_string($element))
<li class="page-item disabled"><span class="page-link">{{ $element }}</span></li>
@endif
<!-- Array Of Links -->
@if (is_array($element))
@foreach ($element as $page => $url)
@if ($page == $paginator->currentPage())
<li class="page-item active"><span class="page-link">{{ $page }}</span></li>
@else
<li class="page-item"><a class="page-link" href="{{ $url }}">{{ $page }}</a></li>
@endif
@endforeach
@endif
@endforeach
<!-- Next Page Link -->
@if ($paginator->hasMorePages())
<li class="page-item"><a class="page-link" href="{{ $paginator->nextPageUrl() }}" rel="next">&raquo;</a></li>
@else
<li class="page-item disabled"><span class="page-link">&raquo;</span></li>
@endif
</ul>
@endif
+36
View File
@@ -0,0 +1,36 @@
@if ($paginator->hasPages())
<ul class="pagination">
<!-- Previous Page Link -->
@if ($paginator->onFirstPage())
<li class="disabled"><span>&laquo;</span></li>
@else
<li><a href="{{ $paginator->previousPageUrl() }}" rel="prev">&laquo;</a></li>
@endif
<!-- Pagination Elements -->
@foreach ($elements as $element)
<!-- "Three Dots" Separator -->
@if (is_string($element))
<li class="disabled"><span>{{ $element }}</span></li>
@endif
<!-- Array Of Links -->
@if (is_array($element))
@foreach ($element as $page => $url)
@if ($page == $paginator->currentPage())
<li class="active"><span>{{ $page }}</span></li>
@else
<li><a href="{{ $url }}">{{ $page }}</a></li>
@endif
@endforeach
@endif
@endforeach
<!-- Next Page Link -->
@if ($paginator->hasMorePages())
<li><a href="{{ $paginator->nextPageUrl() }}" rel="next">&raquo;</a></li>
@else
<li class="disabled"><span>&raquo;</span></li>
@endif
</ul>
@endif
@@ -0,0 +1,17 @@
@if ($paginator->hasPages())
<ul class="pagination">
<!-- Previous Page Link -->
@if ($paginator->onFirstPage())
<li class="page-item disabled"><span class="page-link">&laquo;</span></li>
@else
<li class="page-item"><a class="page-link" href="{{ $paginator->previousPageUrl() }}" rel="prev">&laquo;</a></li>
@endif
<!-- Next Page Link -->
@if ($paginator->hasMorePages())
<li class="page-item"><a class="page-link" href="{{ $paginator->nextPageUrl() }}" rel="next">&raquo;</a></li>
@else
<li class="page-item disabled"><span class="page-link">&raquo;</span></li>
@endif
</ul>
@endif
@@ -0,0 +1,17 @@
@if ($paginator->hasPages())
<ul class="pagination">
<!-- Previous Page Link -->
@if ($paginator->onFirstPage())
<li class="disabled"><span>&laquo;</span></li>
@else
<li><a href="{{ $paginator->previousPageUrl() }}" rel="prev">&laquo;</a></li>
@endif
<!-- Next Page Link -->
@if ($paginator->hasMorePages())
<li><a href="{{ $paginator->nextPageUrl() }}" rel="next">&raquo;</a></li>
@else
<li class="disabled"><span>&raquo;</span></li>
@endif
</ul>
@endif