Merge branch '2.4' into feature/remote-user-authenticate

This commit is contained in:
James Brooks
2019-06-23 09:04:25 +01:00
committed by GitHub
136 changed files with 5378 additions and 2760 deletions
+8
View File
@@ -0,0 +1,8 @@
# These are supported funding model platforms
github: jbrooksuk
patreon: jbrooksuk
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
custom: # Replace with a single custom sponsorship URL
+1 -1
View File
@@ -28,7 +28,7 @@ You can now [join our Slack community!](http://cachethq-slack.herokuapp.com)
## Requirements
- PHP 7.1 or later
- PHP 7.1.3 - 7.3
- HTTP server with PHP support (eg: Apache, Nginx, Caddy)
- [Composer](https://getcomposer.org)
- A supported database: MySQL, PostgreSQL or SQLite
@@ -140,7 +140,7 @@ final class CreateIncidentCommand
*
* @return void
*/
public function __construct($name, $status, $message, $visible, $component_id, $component_status, $notify, $stickied, $occurred_at, $template, array $template_vars = [], $meta = [])
public function __construct($name, $status, $message, $visible, $component_id, $component_status, $notify, $stickied, $occurred_at, $template, array $template_vars = [], array $meta = [])
{
$this->name = $name;
$this->status = $status;
@@ -106,6 +106,13 @@ final class UpdateIncidentCommand
*/
public $template_vars;
/**
* Meta key/value pairs.
*
* @var array
*/
public $meta = [];
/**
* The validation rules.
*
@@ -122,6 +129,7 @@ final class UpdateIncidentCommand
'stickied' => 'nullable|bool',
'occurred_at' => 'nullable|string',
'template' => 'nullable|string',
'meta' => 'nullable|array',
];
/**
@@ -139,10 +147,11 @@ final class UpdateIncidentCommand
* @param string|null $occurred_at
* @param string|null $template
* @param array $template_vars
* @param array $meta
*
* @return void
*/
public function __construct(Incident $incident, $name, $status, $message, $visible, $component_id, $component_status, $notify, $stickied, $occurred_at, $template, array $template_vars = [])
public function __construct(Incident $incident, $name, $status, $message, $visible, $component_id, $component_status, $notify, $stickied, $occurred_at, $template, array $template_vars = [], array $meta = [])
{
$this->incident = $incident;
$this->name = $name;
@@ -156,5 +165,6 @@ final class UpdateIncidentCommand
$this->occurred_at = $occurred_at;
$this->template = $template;
$this->template_vars = $template_vars;
$this->meta = $meta;
}
}
@@ -60,6 +60,13 @@ final class CreateScheduleCommand
*/
public $components;
/**
* Whether to notify that the incident was reported.
*
* @var bool
*/
public $notify;
/**
* The validation rules.
*
@@ -72,6 +79,7 @@ final class CreateScheduleCommand
'scheduled_at' => 'required|string',
'completed_at' => 'nullable|string',
'components' => 'nullable|array',
'notify' => 'nullable|bool',
];
/**
@@ -83,10 +91,11 @@ final class CreateScheduleCommand
* @param string $scheduled_at
* @param string $completed_at
* @param array $components
* @param bool $notify
*
* @return void
*/
public function __construct($name, $message, $status, $scheduled_at, $completed_at, array $components = [])
public function __construct($name, $message, $status, $scheduled_at, $completed_at, $components, $notify)
{
$this->name = $name;
$this->message = $message;
@@ -94,5 +103,6 @@ final class CreateScheduleCommand
$this->scheduled_at = $scheduled_at;
$this->completed_at = $completed_at;
$this->components = $components;
$this->notify = $notify;
}
}
@@ -36,18 +36,27 @@ final class ScheduleWasCreatedEvent implements ActionInterface, ScheduleEventInt
*/
public $schedule;
/**
* Whether to notify that the incident was reported.
*
* @var bool
*/
public $notify;
/**
* Create a new schedule was created event instance.
*
* @param \CachetHQ\Cachet\Models\User $user
* @param \CachetHQ\Cachet\Models\Schedule $schedule
* @param bool notify
*
* @return void
*/
public function __construct(User $user, Schedule $schedule)
public function __construct(User $user, Schedule $schedule, $notify = false)
{
$this->user = $user;
$this->schedule = $schedule;
$this->notify = $notify;
}
/**
@@ -15,6 +15,7 @@ use CachetHQ\Cachet\Bus\Commands\Component\UpdateComponentCommand;
use CachetHQ\Cachet\Bus\Commands\Incident\CreateIncidentCommand;
use CachetHQ\Cachet\Bus\Events\Incident\IncidentWasCreatedEvent;
use CachetHQ\Cachet\Bus\Exceptions\Incident\InvalidIncidentTimestampException;
use CachetHQ\Cachet\Bus\Handlers\Traits\StoresMeta;
use CachetHQ\Cachet\Models\Component;
use CachetHQ\Cachet\Models\Incident;
use CachetHQ\Cachet\Models\IncidentTemplate;
@@ -32,6 +33,8 @@ use Twig\Loader\ArrayLoader as Twig_Loader_Array;
*/
class CreateIncidentCommandHandler
{
use StoresMeta;
/**
* The authentication guard instance.
*
@@ -104,14 +107,7 @@ class CreateIncidentCommandHandler
// Store any meta?
if ($meta = $command->meta) {
foreach ($meta as $key => $value) {
Meta::create([
'key' => $key,
'value' => $value,
'meta_type' => 'incidents',
'meta_id' => $incident->id,
]);
}
$this->storeMeta($command->meta, 'incidents', $incident->id);
}
// Update the component.
@@ -15,6 +15,7 @@ use CachetHQ\Cachet\Bus\Commands\Component\UpdateComponentCommand;
use CachetHQ\Cachet\Bus\Commands\Incident\UpdateIncidentCommand;
use CachetHQ\Cachet\Bus\Events\Incident\IncidentWasUpdatedEvent;
use CachetHQ\Cachet\Bus\Exceptions\Incident\InvalidIncidentTimestampException;
use CachetHQ\Cachet\Bus\Handlers\Traits\StoresMeta;
use CachetHQ\Cachet\Models\Component;
use CachetHQ\Cachet\Models\Incident;
use CachetHQ\Cachet\Models\IncidentTemplate;
@@ -30,6 +31,8 @@ use Twig\Loader\ArrayLoader as Twig_Loader_Array;
*/
class UpdateIncidentCommandHandler
{
use StoresMeta;
/**
* The authentication guard instance.
*
@@ -86,6 +89,11 @@ class UpdateIncidentCommandHandler
// Rather than making lots of updates, just fill and save.
$incident->save();
// Store any meta?
if ($meta = $command->meta) {
$this->storeMeta($command->meta, 'incidents', $incident->id);
}
// Update the component.
if ($component = Component::find($command->component_id)) {
execute(new UpdateComponentCommand(
@@ -66,8 +66,7 @@ class CreateScheduleCommandHandler
{
try {
$schedule = Schedule::create($this->filter($command));
event(new ScheduleWasCreatedEvent($this->auth->user(), $schedule));
event(new ScheduleWasCreatedEvent($this->auth->user(), $schedule, (bool) $command->notify));
} catch (InvalidArgumentException $e) {
throw new ValidationException(new MessageBag([$e->getMessage()]));
}
@@ -96,6 +95,7 @@ class CreateScheduleCommandHandler
'status' => $command->status,
'scheduled_at' => $scheduledAt,
'completed_at' => $completedAt,
'notify' => $command->notify,
];
$availableParams = array_filter($params, function ($val) {
@@ -51,6 +51,9 @@ class SendScheduleEmailNotificationHandler
public function handle(ScheduleEventInterface $event)
{
$schedule = $event->schedule;
if (!$event->notify) {
return false;
}
// First notify all global subscribers.
$globalSubscribers = $this->subscriber->isVerified()->isGlobal()->get()->each(function ($subscriber) use ($schedule) {
+81
View File
@@ -0,0 +1,81 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Bus\Handlers\Traits;
use CachetHQ\Cachet\Models\Meta;
trait StoresMeta
{
/**
* Stores all Meta values of a model.
*
* @param array $metaData
* @param string $metaType
* @param string|int $metaId
* @param string $metaModel
*
* @return void
*/
public function storeMeta($metaData, $metaType, $metaId, $metaModel = Meta::class)
{
// Validation required instead of type hinting because it could be passed as false or NULL
if (!is_array($metaData)) {
return;
}
foreach ($metaData as $key => $value) {
$modelInstance = call_user_func(
[$metaModel, 'firstOrNew'],
[
'key' => $key,
'meta_type' => $metaType,
'meta_id' => $metaId,
]
);
$value = $this->removeEmptyValues($value);
if (!empty($value)) {
$modelInstance->setAttribute('value', $value);
$modelInstance->save();
continue;
}
// The value is empty, remove the row
if ($modelInstance->exists) {
$modelInstance->delete();
}
}
}
/**
* Determine if a Value is empty.
*
* @param mixed $values
*
* @return array|mixed
*/
protected function removeEmptyValues($values)
{
if (!is_array($values)) {
return empty($values) ? null : $values;
}
foreach ($values as $key => $value) {
if (!empty($value)) {
continue;
}
unset($values[$key]);
}
return $values;
}
}
+1 -1
View File
@@ -53,7 +53,7 @@ class ComponentsComposer
public function compose(View $view)
{
$componentGroups = $this->getVisibleGroupedComponents();
$ungroupedComponents = Component::ungrouped()->get();
$ungroupedComponents = Component::ungrouped()->orderBy('status', 'desc')->get();
$view->withComponentGroups($componentGroups)
->withUngroupedComponents($ungroupedComponents);
+68 -5
View File
@@ -26,6 +26,69 @@ use Illuminate\Contracts\View\View;
*/
class DashboardComposer
{
/**
* The component count.
*
* @var int
*/
protected $componentCount;
/**
* The incident count.
*
* @var int
*/
protected $incidentCount;
/**
* The incident template count.
*
* @var int
*/
protected $incidentTemplateCount;
/**
* The schedule count.
*
* @var int
*/
protected $scheduleCount;
/**
* The subscriber count.
*
* @var int
*/
protected $subscriberCount;
/**
* Create a new dashboard composer instance.
*
* @return void
*/
public function __construct()
{
if (is_null($this->componentCount)) {
$this->componentCount = Component::count();
}
if (is_null($this->incidentCount)) {
$this->incidentCount = Incident::count();
}
if (is_null($this->incidentTemplateCount)) {
$this->incidentTemplateCount = IncidentTemplate::count();
}
if (is_null($this->scheduleCount)) {
$this->scheduleCount = Schedule::count();
}
if (is_null($this->subscriberCount)) {
$this->subscriberCount = Subscriber::isVerified()->count();
}
}
/**
* Bind data to the view.
*
@@ -35,11 +98,11 @@ class DashboardComposer
*/
public function compose(View $view)
{
$view->withComponentCount(Component::count());
$view->withIncidentCount(Incident::count());
$view->withIncidentTemplateCount(IncidentTemplate::count());
$view->withScheduleCount(Schedule::count());
$view->withSubscriberCount(Subscriber::isVerified()->count());
$view->withComponentCount($this->componentCount);
$view->withIncidentCount($this->incidentCount);
$view->withIncidentTemplateCount($this->incidentTemplateCount);
$view->withScheduleCount($this->scheduleCount);
$view->withSubscriberCount($this->subscriberCount);
$view->withIsWriteable(is_writable(app()->bootstrapPath().'/cachet'));
}
}
+1 -1
View File
@@ -31,7 +31,7 @@ class ScheduledComposer
*/
public function compose(View $view)
{
$scheduledMaintenance = Schedule::futureSchedules()->orderBy('scheduled_at')->get();
$scheduledMaintenance = Schedule::uncompleted()->orderBy('scheduled_at')->get();
$view->withScheduledMaintenance($scheduledMaintenance);
}
+3 -2
View File
@@ -13,6 +13,7 @@ namespace CachetHQ\Cachet\Composers;
use CachetHQ\Cachet\Integrations\Contracts\System;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Arr;
/**
* This is the status composer.
@@ -52,7 +53,7 @@ class StatusComposer
{
$status = $this->system->getStatus();
$view->withSystemStatus(array_get($status, 'system_status'));
$view->withSystemMessage(array_get($status, 'system_message'));
$view->withSystemStatus(Arr::get($status, 'system_status'));
$view->withSystemMessage(Arr::get($status, 'system_message'));
}
}
+2 -1
View File
@@ -15,6 +15,7 @@ use DateTime;
use DateTimeZone;
use Illuminate\Contracts\Config\Repository;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Arr;
/**
* This is the timezone locale composer class.
@@ -58,7 +59,7 @@ class TimezoneLocaleComposer
$langs = array_map(function ($lang) use ($enabledLangs) {
$locale = basename($lang);
return [$locale => array_get($enabledLangs, $locale, [
return [$locale => Arr::get($enabledLangs, $locale, [
'name' => $locale,
'subset' => null,
])];
+44 -1
View File
@@ -11,9 +11,11 @@
namespace CachetHQ\Cachet\Console\Commands;
use CachetHQ\Cachet\Models\User;
use Dotenv\Dotenv;
use Dotenv\Exception\InvalidPathException;
use Illuminate\Console\Command;
use Illuminate\Contracts\Console\Kernel;
use Illuminate\Contracts\Events\Dispatcher;
/**
@@ -70,6 +72,7 @@ class InstallCommand extends Command
$this->configureDrivers();
$this->configureMail();
$this->configureCachet();
$this->configureUser();
}
$this->line('Installing Cachet...');
@@ -313,9 +316,11 @@ class InstallCommand extends Command
/**
* Configure Cachet.
*
* @param array $config
*
* @return void
*/
protected function configureCachet()
protected function configureCachet(array $config = [])
{
$config = [];
if ($this->confirm('Do you wish to use Cachet Beacon?')) {
@@ -332,6 +337,33 @@ class InstallCommand extends Command
}
}
/**
* Configure the first user.
*
* @return void
*/
protected function configureUser()
{
if (!$this->confirm('Do you want to create an admin user?')) {
return;
}
// We need to refresh the config to get access to the newly connected database.
$this->getFreshConfiguration();
// Now we need to install the application.
// $this->call('cachet:install');
$user = [
'username' => $this->ask('Please enter your username'),
'email' => $this->ask('Please enter your email'),
'password' => $this->secret('Please enter your password'),
'level' => User::LEVEL_ADMIN,
];
User::create($user);
}
/**
* Configure the redis connection.
*
@@ -372,6 +404,17 @@ class InstallCommand extends Command
$this->table(['Setting', 'Value'], $configRows);
}
/**
* Boot a fresh copy of the application configuration.
*
* @return void
*/
protected function getFreshConfiguration()
{
$app = require $this->laravel->bootstrapPath().'/app.php';
$app->make(Kernel::class)->bootstrap();
}
/**
* Writes to the .env file with given parameters.
*
@@ -13,6 +13,7 @@ namespace CachetHQ\Cachet\Foundation\Exceptions\Filters;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
class ApiFilter
{
@@ -31,7 +32,7 @@ class ApiFilter
{
if ($request->is('api*')) {
foreach ($displayers as $index => $displayer) {
if (!str_contains($displayer->contentType(), 'application/')) {
if (!Str::contains($displayer->contentType(), 'application/')) {
unset($displayers[$index]);
}
}
@@ -57,6 +57,6 @@ class ComposerServiceProvider extends ServiceProvider
*/
public function register()
{
//
$this->app->singleton(DashboardComposer::class);
}
}
@@ -11,11 +11,11 @@
namespace CachetHQ\Cachet\Foundation\Providers;
use Barryvdh\Cors\HandleCors;
use CachetHQ\Cachet\Http\Middleware\Acceptable;
use CachetHQ\Cachet\Http\Middleware\Authenticate;
use CachetHQ\Cachet\Http\Middleware\RemoteUserAuthenticate;
use CachetHQ\Cachet\Http\Middleware\Timezone;
use CachetHQ\Cachet\Http\Middleware\VerifyCsrfToken;
use CachetHQ\Cachet\Http\Routes\ApiSystemRoutes;
use CachetHQ\Cachet\Http\Routes\AuthRoutes;
use CachetHQ\Cachet\Http\Routes\Setup\ApiRoutes as ApiSetupRoutes;
@@ -23,7 +23,6 @@ use CachetHQ\Cachet\Http\Routes\SetupRoutes;
use CachetHQ\Cachet\Http\Routes\SignupRoutes;
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
use Illuminate\Cookie\Middleware\EncryptCookies;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Routing\Middleware\SubstituteBindings;
use Illuminate\Routing\Router;
@@ -173,7 +172,6 @@ class RouteServiceProvider extends ServiceProvider
protected function mapOtherwise(Router $router, $routes, $applyAlwaysAuthenticate)
{
$middleware = [
HandleCors::class,
SubstituteBindings::class,
Acceptable::class,
Timezone::class,
@@ -73,7 +73,8 @@ class ScheduleController extends AbstractApiController
Binput::get('status'),
Binput::get('scheduled_at'),
Binput::get('completed_at'),
Binput::get('components', [])
Binput::get('components', []),
Binput::get('notify', false)
));
} catch (QueryException $e) {
throw new BadRequestHttpException();
+3 -2
View File
@@ -17,6 +17,7 @@ use CachetHQ\Cachet\Bus\Events\User\UserLoggedOutEvent;
use CachetHQ\Cachet\Bus\Events\User\UserPassedTwoAuthEvent;
use GrahamCampbell\Binput\Facades\Binput;
use Illuminate\Routing\Controller;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Session;
@@ -47,9 +48,9 @@ class AuthController extends Controller
// Login with username or email.
$loginKey = filter_var($loginData['username'], FILTER_VALIDATE_EMAIL) ? 'email' : 'username';
$loginData[$loginKey] = array_pull($loginData, 'username');
$loginData[$loginKey] = Arr::pull($loginData, 'username');
$rememberUser = array_pull($loginData, 'remember_me') === '1';
$rememberUser = Arr::pull($loginData, 'remember_me') === '1';
// Validate login credentials.
if (Auth::validate($loginData)) {
@@ -21,6 +21,7 @@ use CachetHQ\Cachet\Models\Component;
use CachetHQ\Cachet\Models\ComponentGroup;
use GrahamCampbell\Binput\Facades\Binput;
use Illuminate\Routing\Controller;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\View;
@@ -73,7 +74,7 @@ class ComponentController extends Controller
*/
public function showComponents()
{
$components = Component::orderBy('order')->orderBy('created_at')->get();
$components = Component::with('group')->orderBy('order')->orderBy('created_at')->get();
$this->subMenu['components']['active'] = true;
@@ -112,7 +113,7 @@ class ComponentController extends Controller
public function updateComponentAction(Component $component)
{
$componentData = Binput::get('component');
$tags = array_pull($componentData, 'tags');
$tags = Arr::pull($componentData, 'tags');
try {
$component = execute(new UpdateComponentCommand(
@@ -169,7 +170,7 @@ class ComponentController extends Controller
public function createComponentAction()
{
$componentData = Binput::get('component');
$tags = array_pull($componentData, 'tags');
$tags = Arr::pull($componentData, 'tags');
try {
$component = execute(new CreateComponentCommand(
@@ -106,7 +106,9 @@ class DashboardController extends Controller
$entries = null;
if ($feed = $this->feed->latest()) {
$entries = array_slice($feed->channel->item, 0, 5);
if (is_object($feed)) {
$entries = array_slice($feed->channel->item, 0, 5);
}
}
return View::make('dashboard.index')
@@ -75,7 +75,7 @@ class IncidentController extends Controller
*/
public function showIncidents()
{
$incidents = Incident::orderBy('created_at', 'desc')->get();
$incidents = Incident::with('user')->orderBy('created_at', 'desc')->get();
return View::make('dashboard.incidents.index')
->withPageTitle(trans('dashboard.incidents.incidents').' - '.trans('dashboard.dashboard'))
@@ -128,7 +128,8 @@ class IncidentController extends Controller
Binput::get('stickied', false),
Binput::get('occurred_at'),
null,
[]
[],
['seo' => Binput::get('seo', [])]
));
} catch (ValidationException $e) {
return cachet_redirect('dashboard.incidents.create')
@@ -258,7 +259,8 @@ class IncidentController extends Controller
Binput::get('stickied', false),
Binput::get('occurred_at'),
null,
[]
[],
['seo' => Binput::get('seo', [])]
));
} catch (ValidationException $e) {
return cachet_redirect('dashboard.incidents.edit', ['id' => $incident->id])
@@ -15,6 +15,7 @@ use AltThree\Validator\ValidationException;
use CachetHQ\Cachet\Bus\Commands\Schedule\CreateScheduleCommand;
use CachetHQ\Cachet\Bus\Commands\Schedule\DeleteScheduleCommand;
use CachetHQ\Cachet\Bus\Commands\Schedule\UpdateScheduleCommand;
use CachetHQ\Cachet\Integrations\Contracts\System;
use CachetHQ\Cachet\Models\IncidentTemplate;
use CachetHQ\Cachet\Models\Schedule;
use GrahamCampbell\Binput\Facades\Binput;
@@ -35,13 +36,21 @@ class ScheduleController extends Controller
*/
protected $subMenu = [];
/**
* The system instance.
*
* @var \CachetHQ\Cachet\Integrations\Contracts\System
*/
protected $system;
/**
* Creates a new schedule controller instance.
*
* @return void
*/
public function __construct()
public function __construct(System $system)
{
$this->system = $system;
View::share('subTitle', trans('dashboard.schedule.title'));
}
@@ -70,7 +79,8 @@ class ScheduleController extends Controller
return View::make('dashboard.maintenance.add')
->withPageTitle(trans('dashboard.schedule.add.title').' - '.trans('dashboard.dashboard'))
->withIncidentTemplates($incidentTemplates);
->withIncidentTemplates($incidentTemplates)
->withNotificationsEnabled($this->system->canNotifySubscribers());
}
/**
@@ -87,7 +97,8 @@ class ScheduleController extends Controller
Binput::get('status', Schedule::UPCOMING),
Binput::get('scheduled_at'),
Binput::get('completed_at'),
Binput::get('components', [])
Binput::get('components', []),
Binput::get('notify', false)
));
} catch (ValidationException $e) {
return cachet_redirect('dashboard.schedule.create')
@@ -18,6 +18,7 @@ use CachetHQ\Cachet\Bus\Events\User\UserRegeneratedApiTokenEvent;
use CachetHQ\Cachet\Models\User;
use GrahamCampbell\Binput\Facades\Binput;
use Illuminate\Routing\Controller;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\View;
use PragmaRX\Google2FA\Vendor\Laravel\Facade as Google2FA;
@@ -44,7 +45,7 @@ class UserController extends Controller
{
$userData = array_filter(Binput::only(['username', 'email', 'password', 'google2fa']));
$enable2FA = (bool) array_pull($userData, 'google2fa');
$enable2FA = (bool) Arr::pull($userData, 'google2fa');
// Let's enable/disable auth
if ($enable2FA && !Auth::user()->hasTwoFactor) {
+5 -4
View File
@@ -16,6 +16,7 @@ use CachetHQ\Cachet\Models\User;
use CachetHQ\Cachet\Settings\Repository;
use GrahamCampbell\Binput\Facades\Binput;
use Illuminate\Routing\Controller;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Request;
@@ -199,7 +200,7 @@ class SetupController extends Controller
});
$v->sometimes(['env.mail_username'], 'required', function ($input) {
return !in_array($input->env['mail_username'], ['sendmail']);
return !in_array($input->env['mail_driver'], ['sendmail', 'log']);
});
if ($v->passes()) {
@@ -240,7 +241,7 @@ class SetupController extends Controller
if ($v->passes()) {
// Pull the user details out.
$userDetails = array_pull($postData, 'user');
$userDetails = Arr::pull($postData, 'user');
$user = User::create([
'username' => $userDetails['username'],
@@ -253,13 +254,13 @@ class SetupController extends Controller
$setting = app(Repository::class);
$settings = array_pull($postData, 'settings');
$settings = Arr::pull($postData, 'settings');
foreach ($settings as $settingName => $settingValue) {
$setting->set($settingName, $settingValue);
}
$envData = array_pull($postData, 'env');
$envData = Arr::pull($postData, 'env');
// Write the env to the .env file.
execute(new UpdateConfigCommand($envData));
@@ -96,7 +96,8 @@ class StatusPageController extends AbstractApiController
$nextDate = $startDate->copy()->addDays($appIncidentDays)->toDateString();
}
$allIncidents = Incident::where('visible', '>=', (int) !Auth::check())->whereBetween('occurred_at', [
$allIncidents = Incident::with('component')->with('updates.incident')
->where('visible', '>=', (int) !Auth::check())->whereBetween('occurred_at', [
$endDate->format('Y-m-d').' 00:00:00',
$startDate->format('Y-m-d').' 23:59:59',
])->orderBy('occurred_at', 'desc')->get()->groupBy(function (Incident $incident) {
+1 -1
View File
@@ -213,6 +213,6 @@ class SubscribeController extends Controller
}
return cachet_redirect('subscribe.manage', $subscriber->verify_code)
->withSuccess(sprintf('%s %s', trans('dashboard.notifications.awesome'), trans('cachet.subscriber.email.subscribed')));
->withSuccess(sprintf('%s %s', trans('dashboard.notifications.awesome'), trans('cachet.subscriber.email.updated-subscribe')));
}
}
+15 -11
View File
@@ -11,16 +11,18 @@
namespace CachetHQ\Cachet\Http;
use AltThree\Throttle\ThrottlingMiddleware;
use Barryvdh\Cors\HandleCors;
use CachetHQ\Cachet\Http\Middleware\Admin;
use CachetHQ\Cachet\Http\Middleware\ApiAuthentication;
use CachetHQ\Cachet\Http\Middleware\Authenticate;
use CachetHQ\Cachet\Http\Middleware\CacheControl;
use CachetHQ\Cachet\Http\Middleware\Localize;
use CachetHQ\Cachet\Http\Middleware\ReadyForUse;
use CachetHQ\Cachet\Http\Middleware\RedirectIfAuthenticated;
use CachetHQ\Cachet\Http\Middleware\RemoteUserAuthenticate;
use CachetHQ\Cachet\Http\Middleware\SetupAlreadyCompleted;
use CachetHQ\Cachet\Http\Middleware\SubscribersConfigured;
use CachetHQ\Cachet\Http\Middleware\Throttler;
use CachetHQ\Cachet\Http\Middleware\TrustProxies;
use Illuminate\Auth\Middleware\Authorize;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
@@ -44,16 +46,18 @@ class Kernel extends HttpKernel
* @var array
*/
protected $routeMiddleware = [
'admin' => Admin::class,
'can' => Authorize::class,
'auth' => Authenticate::class,
'auth.api' => ApiAuthentication::class,
'admin' => Admin::class,
'auth.api' => ApiAuthentication::class,
'auth.remoteuser' => RemoteUserAuthenticate::class,
'guest' => RedirectIfAuthenticated::class,
'localize' => Localize::class,
'ready' => ReadyForUse::class,
'setup' => SetupAlreadyCompleted::class,
'subscribers' => SubscribersConfigured::class,
'throttle' => ThrottlingMiddleware::class,
'auth' => Authenticate::class,
'cache' => CacheControl::class,
'can' => Authorize::class,
'cors' => HandleCors::class,
'guest' => RedirectIfAuthenticated::class,
'localize' => Localize::class,
'ready' => ReadyForUse::class,
'setup' => SetupAlreadyCompleted::class,
'subscribers' => SubscribersConfigured::class,
'throttle' => Throttler::class,
];
}
+1 -1
View File
@@ -18,7 +18,7 @@ use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException;
/**
* This is the acceptable middleware class.
*
* @author Graham Campbell <james@alt-three.com>
* @author Graham Campbell <graham@alt-three.com>
* @author James Brooks <james@alt-three.com>
*/
class Acceptable
+1 -1
View File
@@ -20,7 +20,7 @@ use Symfony\Component\HttpKernel\Exception\HttpException;
* This is the admin middleware class.
*
* @author Joseph Cohen <joe@alt-three.com>
* @author Graham Campbell <james@alt-three.com>
* @author Graham Campbell <graham@alt-three.com>
* @author James Brooks <james@alt-three.com>
*/
class Admin
+1 -1
View File
@@ -22,7 +22,7 @@ use Symfony\Component\HttpKernel\Exception\HttpException;
* This is the api authentication middleware class.
*
* @author Joseph Cohen <joe@alt-three.com>
* @author Graham Campbell <james@alt-three.com>
* @author Graham Campbell <graham@alt-three.com>
* @author James Brooks <james@alt-three.com>
*/
class ApiAuthentication
+1 -1
View File
@@ -20,7 +20,7 @@ use Symfony\Component\HttpKernel\Exception\HttpException;
* This is the authenticate middleware class.
*
* @author Joseph Cohen <joe@alt-three.com>
* @author Graham Campbell <james@alt-three.com>
* @author Graham Campbell <graham@alt-three.com>
* @author James Brooks <james@alt-three.com>
*/
class Authenticate
+37
View File
@@ -0,0 +1,37 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class CacheControl
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
*
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
$response = $next($request);
$maxAge = time() + 30;
$response->header('Cache-Control', 'public,max-age='.$maxAge);
return $response;
}
}
+1 -1
View File
@@ -22,7 +22,7 @@ use Jenssegers\Date\Date;
*
* @author James Brooks <james@alt-three.com>
* @author Joseph Cohen <joe@alt-three.com>
* @author Graham Campbell <james@alt-three.com>
* @author Graham Campbell <graham@alt-three.com>
*/
class Localize
{
+1 -1
View File
@@ -18,7 +18,7 @@ use Illuminate\Http\Request;
/**
* This is the ready for use middleware class.
*
* @author Graham Campbell <james@alt-three.com>
* @author Graham Campbell <graham@alt-three.com>
* @author James Brooks <james@alt-three.com>
* @author Joseph Cohen <joe@alt-three.com>
*/
@@ -18,7 +18,7 @@ use Illuminate\Http\Request;
/**
* This is the redirect if authenticated middleware class.
*
* @author Graham Campbell <james@alt-three.com>
* @author Graham Campbell <graham@alt-three.com>
* @author Joseph Cohen <joe@alt-three.com>
* @author James Brooks <james@alt-three.com>
*/
@@ -19,7 +19,7 @@ use Illuminate\Http\Request;
/**
* This is the setup already completed middelware class.
*
* @author Graham Campbell <james@alt-three.com>
* @author Graham Campbell <graham@alt-three.com>
* @author James Brooks <james@alt-three.com>
* @author Joseph Cohen <joe@alt-three.com>
*/
@@ -19,7 +19,7 @@ use Illuminate\Http\Request;
* This is the subscribers configured middleware class.
*
* @author James Brooks <james@alt-three.com>
* @author Graham Campbell <james@alt-three.com>
* @author Graham Campbell <graham@alt-three.com>
*/
class SubscribersConfigured
{
+125
View File
@@ -0,0 +1,125 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Http\Middleware;
use Closure;
use Illuminate\Cache\RateLimiter;
use Illuminate\Http\Request;
use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException;
/**
* This is the throttler middleware class.
*
* @author Graham Campbell <graham@alt-three.com>
*/
class Throttler
{
/**
* The rate limiter instance.
*
* @var \Illuminate\Cache\RateLimiter
*/
protected $limiter;
/**
* Create a new throttler middleware instance.
*
* @param \Illuminate\Cache\RateLimiter $limiter
*
* @return void
*/
public function __construct(RateLimiter $limiter)
{
$this->limiter = $limiter;
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param int|string $limit
* @param int|string $decay
*
* @throws \Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException
*
* @return mixed
*/
public function handle(Request $request, Closure $next, $limit = 60, $decay = 1)
{
return $this->safeHandle($request, $next, (int) $limit, (int) $decay);
}
/**
* Handle an incoming request, with correct types.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param int $limit
* @param int $decay
*
* @throws \Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException
*
* @return mixed
*/
protected function safeHandle(Request $request, Closure $next, int $limit, int $decay)
{
$key = $request->fingerprint();
if ($this->limiter->tooManyAttempts($key, $limit, $decay)) {
throw $this->buildException($key, $limit);
}
$this->limiter->hit($key, $decay);
$response = $next($request);
$response->headers->add($this->getHeaders($key, $limit));
return $response;
}
/**
* Create a too many requests http exception.
*
* @param string $key
* @param int $limit
*
* @return \Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException
*/
protected function buildException(string $key, int $limit)
{
$after = $this->limiter->availableIn($key);
$exception = new TooManyRequestsHttpException($after, 'Rate limit exceeded.');
$exception->setHeaders($this->getHeaders($key, $limit, $after, $exception->getHeaders()));
return $exception;
}
/**
* Get the limit header information.
*
* @param string $key
* @param int $limit
* @param int|null $after
* @param array $merge
*
* @return array
*/
protected function getHeaders(string $key, int $limit, int $after = null, array $merge = [])
{
$remaining = $after === null ? $this->limiter->retriesLeft($key, $limit) : 0;
$headers = ['X-RateLimit-Limit' => $limit, 'X-RateLimit-Remaining' => $remaining];
return array_merge($headers, $merge);
}
}
+1 -1
View File
@@ -19,7 +19,7 @@ use Illuminate\Http\Request;
* This is the timezone middleware class.
*
* @author James Brooks <james@alt-three.com>
* @author Graham Campbell <james@alt-three.com>
* @author Graham Campbell <graham@alt-three.com>
*/
class Timezone
{
+38
View File
@@ -0,0 +1,38 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
/**
* This is the verify csrf token middleware class.
*
* @author James Brooks <james@alt-three.com>
*/
class VerifyCsrfToken extends Middleware
{
/**
* Indicates whether the XSRF-TOKEN cookie should be set on the response.
*
* @var bool
*/
protected $addHttpCookie = true;
/**
* The URIs that should be excluded from CSRF verification.
*
* @var array
*/
protected $except = [
'/api/*',
];
}
+1 -1
View File
@@ -40,7 +40,7 @@ class ApiRoutes
'namespace' => 'Api',
'prefix' => 'api/v1',
], function (Registrar $router) {
$router->group(['middleware' => ['auth.api']], function (Registrar $router) {
$router->group(['middleware' => ['auth.api', 'cors']], function (Registrar $router) {
$router->get('components', 'ComponentController@index');
$router->get('components/groups', 'ComponentGroupController@index');
$router->get('components/groups/{component_group}', 'ComponentGroupController@show');
+1 -1
View File
@@ -43,7 +43,7 @@ class ApiSystemRoutes
$router->group(['middleware' => ['auth.api']], function (Registrar $router) {
$router->get('ping', 'GeneralController@ping');
$router->get('version', 'GeneralController@version');
$router->get('status', 'GeneralController@status');
$router->get('status', ['uses' => 'GeneralController@status', 'middleware' => ['cache']]);
});
});
}
+2 -1
View File
@@ -25,6 +25,7 @@ use CachetHQ\Cachet\Settings\Repository as Setting;
use Exception;
use GuzzleHttp\Client;
use Illuminate\Contracts\Config\Repository;
use Illuminate\Support\Str;
/**
* This is the beacon class.
@@ -84,7 +85,7 @@ class Beacon implements BeaconContract
$setting = app(Setting::class);
if (!$installId = $setting->get('install_id', null)) {
$installId = sha1(str_random(20));
$installId = sha1(Str::random(20));
$setting->set('install_id', $installId);
}
+1 -1
View File
@@ -28,7 +28,7 @@ class Feed implements FeedContract
*
* @var string
*/
const URL = 'https://blog.alt-three.com/tag/cachet/rss';
const URL = 'https://alt-three.com/tag/cachet/rss';
/**
* The failed status indicator.
+7 -11
View File
@@ -12,6 +12,7 @@
namespace CachetHQ\Cachet\Models;
use AltThree\Validator\ValidatingTrait;
use CachetHQ\Cachet\Models\Traits\HasMeta;
use CachetHQ\Cachet\Models\Traits\HasTags;
use CachetHQ\Cachet\Models\Traits\SearchableTrait;
use CachetHQ\Cachet\Models\Traits\SortableTrait;
@@ -23,7 +24,12 @@ use McCool\LaravelAutoPresenter\HasPresenter;
class Component extends Model implements HasPresenter
{
use HasTags, SearchableTrait, SoftDeletes, SortableTrait, ValidatingTrait;
use HasTags,
HasMeta,
SearchableTrait,
SoftDeletes,
SortableTrait,
ValidatingTrait;
/**
* List of attributes that have default values.
@@ -134,16 +140,6 @@ class Component extends Model implements HasPresenter
return $this->hasMany(Incident::class, 'component_id', 'id');
}
/**
* Get the meta relation.
*
* @return \Illuminate\Database\Eloquent\Relations\MorphMany
*/
public function meta()
{
return $this->morphMany(Meta::class, 'meta');
}
/**
* Finds all components by status.
*
+7 -11
View File
@@ -12,6 +12,7 @@
namespace CachetHQ\Cachet\Models;
use AltThree\Validator\ValidatingTrait;
use CachetHQ\Cachet\Models\Traits\HasMeta;
use CachetHQ\Cachet\Models\Traits\HasTags;
use CachetHQ\Cachet\Models\Traits\SearchableTrait;
use CachetHQ\Cachet\Models\Traits\SortableTrait;
@@ -30,7 +31,12 @@ use McCool\LaravelAutoPresenter\HasPresenter;
*/
class Incident extends Model implements HasPresenter
{
use HasTags, SearchableTrait, SoftDeletes, SortableTrait, ValidatingTrait;
use HasMeta,
HasTags,
SearchableTrait,
SoftDeletes,
SortableTrait,
ValidatingTrait;
/**
* Status for incident being investigated.
@@ -181,16 +187,6 @@ class Incident extends Model implements HasPresenter
return $this->belongsTo(Component::class, 'component_id', 'id');
}
/**
* Get all of the meta relation.
*
* @return \Illuminate\Database\Eloquent\Relations\MorphMany
*/
public function meta()
{
return $this->morphMany(Meta::class, 'meta');
}
/**
* Get the updates relation.
*
+2 -1
View File
@@ -13,6 +13,7 @@ namespace CachetHQ\Cachet\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Str;
/**
* This is the invite class.
@@ -51,7 +52,7 @@ class Invite extends Model
self::creating(function ($invite) {
if (!$invite->code) {
$invite->code = str_random(20);
$invite->code = Str::random(20);
}
});
}
+4 -11
View File
@@ -13,6 +13,7 @@ namespace CachetHQ\Cachet\Models;
use AltThree\Validator\ValidatingTrait;
use AltThree\Validator\ValidationException;
use CachetHQ\Cachet\Models\Traits\HasMeta;
use CachetHQ\Cachet\Models\Traits\SortableTrait;
use CachetHQ\Cachet\Presenters\MetricPresenter;
use Illuminate\Database\Eloquent\Builder;
@@ -22,7 +23,9 @@ use McCool\LaravelAutoPresenter\HasPresenter;
class Metric extends Model implements HasPresenter
{
use SortableTrait, ValidatingTrait;
use HasMeta,
SortableTrait,
ValidatingTrait;
/**
* The calculation type of sum.
@@ -165,16 +168,6 @@ class Metric extends Model implements HasPresenter
});
}
/**
* Get the meta relation.
*
* @return \Illuminate\Database\Eloquent\Relations\MorphMany
*/
public function meta()
{
return $this->morphMany(Meta::class, 'meta');
}
/**
* Get the points relation.
*
+31 -15
View File
@@ -12,6 +12,7 @@
namespace CachetHQ\Cachet\Models;
use AltThree\Validator\ValidatingTrait;
use CachetHQ\Cachet\Models\Traits\HasMeta;
use CachetHQ\Cachet\Models\Traits\SearchableTrait;
use CachetHQ\Cachet\Models\Traits\SortableTrait;
use CachetHQ\Cachet\Presenters\SchedulePresenter;
@@ -21,14 +22,13 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use McCool\LaravelAutoPresenter\HasPresenter;
/**
* This is the schedule class.
*
* @author James Brooks <james@alt-three.com>
*/
class Schedule extends Model implements HasPresenter
{
use SearchableTrait, SoftDeletes, SortableTrait, ValidatingTrait;
use HasMeta,
SearchableTrait,
SoftDeletes,
SortableTrait,
ValidatingTrait;
/**
* The upcoming status.
@@ -144,13 +144,17 @@ class Schedule extends Model implements HasPresenter
}
/**
* Get the meta relation.
* Scope schedules that are uncompleted.
*
* @return \Illuminate\Database\Eloquent\Relations\MorphMany
* @param \Illuminate\Database\Eloquent\Builder $query
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function meta()
public function scopeUncompleted(Builder $query)
{
return $this->morphMany(Meta::class, 'meta');
return $query->whereIn('status', [self::UPCOMING, self::IN_PROGRESS])->where(function (Builder $query) {
return $query->whereNull('completed_at');
});
}
/**
@@ -163,7 +167,7 @@ class Schedule extends Model implements HasPresenter
public function scopeInProgress(Builder $query)
{
return $query->where('scheduled_at', '<=', Carbon::now())->where('status', '<>', self::COMPLETE)->where(function ($query) {
$query->whereNull('completed_at')->orWhere('completed_at', '>', Carbon::now());
$query->whereNull('completed_at');
});
}
@@ -174,21 +178,33 @@ class Schedule extends Model implements HasPresenter
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeFutureSchedules($query)
public function scopeScheduledInFuture($query)
{
return $query->whereIn('status', [self::UPCOMING, self::IN_PROGRESS])->where('scheduled_at', '>=', Carbon::now());
}
/**
* Scopes schedules to those in the past.
* Scopes schedules to those scheduled in the past.
*
* @param \Illuminate\Database\Eloquent\Builder $query
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopePastSchedules($query)
public function scopeScheduledInPast($query)
{
return $query->where('status', '<', self::COMPLETE)->where('scheduled_at', '<=', Carbon::now());
return $query->whereIn('status', [self::UPCOMING, self::IN_PROGRESS])->where('scheduled_at', '<=', Carbon::now());
}
/**
* Scopes schedules to those completed in the past.
*
* @param \Illuminate\Database\Eloquent\Builder $query
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeCompletedInPast($query)
{
return $query->where('status', '=', self::COMPLETE)->where('completed_at', '<=', Carbon::now());
}
/**
+6 -12
View File
@@ -12,10 +12,12 @@
namespace CachetHQ\Cachet\Models;
use AltThree\Validator\ValidatingTrait;
use CachetHQ\Cachet\Models\Traits\HasMeta;
use CachetHQ\Cachet\Presenters\SubscriberPresenter;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Str;
use McCool\LaravelAutoPresenter\HasPresenter;
/**
@@ -27,7 +29,9 @@ use McCool\LaravelAutoPresenter\HasPresenter;
*/
class Subscriber extends Model implements HasPresenter
{
use Notifiable, ValidatingTrait;
use HasMeta,
Notifiable,
ValidatingTrait;
/**
* The attributes that should be casted to native types.
@@ -90,16 +94,6 @@ class Subscriber extends Model implements HasPresenter
});
}
/**
* Get the meta relation.
*
* @return \Illuminate\Database\Eloquent\Relations\MorphMany
*/
public function meta()
{
return $this->morphMany(Meta::class, 'meta');
}
/**
* Get the subscriptions relation.
*
@@ -166,7 +160,7 @@ class Subscriber extends Model implements HasPresenter
*/
public static function generateVerifyCode()
{
return str_random(42);
return Str::random(42);
}
/**
+32
View File
@@ -0,0 +1,32 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Models\Traits;
use CachetHQ\Cachet\Models\Meta;
/**
* This is the has meta trait.
*
* @author James Brooks <james@alt-three.com>
*/
trait HasMeta
{
/**
* Get the meta relation.
*
* @return \Illuminate\Database\Eloquent\Relations\MorphMany
*/
public function meta()
{
return $this->morphMany(Meta::class, 'meta');
}
}
+2 -1
View File
@@ -18,6 +18,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use McCool\LaravelAutoPresenter\HasPresenter;
/**
@@ -188,7 +189,7 @@ class User extends Authenticatable implements HasPresenter
*/
public static function generateApiKey()
{
return str_random(20);
return Str::random(20);
}
/**
@@ -128,7 +128,7 @@ class NewIncidentNotification extends Notification
->$status()
->content($content)
->attachment(function ($attachment) use ($notifiable) {
$attachment->title(trans('notifications.incident.new.slack.title', [$this->incident->name]))
$attachment->title(trans('notifications.incident.new.slack.title', ['name' => $this->incident->name]))
->timestamp($this->incident->getWrappedObject()->occurred_at)
->fields(array_filter([
'ID' => "#{$this->incident->id}",
@@ -78,6 +78,7 @@ class IncidentUpdatedNotification extends Notification
->subject(trans('notifications.incident.update.mail.subject'))
->markdown('notifications.incident.update', [
'incident' => $this->update->incident,
'update' => $this->update,
'content' => $content,
'actionText' => trans('notifications.incident.new.mail.action'),
'actionUrl' => cachet_route('incident', [$this->update->incident]),
+24 -3
View File
@@ -20,6 +20,13 @@ class ComponentGroupPresenter extends BasePresenter implements Arrayable
{
use TimestampsTrait;
/**
* Flag for the enabled_components_lowest function.
*
* @var bool
*/
protected $enabledComponentsLowest = false;
/**
* Returns the lowest component status.
*
@@ -27,7 +34,7 @@ class ComponentGroupPresenter extends BasePresenter implements Arrayable
*/
public function lowest_status()
{
if ($component = $this->wrappedObject->enabled_components_lowest()->first()) {
if ($component = $this->enabled_components_lowest()) {
return AutoPresenter::decorate($component)->status;
}
}
@@ -39,7 +46,7 @@ class ComponentGroupPresenter extends BasePresenter implements Arrayable
*/
public function lowest_human_status()
{
if ($component = $this->wrappedObject->enabled_components_lowest()->first()) {
if ($component = $this->enabled_components_lowest()) {
return AutoPresenter::decorate($component)->human_status;
}
}
@@ -51,11 +58,25 @@ class ComponentGroupPresenter extends BasePresenter implements Arrayable
*/
public function lowest_status_color()
{
if ($component = $this->wrappedObject->enabled_components_lowest()->first()) {
if ($component = $this->enabled_components_lowest()) {
return AutoPresenter::decorate($component)->status_color;
}
}
/**
* Return the enabled components from the wrapped object, and cache it if need be.
*
* @return bool
*/
public function enabled_components_lowest()
{
if (is_bool($this->enabledComponentsLowest)) {
$this->enabledComponentsLowest = $this->wrappedObject->enabled_components_lowest()->first();
}
return $this->enabledComponentsLowest;
}
/**
* Determine the class for collapsed/uncollapsed groups.
*
+11 -2
View File
@@ -29,6 +29,13 @@ class IncidentPresenter extends BasePresenter implements Arrayable
*/
protected $dates;
/**
* Flag for the latest function.
*
* @var bool
*/
protected $latest = false;
/**
* Incident icon lookup.
*
@@ -248,9 +255,11 @@ class IncidentPresenter extends BasePresenter implements Arrayable
*/
public function latest()
{
if ($update = $this->wrappedObject->updates()->orderBy('created_at', 'desc')->first()) {
return $update;
if (is_bool($this->latest)) {
$this->latest = $this->wrappedObject->updates()->first();
}
return $this->latest;
}
/**
+2 -1
View File
@@ -12,6 +12,7 @@
namespace CachetHQ\Cachet\Presenters;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Support\Facades\Config;
use Laravolt\Avatar\Facade as Avatar;
use McCool\LaravelAutoPresenter\BasePresenter;
@@ -29,7 +30,7 @@ class UserPresenter extends BasePresenter implements Arrayable
*/
public function avatar()
{
if (setting('enable_external_dependencies')) {
if (Config::get('setting.enable_external_dependencies')) {
return sprintf('https://www.gravatar.com/avatar/%s?size=%d', md5(strtolower($this->email)), 200);
}
@@ -108,7 +108,7 @@ abstract class AbstractMetricRepository
$point->value = $metric->default_value;
}
if ($point->value === 0 && $metric->default_value != $value) {
if ($point->value === 0 && $metric->default_value != $point->value) {
$point->value = $metric->default_value;
}
+2 -2
View File
@@ -38,7 +38,7 @@ class PgSqlRepository extends AbstractMetricRepository implements MetricInterfac
"AND {$this->getMetricPointsTable()}.created_at >= (NOW() - INTERVAL '{$minutes}' MINUTE) ".
"AND {$this->getMetricPointsTable()}.created_at <= NOW() ".
"GROUP BY to_char({$this->getMetricPointsTable()}.created_at, 'HH24:MI') ".
"ORDER BY to_char({$this->getMetricPointsTable()}.created_at, 'HH24:MI')", [
"ORDER BY {$this->getMetricPointsTable()}.created_at", [
'metricId' => $metric->id,
]);
@@ -62,7 +62,7 @@ class PgSqlRepository extends AbstractMetricRepository implements MetricInterfac
"AND {$this->getMetricPointsTable()}.created_at >= (NOW() - INTERVAL '{$hour}' HOUR) ".
"AND {$this->getMetricPointsTable()}.created_at <= NOW() ".
"GROUP BY to_char({$this->getMetricPointsTable()}.created_at, 'HH24:00') ".
"ORDER BY to_char({$this->getMetricPointsTable()}.created_at, 'HH24:00')", [
"ORDER BY {$this->getMetricPointsTable()}.created_at", [
'metricId' => $metric->id,
]);
+1 -1
View File
@@ -177,7 +177,7 @@ class CommandSubscriber
*/
public function onPublishVendors(Command $command)
{
$command->call('vendor:publish');
$command->call('vendor:publish', ['--all' => true]);
}
/**
+1 -3
View File
@@ -36,7 +36,6 @@
"alt-three/badger": "^5.1",
"alt-three/bus": "^4.1",
"alt-three/emoji": "^7.0",
"alt-three/throttle": "^3.1",
"alt-three/twitter": "^3.1",
"alt-three/validator": "^4.1",
"aws/aws-sdk-php": "^3.7",
@@ -61,14 +60,13 @@
"ext-sqlite3": "*",
"alt-three/testbench": "^4.0",
"barryvdh/laravel-debugbar": "^3.2",
"bugsnag/bugsnag-laravel": "^2.15",
"filp/whoops": "^2.3",
"fzaninotto/faker": "^1.8",
"graham-campbell/analyzer": "^2.1",
"graham-campbell/testbench-core": "^3.0",
"mockery/mockery": "^1.2",
"phpunit/phpunit": "^7.4",
"symfony/css-selector": "^4.1",
"symfony/dom-crawler": "^4.1",
"tightenco/mailthief": "^0.3.14"
},
"suggest": {
Generated
+1196 -596
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -173,6 +173,7 @@ return [
/*
* Packages Service Providers...
*/
env('APP_DEBUG') ? Bugsnag\BugsnagLaravel\BugsnagServiceProvider::class : null,
AltThree\Badger\BadgerServiceProvider::class,
AltThree\Emoji\EmojiServiceProvider::class,
AltThree\Twitter\TwitterServiceProvider::class,
+10 -7
View File
@@ -10,6 +10,7 @@
*/
return [
/*
|--------------------------------------------------------------------------
| Laravel CORS
@@ -19,11 +20,13 @@ return [
| to accept any value.
|
*/
'supportsCredentials' => false,
'allowedOrigins' => ['*'],
'allowedHeaders' => ['X-Cachet-Token'],
'allowedMethods' => ['*'],
'exposedHeaders' => [],
'maxAge' => 3600,
'hosts' => [],
'supportsCredentials' => false,
'allowedOrigins' => ['*'],
'allowedOriginsPatterns' => [],
'allowedHeaders' => ['X-Cachet-Token'],
'allowedMethods' => ['*'],
'exposedHeaders' => [],
'maxAge' => 3600,
];
+1 -1
View File
@@ -72,7 +72,7 @@ return [
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => env('DB_PREFIX', null),
'schema' => 'public',
'schema' => env('DB_SCHEMA', 'public'),
'sslmode' => 'prefer',
],
+9
View File
@@ -85,6 +85,15 @@ return [
'driver' => 'errorlog',
'level' => 'debug',
],
'bugsnag' => [
'driver' => 'bugsnag',
],
'debug' => [
'driver' => 'stack',
'channels' => ['bugsnag', 'single'],
],
],
];
+8 -9
View File
@@ -11,16 +11,15 @@
},
"devDependencies": {
"animate-sass": "^0.8.2",
"autosize": "^3.0.20",
"axios": "^0.18",
"bootstrap-sass": "^3.3.6",
"chart.js": "^2.7.0",
"bootstrap-sass": "^3.4.1",
"chart.js": "^2.8.0",
"cross-env": "^5.1",
"es5-shim": "^4.5.9",
"flatpickr": "^4.5.0",
"flatpickr": "^4.5.7",
"github-markdown-css": "^2.3.0",
"ionicons": "~2.0",
"jquery": "^2.2.4",
"jquery": "^3.4.0",
"jquery-minicolors": "^2.1.10",
"jquery-serializeobject": "^1.0.0",
"jquery-sparkline": "^2.4.0",
@@ -29,12 +28,12 @@
"livestamp": "git+https://github.com/mattbradley/livestampjs.git#develop",
"lodash": "^4.17.11",
"messenger": "git+https://github.com/HubSpot/messenger.git",
"moment": "^2.17.1",
"moment": "^2.24.0",
"promise": "^7.3.1",
"sortablejs": "^1.6.1",
"sortablejs": "^1.8.4",
"sweetalert2": "^6.8.0",
"vue": "^2.5.17",
"vue-template-compiler": "^2.5.16"
"vue": "^2.6.10",
"vue-template-compiler": "^2.6.10"
},
"private": true
}
+2 -6
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+28 -27
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+6 -8
View File
@@ -1,10 +1,8 @@
{
"/dist/js/vendor.js": "/dist/js/vendor.js",
"/dist/js/app.js": "/dist/js/app.js",
"/dist/css/dashboard/dashboard.css": "/dist/css/dashboard/dashboard.css",
"/dist/css/app.css": "/dist/css/app.css",
"/dist/js/manifest.js": "/dist/js/manifest.js",
"/resources/assets/sass/plugins/_jquery.minicolors.scss": "/resources/assets/sass/plugins/_jquery.minicolors.scss",
"/resources/assets/sass/plugins/_github-markdown.scss": "/resources/assets/sass/plugins/_github-markdown.scss",
"/dist/js/all.js": "/dist/js/all.js"
"/dist/js/vendor.js": "/dist/js/vendor.js?id=313e4cd2cf600307cb5c",
"/dist/js/app.js": "/dist/js/app.js?id=7877550e52e1d4e8d66b",
"/dist/css/dashboard/dashboard.css": "/dist/css/dashboard/dashboard.css?id=0d9dfb3411fe9391898f",
"/dist/css/app.css": "/dist/css/app.css?id=1b9032e972af93e2c869",
"/dist/js/manifest.js": "/dist/js/manifest.js?id=40dcfff9d09d402daf38",
"/dist/js/all.js": "/dist/js/all.js?id=498db5622a6525cca7e2"
}
+8 -12
View File
@@ -216,7 +216,9 @@ $(function () {
$('input[name=remove_banner]').val('1');
});
$('.group-name').on('click', function () {
$('.group-name').on('click', function (event) {
event.stopPropagation();
var $this = $(this);
$this.find('.group-toggle').toggleClass('ion-ios-minus-outline').toggleClass('ion-ios-plus-outline');
@@ -224,20 +226,16 @@ $(function () {
$this.next('.group-items').toggleClass('hide');
});
$('.select-group').on('click', function () {
$('.select-group').on('click', function (event) {
var $parentGroup = $(this).closest('ul.list-group');
$parentGroup.find('input[type=checkbox]').prop('checked', true);
$parentGroup.find('.group-items').removeClass('hide')
$parentGroup.find('.group-toggle').addClass('ion-ios-minus-outline').removeClass('ion-ios-plus-outline');
event.stopPropagation();
return false;
});
$('.deselect-group').on('click', function () {
$('.deselect-group').on('click', function (event) {
var $parentGroup = $(this).closest('ul.list-group');
$parentGroup.find('input[type=checkbox]').prop('checked', false);
$parentGroup.find('.group-items').addClass('hide');
$parentGroup.find('.group-toggle').removeClass('ion-ios-minus-outline').addClass('ion-ios-plus-outline');
event.stopPropagation();
return false;
});
@@ -253,7 +251,8 @@ $(function () {
// Only validate going forward. If current group is invalid, do not go further
if (next > current) {
var url = '/setup/step' + current;
var currentUrl = window.location.href.replace(/step\d/, '');
var url = currentUrl + '/step' + current;
$.post(url, $form.serializeObject())
.done(function(response) {
goToStep(current, next);
@@ -308,7 +307,7 @@ $(function () {
});
};
sparkLine(false);
sparkLine();
}
function goToStep(current, next) {
@@ -327,9 +326,6 @@ $(function () {
.addClass("active");
}
// Password strength
$('.password-strength').strengthify();
// Check for updates.
if ($('#update-alert').length > 0) {
$.ajax({
@@ -2,6 +2,7 @@
const Vue = require('vue');
Vue.component('report-incident', require('./ReportIncident'));
Vue.component('report-schedule', require('./ReportSchedule'));
Vue.component('invite-team', require('./InviteTeam'));
module.exports = {
@@ -0,0 +1,30 @@
<script>
module.exports = {
data () {
return {
template: null,
name: '',
message: ''
}
},
methods: {
getTemplate (template) {
axios.get('/dashboard/api/incidents/templates', {
params: {
slug: template
}
}).then(response => {
this.name = response.data.name
this.message = response.data.template
}).catch(response => {
(new Cachet.Notifier()).notify('There was an error finding that template.');
})
}
},
watch: {
'template' (template) {
this.getTemplate(template)
}
}
}
</script>
+1
View File
@@ -2,6 +2,7 @@
$ionicons-font-path: "../../../fonts" !default;
@import "./node_modules/ionicons/scss/ionicons";
@import "./node_modules/github-markdown-css/github-markdown";
@import "modules/bootstrap";
@import "plugins/flatpickr";
+3 -2
View File
@@ -1,5 +1,8 @@
@import "vendors";
// Vendors for sDshboard.
@import "./node_modules/jquery-minicolors/jquery.minicolors";
// Styles for partials
@import "dashboard/partials/base";
@import "dashboard/partials/wrapper";
@@ -16,10 +19,8 @@
// Styles for plugins
/*! purgecss start ignore */
@import "plugins/jquery.minicolors";
@import "plugins/github-markdown";
@import "plugins/sweetalert";
@import "plugins/messenger";
@import "plugins/animate";
@import "plugins/password-strength";
@import "plugins/sortable";
/*! purgecss end ignore */
-695
View File
@@ -1,695 +0,0 @@
@font-face {
font-family: octicons-link;
src: url(data:font/woff;charset=utf-8;base64,d09GRgABAAAAAAZwABAAAAAACFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEU0lHAAAGaAAAAAgAAAAIAAAAAUdTVUIAAAZcAAAACgAAAAoAAQAAT1MvMgAAAyQAAABJAAAAYFYEU3RjbWFwAAADcAAAAEUAAACAAJThvmN2dCAAAATkAAAABAAAAAQAAAAAZnBnbQAAA7gAAACyAAABCUM+8IhnYXNwAAAGTAAAABAAAAAQABoAI2dseWYAAAFsAAABPAAAAZwcEq9taGVhZAAAAsgAAAA0AAAANgh4a91oaGVhAAADCAAAABoAAAAkCA8DRGhtdHgAAAL8AAAADAAAAAwGAACfbG9jYQAAAsAAAAAIAAAACABiATBtYXhwAAACqAAAABgAAAAgAA8ASm5hbWUAAAToAAABQgAAAlXu73sOcG9zdAAABiwAAAAeAAAAME3QpOBwcmVwAAAEbAAAAHYAAAB/aFGpk3jaTY6xa8JAGMW/O62BDi0tJLYQincXEypYIiGJjSgHniQ6umTsUEyLm5BV6NDBP8Tpts6F0v+k/0an2i+itHDw3v2+9+DBKTzsJNnWJNTgHEy4BgG3EMI9DCEDOGEXzDADU5hBKMIgNPZqoD3SilVaXZCER3/I7AtxEJLtzzuZfI+VVkprxTlXShWKb3TBecG11rwoNlmmn1P2WYcJczl32etSpKnziC7lQyWe1smVPy/Lt7Kc+0vWY/gAgIIEqAN9we0pwKXreiMasxvabDQMM4riO+qxM2ogwDGOZTXxwxDiycQIcoYFBLj5K3EIaSctAq2kTYiw+ymhce7vwM9jSqO8JyVd5RH9gyTt2+J/yUmYlIR0s04n6+7Vm1ozezUeLEaUjhaDSuXHwVRgvLJn1tQ7xiuVv/ocTRF42mNgZGBgYGbwZOBiAAFGJBIMAAizAFoAAABiAGIAznjaY2BkYGAA4in8zwXi+W2+MjCzMIDApSwvXzC97Z4Ig8N/BxYGZgcgl52BCSQKAA3jCV8CAABfAAAAAAQAAEB42mNgZGBg4f3vACQZQABIMjKgAmYAKEgBXgAAeNpjYGY6wTiBgZWBg2kmUxoDA4MPhGZMYzBi1AHygVLYQUCaawqDA4PChxhmh/8ODDEsvAwHgMKMIDnGL0x7gJQCAwMAJd4MFwAAAHjaY2BgYGaA4DAGRgYQkAHyGMF8NgYrIM3JIAGVYYDT+AEjAwuDFpBmA9KMDEwMCh9i/v8H8sH0/4dQc1iAmAkALaUKLgAAAHjaTY9LDsIgEIbtgqHUPpDi3gPoBVyRTmTddOmqTXThEXqrob2gQ1FjwpDvfwCBdmdXC5AVKFu3e5MfNFJ29KTQT48Ob9/lqYwOGZxeUelN2U2R6+cArgtCJpauW7UQBqnFkUsjAY/kOU1cP+DAgvxwn1chZDwUbd6CFimGXwzwF6tPbFIcjEl+vvmM/byA48e6tWrKArm4ZJlCbdsrxksL1AwWn/yBSJKpYbq8AXaaTb8AAHja28jAwOC00ZrBeQNDQOWO//sdBBgYGRiYWYAEELEwMTE4uzo5Zzo5b2BxdnFOcALxNjA6b2ByTswC8jYwg0VlNuoCTWAMqNzMzsoK1rEhNqByEyerg5PMJlYuVueETKcd/89uBpnpvIEVomeHLoMsAAe1Id4AAAAAAAB42oWQT07CQBTGv0JBhagk7HQzKxca2sJCE1hDt4QF+9JOS0nbaaYDCQfwCJ7Au3AHj+LO13FMmm6cl7785vven0kBjHCBhfpYuNa5Ph1c0e2Xu3jEvWG7UdPDLZ4N92nOm+EBXuAbHmIMSRMs+4aUEd4Nd3CHD8NdvOLTsA2GL8M9PODbcL+hD7C1xoaHeLJSEao0FEW14ckxC+TU8TxvsY6X0eLPmRhry2WVioLpkrbp84LLQPGI7c6sOiUzpWIWS5GzlSgUzzLBSikOPFTOXqly7rqx0Z1Q5BAIoZBSFihQYQOOBEdkCOgXTOHA07HAGjGWiIjaPZNW13/+lm6S9FT7rLHFJ6fQbkATOG1j2OFMucKJJsxIVfQORl+9Jyda6Sl1dUYhSCm1dyClfoeDve4qMYdLEbfqHf3O/AdDumsjAAB42mNgYoAAZQYjBmyAGYQZmdhL8zLdDEydARfoAqIAAAABAAMABwAKABMAB///AA8AAQAAAAAAAAAAAAAAAAABAAAAAA==) format('woff');
}
.markdown-body {
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
line-height: 1.5;
color: #24292e;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
font-size: 16px;
line-height: 1.5;
word-wrap: break-word;
}
.markdown-body .pl-c {
color: #6a737d;
}
.markdown-body .pl-c1,
.markdown-body .pl-s .pl-v {
color: #005cc5;
}
.markdown-body .pl-e,
.markdown-body .pl-en {
color: #6f42c1;
}
.markdown-body .pl-smi,
.markdown-body .pl-s .pl-s1 {
color: #24292e;
}
.markdown-body .pl-ent {
color: #22863a;
}
.markdown-body .pl-k {
color: #d73a49;
}
.markdown-body .pl-s,
.markdown-body .pl-pds,
.markdown-body .pl-s .pl-pse .pl-s1,
.markdown-body .pl-sr,
.markdown-body .pl-sr .pl-cce,
.markdown-body .pl-sr .pl-sre,
.markdown-body .pl-sr .pl-sra {
color: #032f62;
}
.markdown-body .pl-v,
.markdown-body .pl-smw {
color: #e36209;
}
.markdown-body .pl-bu {
color: #b31d28;
}
.markdown-body .pl-ii {
color: #fafbfc;
background-color: #b31d28;
}
.markdown-body .pl-c2 {
color: #fafbfc;
background-color: #d73a49;
}
.markdown-body .pl-c2::before {
content: "^M";
}
.markdown-body .pl-sr .pl-cce {
font-weight: bold;
color: #22863a;
}
.markdown-body .pl-ml {
color: #735c0f;
}
.markdown-body .pl-mh,
.markdown-body .pl-mh .pl-en,
.markdown-body .pl-ms {
font-weight: bold;
color: #005cc5;
}
.markdown-body .pl-mi {
font-style: italic;
color: #24292e;
}
.markdown-body .pl-mb {
font-weight: bold;
color: #24292e;
}
.markdown-body .pl-md {
color: #b31d28;
background-color: #ffeef0;
}
.markdown-body .pl-mi1 {
color: #22863a;
background-color: #f0fff4;
}
.markdown-body .pl-mc {
color: #e36209;
background-color: #ffebda;
}
.markdown-body .pl-mi2 {
color: #f6f8fa;
background-color: #005cc5;
}
.markdown-body .pl-mdr {
font-weight: bold;
color: #6f42c1;
}
.markdown-body .pl-ba {
color: #586069;
}
.markdown-body .pl-sg {
color: #959da5;
}
.markdown-body .pl-corl {
text-decoration: underline;
color: #032f62;
}
.markdown-body .octicon {
display: inline-block;
vertical-align: text-top;
fill: currentColor;
}
.markdown-body a {
background-color: transparent;
}
.markdown-body a:active,
.markdown-body a:hover {
outline-width: 0;
}
.markdown-body strong {
font-weight: inherit;
}
.markdown-body strong {
font-weight: bolder;
}
.markdown-body h1 {
font-size: 2em;
margin: 0.67em 0;
}
.markdown-body img {
border-style: none;
}
.markdown-body code,
.markdown-body kbd,
.markdown-body pre {
font-family: monospace, monospace;
font-size: 1em;
}
.markdown-body hr {
box-sizing: content-box;
height: 0;
overflow: visible;
}
.markdown-body input {
font: inherit;
margin: 0;
}
.markdown-body input {
overflow: visible;
}
.markdown-body [type="checkbox"] {
box-sizing: border-box;
padding: 0;
}
.markdown-body * {
box-sizing: border-box;
}
.markdown-body input {
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
.markdown-body a {
color: #0366d6;
text-decoration: none;
}
.markdown-body a:hover {
text-decoration: underline;
}
.markdown-body strong {
font-weight: 600;
}
.markdown-body hr {
height: 0;
margin: 15px 0;
overflow: hidden;
background: transparent;
border: 0;
border-bottom: 1px solid #dfe2e5;
}
.markdown-body hr::before {
display: table;
content: "";
}
.markdown-body hr::after {
display: table;
clear: both;
content: "";
}
.markdown-body table {
border-spacing: 0;
border-collapse: collapse;
}
.markdown-body td,
.markdown-body th {
padding: 0;
}
.markdown-body h1,
.markdown-body h2,
.markdown-body h3,
.markdown-body h4,
.markdown-body h5,
.markdown-body h6 {
margin-top: 0;
margin-bottom: 0;
}
.markdown-body h1 {
font-size: 32px;
font-weight: 600;
}
.markdown-body h2 {
font-size: 24px;
font-weight: 600;
}
.markdown-body h3 {
font-size: 20px;
font-weight: 600;
}
.markdown-body h4 {
font-size: 16px;
font-weight: 600;
}
.markdown-body h5 {
font-size: 14px;
font-weight: 600;
}
.markdown-body h6 {
font-size: 12px;
font-weight: 600;
}
.markdown-body p {
margin-top: 0;
margin-bottom: 10px;
}
.markdown-body blockquote {
margin: 0;
}
.markdown-body ul,
.markdown-body ol {
padding-left: 0;
margin-top: 0;
margin-bottom: 0;
}
.markdown-body ol ol,
.markdown-body ul ol {
list-style-type: lower-roman;
}
.markdown-body ul ul ol,
.markdown-body ul ol ol,
.markdown-body ol ul ol,
.markdown-body ol ol ol {
list-style-type: lower-alpha;
}
.markdown-body dd {
margin-left: 0;
}
.markdown-body code {
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
font-size: 12px;
}
.markdown-body pre {
margin-top: 0;
margin-bottom: 0;
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
font-size: 12px;
}
.markdown-body .octicon {
vertical-align: text-bottom;
}
.markdown-body .pl-0 {
padding-left: 0 !important;
}
.markdown-body .pl-1 {
padding-left: 4px !important;
}
.markdown-body .pl-2 {
padding-left: 8px !important;
}
.markdown-body .pl-3 {
padding-left: 16px !important;
}
.markdown-body .pl-4 {
padding-left: 24px !important;
}
.markdown-body .pl-5 {
padding-left: 32px !important;
}
.markdown-body .pl-6 {
padding-left: 40px !important;
}
.markdown-body::before {
display: table;
content: "";
}
.markdown-body::after {
display: table;
clear: both;
content: "";
}
.markdown-body>*:first-child {
margin-top: 0 !important;
}
.markdown-body>*:last-child {
margin-bottom: 0 !important;
}
.markdown-body a:not([href]) {
color: inherit;
text-decoration: none;
}
.markdown-body .anchor {
float: left;
padding-right: 4px;
margin-left: -20px;
line-height: 1;
}
.markdown-body .anchor:focus {
outline: none;
}
.markdown-body p,
.markdown-body blockquote,
.markdown-body ul,
.markdown-body ol,
.markdown-body dl,
.markdown-body table,
.markdown-body pre {
margin-top: 0;
margin-bottom: 16px;
}
.markdown-body hr {
height: 0.25em;
padding: 0;
margin: 24px 0;
background-color: #e1e4e8;
border: 0;
}
.markdown-body blockquote {
padding: 0 1em;
color: #6a737d;
border-left: 0.25em solid #dfe2e5;
}
.markdown-body blockquote>:first-child {
margin-top: 0;
}
.markdown-body blockquote>:last-child {
margin-bottom: 0;
}
.markdown-body kbd {
display: inline-block;
padding: 3px 5px;
font-size: 11px;
line-height: 10px;
color: #444d56;
vertical-align: middle;
background-color: #fafbfc;
border: solid 1px #c6cbd1;
border-bottom-color: #959da5;
border-radius: 3px;
box-shadow: inset 0 -1px 0 #959da5;
}
.markdown-body h1,
.markdown-body h2,
.markdown-body h3,
.markdown-body h4,
.markdown-body h5,
.markdown-body h6 {
margin-top: 24px;
margin-bottom: 16px;
font-weight: 600;
line-height: 1.25;
}
.markdown-body h1 .octicon-link,
.markdown-body h2 .octicon-link,
.markdown-body h3 .octicon-link,
.markdown-body h4 .octicon-link,
.markdown-body h5 .octicon-link,
.markdown-body h6 .octicon-link {
color: #1b1f23;
vertical-align: middle;
visibility: hidden;
}
.markdown-body h1:hover .anchor,
.markdown-body h2:hover .anchor,
.markdown-body h3:hover .anchor,
.markdown-body h4:hover .anchor,
.markdown-body h5:hover .anchor,
.markdown-body h6:hover .anchor {
text-decoration: none;
}
.markdown-body h1:hover .anchor .octicon-link,
.markdown-body h2:hover .anchor .octicon-link,
.markdown-body h3:hover .anchor .octicon-link,
.markdown-body h4:hover .anchor .octicon-link,
.markdown-body h5:hover .anchor .octicon-link,
.markdown-body h6:hover .anchor .octicon-link {
visibility: visible;
}
.markdown-body h1 {
padding-bottom: 0.3em;
font-size: 2em;
border-bottom: 1px solid #eaecef;
}
.markdown-body h2 {
padding-bottom: 0.3em;
font-size: 1.5em;
border-bottom: 1px solid #eaecef;
}
.markdown-body h3 {
font-size: 1.25em;
}
.markdown-body h4 {
font-size: 1em;
}
.markdown-body h5 {
font-size: 0.875em;
}
.markdown-body h6 {
font-size: 0.85em;
color: #6a737d;
}
.markdown-body ul,
.markdown-body ol {
padding-left: 2em;
}
.markdown-body ul ul,
.markdown-body ul ol,
.markdown-body ol ol,
.markdown-body ol ul {
margin-top: 0;
margin-bottom: 0;
}
.markdown-body li {
word-wrap: break-all;
}
.markdown-body li>p {
margin-top: 16px;
}
.markdown-body li+li {
margin-top: 0.25em;
}
.markdown-body dl {
padding: 0;
}
.markdown-body dl dt {
padding: 0;
margin-top: 16px;
font-size: 1em;
font-style: italic;
font-weight: 600;
}
.markdown-body dl dd {
padding: 0 16px;
margin-bottom: 16px;
}
.markdown-body table {
display: block;
width: 100%;
overflow: auto;
}
.markdown-body table th {
font-weight: 600;
}
.markdown-body table th,
.markdown-body table td {
padding: 6px 13px;
border: 1px solid #dfe2e5;
}
.markdown-body table tr {
background-color: #fff;
border-top: 1px solid #c6cbd1;
}
.markdown-body table tr:nth-child(2n) {
background-color: #f6f8fa;
}
.markdown-body img {
max-width: 100%;
box-sizing: content-box;
background-color: #fff;
}
.markdown-body img[align=right] {
padding-left: 20px;
}
.markdown-body img[align=left] {
padding-right: 20px;
}
.markdown-body code {
padding: 0.2em 0.4em;
margin: 0;
font-size: 85%;
background-color: rgba(27,31,35,0.05);
border-radius: 3px;
}
.markdown-body pre {
word-wrap: normal;
}
.markdown-body pre>code {
padding: 0;
margin: 0;
font-size: 100%;
word-break: normal;
white-space: pre;
background: transparent;
border: 0;
}
.markdown-body .highlight {
margin-bottom: 16px;
}
.markdown-body .highlight pre {
margin-bottom: 0;
word-break: normal;
}
.markdown-body .highlight pre,
.markdown-body pre {
padding: 16px;
overflow: auto;
font-size: 85%;
line-height: 1.45;
background-color: #f6f8fa;
border-radius: 3px;
}
.markdown-body pre code {
display: inline;
max-width: auto;
padding: 0;
margin: 0;
overflow: visible;
line-height: inherit;
word-wrap: normal;
background-color: transparent;
border: 0;
}
.markdown-body .full-commit .btn-outline:not(:disabled):hover {
color: #005cc5;
border-color: #005cc5;
}
.markdown-body kbd {
display: inline-block;
padding: 3px 5px;
font: 11px "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
line-height: 10px;
color: #444d56;
vertical-align: middle;
background-color: #fafbfc;
border: solid 1px #d1d5da;
border-bottom-color: #c6cbd1;
border-radius: 3px;
box-shadow: inset 0 -1px 0 #c6cbd1;
}
.markdown-body :checked+.radio-label {
position: relative;
z-index: 1;
border-color: #0366d6;
}
.markdown-body .task-list-item {
list-style-type: none;
}
.markdown-body .task-list-item+.task-list-item {
margin-top: 3px;
}
.markdown-body .task-list-item input {
margin: 0 0.2em 0.25em -1.6em;
vertical-align: middle;
}
.markdown-body hr {
border-bottom-color: #eee;
}
-2
View File
@@ -346,7 +346,6 @@ ul.messenger-theme-air .messenger-message .messenger-actions a {
border-radius: 4px;
text-decoration: none;
display: inline-block;
padding: 10px;
color: #888888;
margin-right: 10px;
padding: 3px 10px 5px;
@@ -452,7 +451,6 @@ ul.messenger-theme-air .messenger-spinner {
left: 12px;
top: 50%;
margin-top: -13px;
z-index: 999;
height: 24px;
width: 24px;
z-index: 10;
-46
View File
@@ -1,46 +0,0 @@
.strengthify-wrapper > * {
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=0);
opacity: 0;
-webkit-transition:all .5s ease-in-out;
-moz-transition:all .5s ease-in-out;
transition:all .5s ease-in-out;
}
.strengthify-wrapper {
position: relative;
}
.strengthify-bg, .strengthify-container, .strengthify-wrapper, .strengthify-separator {
height: 8px;
}
.strengthify-bg, .strengthify-container {
display: block;
position: absolute;
width: 100%;
}
.strengthify-bg {
background-color: #eeeeee;
}
.strengthify-separator {
display: inline-block;
position: absolute;
background-color: #ffffff;
width: 2px;
z-index: 10;
}
.password-bad {
background-color: $cachet-red;
}
.password-medium {
background-color: $cachet-yellow;
}
.password-good {
background-color: $cachet-green;
}
+162 -162
View File
@@ -13,134 +13,134 @@ return [
// Setup form fields
'setup' => [
'email' => 'Email',
'username' => 'Username',
'password' => 'Password',
'site_name' => 'Site Name',
'site_domain' => 'Site Domain',
'site_timezone' => 'Select your timezone',
'site_locale' => 'Select your language',
'enable_google2fa' => 'Enable Google Two Factor Authentication',
'cache_driver' => 'Cache Driver',
'queue_driver' => 'Queue Driver',
'session_driver' => 'Session Driver',
'mail_driver' => 'Mail Driver',
'mail_host' => 'Mail Host',
'mail_address' => 'Mail From Address',
'mail_username' => 'Mail Username',
'mail_password' => 'Mail Password',
'email' => 'E-mail',
'username' => 'Uživatelské jméno',
'password' => 'Heslo',
'site_name' => 'Název webu',
'site_domain' => 'Doména webu',
'site_timezone' => 'Vyberte vaše časové pásmo',
'site_locale' => 'Vyberte svůj jazyk',
'enable_google2fa' => 'Povolit dvoufaktorové ověřování Google',
'cache_driver' => 'Ovladač cache',
'queue_driver' => 'Řadič fronty',
'session_driver' => 'Ovladač sezení',
'mail_driver' => 'Ovladač pro e-mail',
'mail_host' => 'Host pro Mail',
'mail_address' => 'Adresa Mailu',
'mail_username' => 'Uživatelské jméno pro Mail účet',
'mail_password' => 'Heslo pro Mail účet',
],
// Login form fields
'login' => [
'login' => 'Username or Email',
'email' => 'Email',
'password' => 'Password',
'2fauth' => 'Authentication Code',
'invalid' => 'Invalid username or password',
'invalid-token' => 'Invalid token',
'cookies' => 'You must enable cookies to login.',
'rate-limit' => 'Rate limit exceeded.',
'remember_me' => 'Remember me',
'login' => 'Uživatelské jméno nebo e-mail',
'email' => 'E-mail',
'password' => 'Heslo',
'2fauth' => 'Ověřovací kód',
'invalid' => 'Nesprávné uživatelské jméno nebo heslo',
'invalid-token' => 'Neplatný token',
'cookies' => 'Pro přihlášení je třeba povolit soubory cookie.',
'rate-limit' => 'Překročen limit.',
'remember_me' => 'Zůstat přihlášený',
],
// Incidents form fields
'incidents' => [
'name' => 'Name',
'status' => 'Status',
'component' => 'Component',
'component_status' => 'Component Status',
'message' => 'Message',
'message-help' => 'You may also use Markdown.',
'occurred_at' => 'When did this incident occur?',
'notify_subscribers' => 'Notify subscribers?',
'notify_disabled' => 'Due to scheduled maintenance, notifications about this incident or its components will be suppressed.',
'visibility' => 'Incident Visibility',
'stick_status' => 'Stick Incident',
'stickied' => 'Stickied',
'not_stickied' => 'Not Stickied',
'public' => 'Viewable by public',
'logged_in_only' => 'Only visible to logged in users',
'name' => 'Jméno',
'status' => 'Stav',
'component' => 'Komponenta',
'component_status' => 'Stavy služeb',
'message' => 'Zpráva',
'message-help' => 'Můžete také použít Markdown.',
'occurred_at' => 'Kdy došlo k incidentu?',
'notify_subscribers' => 'Oznámit odběratelům?',
'notify_disabled' => 'Z důvodu plánované údržby budou oznámení o tomto incidentu nebo jeho součástech potlačena.',
'visibility' => 'Viditelnost incidentu',
'stick_status' => 'Připnout událost',
'stickied' => 'Připnuté',
'not_stickied' => 'Nepřipnuté',
'public' => 'Viditelné veřejnosti',
'logged_in_only' => 'Viditelné pouze pro přihlášené uživatele',
'templates' => [
'name' => 'Name',
'template' => 'Template',
'twig' => 'Incident Templates can make use of the <a href="http://twig.sensiolabs.org/" target="_blank">Twig</a> templating language.',
'name' => 'Jméno',
'template' => 'Šablona',
'twig' => 'Šablony pro incidenty mohou používat šablonovací jazyk <a href="http://twig.sensiolabs.org/" target="_blank">Twing</a>.',
],
],
'schedules' => [
'name' => 'Name',
'status' => 'Status',
'message' => 'Message',
'message-help' => 'You may also use Markdown.',
'scheduled_at' => 'When is this maintenance scheduled for?',
'completed_at' => 'When did this maintenance complete?',
'name' => 'Jméno',
'status' => 'Stav',
'message' => 'Zpráva',
'message-help' => 'Můžete také použít Markdown.',
'scheduled_at' => 'Na kdy je naplánovaná údržba?',
'completed_at' => 'Kdy bude údržba hotová?',
'templates' => [
'name' => 'Name',
'template' => 'Template',
'twig' => 'Incident Templates can make use of the <a href="http://twig.sensiolabs.org/" target="_blank">Twig</a> templating language.',
'name' => 'Jméno',
'template' => 'Šablona',
'twig' => 'Šablony pro incidenty mohou používat šablonovací jazyk <a href="http://twig.sensiolabs.org/" target="_blank">Twing</a>.',
],
],
// Components form fields
'components' => [
'name' => 'Name',
'status' => 'Status',
'group' => 'Group',
'description' => 'Description',
'link' => 'Link',
'tags' => 'Tags',
'tags-help' => 'Comma separated.',
'enabled' => 'Component enabled?',
'name' => 'Jméno',
'status' => 'Stav',
'group' => 'Skupina',
'description' => 'Popis',
'link' => 'Odkaz',
'tags' => 'Štítky',
'tags-help' => 'Oddělené čárkou.',
'enabled' => 'Je služba povolena?',
'groups' => [
'name' => 'Name',
'collapsing' => 'Expand/Collapse options',
'visible' => 'Always expanded',
'collapsed' => 'Collapse the group by default',
'collapsed_incident' => 'Collapse the group, but expand if there are issues',
'visibility' => 'Visibility',
'visibility_public' => 'Visible to public',
'visibility_authenticated' => 'Visible only to logged in users',
'name' => 'Jméno',
'collapsing' => 'Rozbalit nebo sbalit možnosti',
'visible' => 'Vždy rozbalené',
'collapsed' => 'Sbalit skupinu ve výchozím nastavení',
'collapsed_incident' => 'Sbalit skupinu, ale rozšířit, pokud existují problémy',
'visibility' => 'Viditelnost',
'visibility_public' => 'Viditelné pro veřejnost',
'visibility_authenticated' => 'Viditelné pouze pro přihlášené uživatele',
],
],
// Action form fields
'actions' => [
'name' => 'Name',
'description' => 'Description',
'start_at' => 'Schedule start time',
'timezone' => 'Timezone',
'schedule_frequency' => 'Schedule frequency (in seconds)',
'completion_latency' => 'Completion latency (in seconds)',
'group' => 'Group',
'active' => 'Active?',
'name' => 'Jméno',
'description' => 'Popis',
'start_at' => 'Naplánovat čas spuštění',
'timezone' => 'Časová zóna',
'schedule_frequency' => 'Naplánovat frekvenci (ve vteřinách)',
'completion_latency' => 'Prodleva dokončení (ve vteřinách)',
'group' => 'Skupina',
'active' => 'Aktiv?',
'groups' => [
'name' => 'Group Name',
'name' => 'Název skupiny',
],
],
// Metric form fields
'metrics' => [
'name' => 'Name',
'suffix' => 'Suffix',
'description' => 'Description',
'description-help' => 'You may also use Markdown.',
'display-chart' => 'Display chart on status page?',
'default-value' => 'Default value',
'calc_type' => 'Calculation of metrics',
'type_sum' => 'Sum',
'type_avg' => 'Average',
'places' => 'Decimal places',
'default_view' => 'Default view',
'threshold' => 'How many minutes of threshold between metric points?',
'visibility' => 'Visibility',
'visibility_authenticated' => 'Visible to authenticated users',
'visibility_public' => 'Visible to everybody',
'visibility_hidden' => 'Always hidden',
'name' => 'Jméno',
'suffix' => 'Přípona',
'description' => 'Popis',
'description-help' => 'Můžete také použít Markdown.',
'display-chart' => 'Zobrazovat graf na stavové stránce?',
'default-value' => 'Výchozí hodnota',
'calc_type' => 'Výpočet metrik',
'type_sum' => 'Celkem',
'type_avg' => 'Průměr',
'places' => 'Počet desetinných míst',
'default_view' => 'Výchozí zobrazení',
'threshold' => 'Jak často se mají snímat metrické body?',
'visibility' => 'Viditelnost',
'visibility_authenticated' => 'Viditelné přihlášeným uživatelům',
'visibility_public' => 'Viditelný všem',
'visibility_hidden' => 'Vždy skrýt',
'points' => [
'value' => 'Value',
'value' => 'Hodnota',
],
],
@@ -148,101 +148,101 @@ return [
'settings' => [
// Application setup
'app-setup' => [
'site-name' => 'Site Name',
'site-url' => 'Site URL',
'display-graphs' => 'Display graphs on status page?',
'about-this-page' => 'About this page',
'days-of-incidents' => 'How many days of incidents to show?',
'time_before_refresh' => 'Status page refresh rate (in seconds)',
'major_outage_rate' => 'Major outage threshold (in %)',
'banner' => 'Banner Image',
'banner-help' => "It's recommended that you upload files no bigger than 930px wide",
'subscribers' => 'Allow people to signup to email notifications?',
'suppress_notifications_in_maintenance' => 'Suppress notifications when incident occurs during maintenance period?',
'skip_subscriber_verification' => 'Skip verifying of users? (Be warned, you could be spammed)',
'automatic_localization' => 'Automatically localise your status page to your visitor\'s language?',
'enable_external_dependencies' => 'Enable Third Party Dependencies (Google Fonts, Trackers, etc...)',
'show_timezone' => 'Show the timezone the status page is running in',
'only_disrupted_days' => 'Only show days containing incidents in the timeline?',
'site-name' => 'Název webu',
'site-url' => 'URL adresa webu',
'display-graphs' => 'Zobrazit grafy na stavové stránce?',
'about-this-page' => 'O této stránce',
'days-of-incidents' => 'Kolik dní incidentů zobrazovat?',
'time_before_refresh' => 'Obnovovací frekvence status stránky (v sekundách)',
'major_outage_rate' => 'Hlavní doba výpadků (v %)',
'banner' => 'Obrázek banneru',
'banner-help' => 'Doručuje se nenahrávat soubory větší než 930 pixelů na šířku',
'subscribers' => 'Umožnit lidem, aby se přihlašovali k odběru e-mailových upozornění?',
'suppress_notifications_in_maintenance' => 'Potlačit oznámení dojde-li k události během během času údržby?',
'skip_subscriber_verification' => 'Přestat ověřovat uživatele? (Pozor na spammery)',
'automatic_localization' => 'Automaticky lokalizovat stránku do jazyka návštěvníka?',
'enable_external_dependencies' => 'Povolit závislosti třetích stran (Google písma, Trackery, atd...)',
'show_timezone' => 'Zobrazit časové pásmo, ve které je zobrazena stavová stránka',
'only_disrupted_days' => 'Zobrazit na časové ose pouze dny, kdy došlo k incidentu?',
],
'analytics' => [
'analytics_google' => 'Google Analytics code',
'analytics_gosquared' => 'GoSquared Analytics code',
'analytics_piwik_url' => 'URL of your Piwik instance (without http(s)://)',
'analytics_piwik_siteid' => 'Piwik\'s site id',
'analytics_google' => 'Kód pro Google Analytics',
'analytics_gosquared' => 'Kód pro GoSquared Analytics',
'analytics_piwik_url' => 'URL tvojí instance Piwik (bez http(s)://)',
'analytics_piwik_siteid' => 'Id webu Piwik',
],
'localization' => [
'site-timezone' => 'Site timezone',
'site-locale' => 'Site language',
'date-format' => 'Date format',
'incident-date-format' => 'Incident timestamp format',
'site-timezone' => 'Časové pásmo webu',
'site-locale' => 'Jazyk webu',
'date-format' => 'Formát datumu',
'incident-date-format' => 'Formát času pro incident',
],
'security' => [
'allowed-domains' => 'Allowed domains',
'allowed-domains-help' => 'Comma separated. The domain set above is automatically allowed by default.',
'always-authenticate' => 'Always authenticate',
'always-authenticate-help' => 'Require login to view any Cachet page',
'allowed-domains' => 'Povolené domény',
'allowed-domains-help' => 'Oddělené čárkami. Výše uvedené domény jsou ve výchozím nastavení automaticky povoleny.',
'always-authenticate' => 'Vždy ověřovat',
'always-authenticate-help' => 'Požadovat přihlášení k zobrazení jakékoli Cachet stránky',
],
'stylesheet' => [
'custom-css' => 'Custom Stylesheet',
'custom-css' => 'Vlastní šablona stylů',
],
'theme' => [
'background-color' => 'Background color',
'background-fills' => 'Background fills (components, incidents, footer)',
'banner-background-color' => 'Banner background color',
'banner-padding' => 'Banner padding',
'fullwidth-banner' => 'Enable full width banner?',
'text-color' => 'Text color',
'dashboard-login' => 'Show dashboard button in the footer?',
'reds' => 'Red (used for errors)',
'blues' => 'Blue (used for information)',
'greens' => 'Green (used for success)',
'yellows' => 'Yellow (used for alerts)',
'oranges' => 'Orange (used for notices)',
'metrics' => 'Metrics fill',
'links' => 'Links',
'background-color' => 'Barva pozadí',
'background-fills' => 'Pozadí výplně (komponenty, incidenty, zápatí)',
'banner-background-color' => 'Barva pozadí banneru',
'banner-padding' => 'Odsazení banneru',
'fullwidth-banner' => 'Povolit banner přes celou obrazovku?',
'text-color' => 'Barva textu',
'dashboard-login' => 'Zobrazit tlačítko Řídící panel v zápatí?',
'reds' => 'Červená (používané pro chyby)',
'blues' => 'Modrá (používané pro informace)',
'greens' => 'Zelená (používá se pro vyřešení problémů)',
'yellows' => 'Žlutá (používá se pro upozornění)',
'oranges' => 'Oranžová (slouží k oznámení)',
'metrics' => 'Vyplnění metrik',
'links' => 'Odkazy',
],
],
'user' => [
'username' => 'Username',
'email' => 'Email',
'password' => 'Password',
'username' => 'Uživatelské jméno',
'email' => 'E-mail',
'password' => 'Heslo',
'api-token' => 'API Token',
'api-token-help' => 'Regenerating your API token will prevent existing applications from accessing Cachet.',
'gravatar' => 'Change your profile picture at Gravatar.',
'user_level' => 'User Level',
'api-token-help' => 'egenerování vašeho API tokenu zabrání současným aplikacím přistupovat ke Cachet.',
'gravatar' => 'Profilový obrázek si změn na Gravatar.',
'user_level' => 'Úroveň uživatele',
'levels' => [
'admin' => 'Admin',
'user' => 'User',
'admin' => 'Správce',
'user' => 'Uživatel',
],
'2fa' => [
'help' => 'Enabling two factor authentication increases security of your account. You will need to download <a href="https://support.google.com/accounts/answer/1066447?hl=en">Google Authenticator</a> or a similar app on to your mobile device. When you login you will be asked to provide a token generated by the app.',
'help' => 'Zapnutí dvoufaktorového ověřování zvýší zabezpečení vašeho účtu. Budete muset stáhnout <a href="https://support.google.com/accounts/answer/1066447?hl=en">Google Authenticator</a> nebo podobnou aplikaci pro mobilní zařízení. Po přihlášení budete vyzváni k zadání tokenu vygenerovaného aplikací.',
],
'team' => [
'description' => 'Invite your team members by entering their email addresses here.',
'email' => 'Your Team Members Email Address',
'description' => 'Pozvi uživatele do týmu zadáním emailové adresy.',
'email' => 'Email #:id',
],
],
'general' => [
'timezone' => 'Select Timezone',
'timezone' => 'Vybrat časové pásmo',
],
// Buttons
'add' => 'Add',
'save' => 'Save',
'update' => 'Update',
'create' => 'Create',
'edit' => 'Edit',
'delete' => 'Delete',
'submit' => 'Submit',
'cancel' => 'Cancel',
'remove' => 'Remove',
'invite' => 'Invite',
'signup' => 'Sign Up',
'manage_updates' => 'Manage Updates',
'add' => 'Přidat',
'save' => 'Uložit',
'update' => 'Aktualizovat',
'create' => 'Vytvořit',
'edit' => 'Upravit',
'delete' => 'Smazat',
'submit' => 'Potvrdit',
'cancel' => 'Zrušit',
'remove' => 'Smazat',
'invite' => 'Pozvat',
'signup' => 'Registrovat se',
'manage_updates' => 'Správa aktualizací',
// Other
'optional' => '* Optional',
'optional' => '* Volitelné',
];
+32 -32
View File
@@ -22,72 +22,72 @@ return [
|
*/
'accepted' => 'The :attribute must be accepted.',
'active_url' => 'The :attribute is not a valid URL.',
'after' => 'The :attribute must be a date after :date.',
'alpha' => 'The :attribute may only contain letters.',
'alpha_dash' => 'The :attribute may only contain letters, numbers, and dashes.',
'alpha_num' => 'The :attribute may only contain letters and numbers.',
'array' => 'The :attribute must be an array.',
'before' => 'The :attribute must be a date before :date.',
'accepted' => 'Je potřeba potvrdit :attribute.',
'active_url' => ':attribute není platná adresa URL.',
'after' => ':attribute musí být datum po :date.',
'alpha' => ':attribute může obsahovat pouze písmena.',
'alpha_dash' => ':attribute může obsahovat pouze písmena, čísla a pomlčky.',
'alpha_num' => ':attribute může obsahovat pouze písmena a čísla.',
'array' => ':attribute musí být textové pole.',
'before' => ':attribute musí být datum před :date.',
'between' => [
'numeric' => 'The :attribute must be between :min and :max.',
'file' => 'The :attribute must be between :min and :max kilobytes.',
'numeric' => ':attribute musí mít hodnou mezi :min a :max.',
'file' => ':attribute musí mít velikost v rozmezí :min až :max kilobytů.',
'string' => 'The :attribute must be between :min and :max characters.',
'array' => 'The :attribute must have between :min and :max items.',
'array' => ':attribute musí mít mezi :min a :max položkami.',
],
'boolean' => 'The :attribute field must be true or false.',
'confirmed' => 'The :attribute confirmation does not match.',
'date' => 'The :attribute is not a valid date.',
'date_format' => 'The :attribute does not match the format :format.',
'boolean' => ':attribute musí mít hodnotu pravda nebo nepravda.',
'confirmed' => 'Potvrzení :attribute se neshoduje.',
'date' => ':attribute není platné datum.',
'date_format' => ':attribute se neshoduje se správným formátem :format.',
'different' => 'The :attribute and :other must be different.',
'digits' => 'The :attribute must be :digits digits.',
'digits_between' => 'The :attribute must be between :min and :max digits.',
'email' => 'The :attribute must be a valid email address.',
'exists' => 'The selected :attribute is invalid.',
'distinct' => 'The :attribute field has a duplicate value.',
'distinct' => ':attribute má duplicitní hodnotu.',
'filled' => 'The :attribute field is required.',
'image' => 'The :attribute must be an image.',
'image' => ':attribute musí být obrázek.',
'in' => 'The selected :attribute is invalid.',
'in_array' => 'The :attribute field does not exist in :other.',
'in_array' => ':attribute není v :other.',
'integer' => 'The :attribute must be an integer.',
'ip' => 'The :attribute must be a valid IP address.',
'json' => 'The :attribute must be a valid JSON string.',
'json' => ': attribute musí být ve formátu JSON.',
'max' => [
'numeric' => 'The :attribute may not be greater than :max.',
'file' => 'The :attribute may not be greater than :max kilobytes.',
'string' => 'The :attribute may not be greater than :max characters.',
'array' => 'The :attribute may not have more than :max items.',
'array' => 'Atribut nesmí mít více než :max položek.',
],
'mimes' => 'The :attribute must be a file of type: :values.',
'min' => [
'numeric' => 'The :attribute must be at least :min.',
'file' => 'The :attribute must be at least :min kilobytes.',
'file' => 'Atribut musí mít alespoň :min kB.',
'string' => 'The :attribute must be at least :min characters.',
'array' => 'The :attribute must have at least :min items.',
],
'not_in' => 'The selected :attribute is invalid.',
'numeric' => 'The :attribute must be a number.',
'present' => 'The :attribute field must be present.',
'regex' => 'The :attribute format is invalid.',
'present' => 'Pole :attribute je vyžadováno.',
'regex' => 'Formát :attribute je neplatný.',
'required' => 'The :attribute field is required.',
'required_if' => 'The :attribute field is required when :other is :value.',
'required_unless' => 'The :attribute field is required unless :other is in :values.',
'required_with' => 'The :attribute field is required when :values is present.',
'required_with_all' => 'The :attribute field is required when :values is present.',
'required_unless' => 'Pole :attribute je požadováno, pokud :other není v :value.',
'required_with' => 'Pole :attribute je požadováno, když je zadané :values.',
'required_with_all' => 'Pole :attribute je požadováno, když je zadané :values.',
'required_without' => 'The :attribute field is required when :values is not present.',
'required_without_all' => 'The :attribute field is required when none of :values are present.',
'same' => 'The :attribute and :other must match.',
'size' => [
'numeric' => 'The :attribute must be :size.',
'file' => 'The :attribute must be :size kilobytes.',
'string' => 'The :attribute must be :size characters.',
'file' => 'Atribut musí mít :size kB.',
'string' => 'Atribut musí mít :size znaků.',
'array' => 'The :attribute must contain :size items.',
],
'string' => 'The :attribute must be a string.',
'timezone' => 'The :attribute must be a valid zone.',
'unique' => 'The :attribute has already been taken.',
'url' => 'The :attribute format is invalid.',
'timezone' => ':attribute musí být platná zóna.',
'unique' => ':attribute byl už použit.',
'url' => 'Formát :attribute je neplatný.',
/*
|--------------------------------------------------------------------------
@@ -102,7 +102,7 @@ return [
'custom' => [
'attribute-name' => [
'rule-name' => 'custom-message',
'rule-name' => 'vlastní zpráva',
],
],
+12 -12
View File
@@ -23,8 +23,8 @@ return [
'group' => [
'other' => 'Andere Komponenten',
],
'select_all' => 'Select All',
'deselect_all' => 'Deselect All',
'select_all' => 'Alles auswählen',
'deselect_all' => 'Alles abwählen',
],
// Incidents
@@ -56,8 +56,8 @@ return [
// Service Status
'service' => [
'good' => '[0,1]System funktioniert|[2,*]Alle Systeme funktionieren',
'bad' => '[0,1]The system is experiencing issues|[2,*]Some systems are experiencing issues',
'major' => '[0,1]The system is experiencing major issues|[2,*]Some systems are experiencing major issues',
'bad' => '[0,1] Das System hat momentan Probleme|[2,*] Mehrere Systeme haben momentan Probleme',
'major' => '[0,1] Das System hat ein schwerwiegendes Problem|[2,*] Mehrere Systeme haben ein schwerwiegendes Problem',
],
'api' => [
@@ -77,17 +77,17 @@ return [
// Subscriber
'subscriber' => [
'subscribe' => 'Subscribe to status changes and incident updates',
'unsubscribe' => 'Unsubscribe',
'subscribe' => 'Abonniere Status- und Vorfalländerungen',
'unsubscribe' => 'Abmelden',
'button' => 'Abonnieren',
'manage_subscription' => 'Manage subscription',
'manage_subscription' => 'Abonnements verwalten',
'manage' => [
'notifications' => 'Benachrichtigungen',
'notifications_for' => 'Manage notifications for',
'notifications_for' => 'Verwalten von Benachrichtigungen für',
'no_subscriptions' => 'Du hast im Augenblick alle Updates abonniert.',
'update_subscription' => 'Update Subscription',
'update_subscription' => 'Update-Abonnement',
'my_subscriptions' => 'Du hast im Augenblick folgende Updates abonniert.',
'manage_at_link' => 'Manage your subscriptions at :link',
'manage_at_link' => 'Verwalte deine Abonnements unter :link',
],
'email' => [
'subscribe' => 'Aktualisierungen per E-Mail abonnieren.',
@@ -128,8 +128,8 @@ return [
'meta' => [
'description' => [
'incident' => 'Details und Aktualisierung über den :name Vorfall, die am :date aufgetreten sind',
'schedule' => 'Details about the scheduled maintenance period :name starting :startDate',
'subscribe' => 'Subscribe to :app in order to receive updates of incidents and scheduled maintenance periods',
'schedule' => 'Details zu den geplanten Wartungszeitraum :name beginnend ab :startDate',
'subscribe' => 'Abonniere :app um Updates von Vorfällen und geplanten Wartungszeiten zu erhalten',
'overview' => 'Bleiben sie auf dem Laufenden mit den neuesten Service-Updates von :app.',
],
],
+23 -23
View File
@@ -16,26 +16,26 @@ return [
// Incidents
'incidents' => [
'title' => 'Incidents & Maintenance',
'title' => 'Vorfälle & Wartungsarbeiten',
'incidents' => 'Ereignisse',
'logged' => '{0}There are no incidents, good work.|[1]You have logged one incident.|[2,*]You have reported <strong>:count</strong> incidents.',
'logged' => '{0}Es gibt keine Ereignisse, gute Arbeit.|[1]Du hast ein Ereignis gemeldet.|[2,*]Du hast <strong>:count</strong> Ereignisse gemeldet.',
'incident-create-template' => 'Vorlage erstellen',
'incident-templates' => 'Ereignis Vorlagen',
'updates' => [
'title' => 'Incident updates for :incident',
'count' => '{0}Zero Updates|[1]One Update|[2]Two Updates|[3,*]Several Updates',
'title' => 'Vorfall Updates für :incident',
'count' => '{0}Keine Updates|[1]Ein Update|[2]Zwei Updates|[3,*]Mehrere Updates',
'add' => [
'title' => 'Vorfall-Update erstellen',
'success' => 'Your new incident update has been created.',
'failure' => 'Something went wrong with the incident update.',
'success' => 'Dein Vorfall Update wurde erstellt.',
'failure' => 'Etwas ist mit dem Vorfall Update schief gelaufen.',
],
'edit' => [
'title' => 'Edit incident update',
'success' => 'The incident update has been updated.',
'failure' => 'Something went wrong updating the incident update',
'title' => 'Vorfall Update bearbeiten',
'success' => 'Vorfall wurde aktualisiert.',
'failure' => 'Etwas ist mit dem Aktualisieren des Vorfall Updates schief gelaufen',
],
],
'reported_by' => 'Reported by :user',
'reported_by' => 'Gemeldet von :user',
'add' => [
'title' => 'Ereignis hinzufügen',
'success' => 'Ereignis hinzugefügt.',
@@ -56,7 +56,7 @@ return [
'title' => 'Ereignis Vorlagen',
'add' => [
'title' => 'Ereignisvorlage erstellen',
'message' => 'Create your first incident template.',
'message' => 'Du solltest eine Ereignis-Vorlage hinzufügen.',
'success' => 'Deine neue Ereignis-Vorlage wurde angelegt.',
'failure' => 'Etwas ist mit der Ereignis-Vorlage schief gelaufen.',
],
@@ -74,22 +74,22 @@ return [
// Incident Maintenance
'schedule' => [
'schedule' => 'Maintenance',
'logged' => '{0}There has been no Maintenance, good work.|[1]You have logged one schedule.|[2,*]You have reported <strong>:count</strong> schedules.',
'schedule' => 'Wartungsarbeiten',
'logged' => '{0}Es gibt keine geplanten Wartungen, gute Arbeit.|[1]Du hast einen Eintrag erstellt.|[2,*]Du hast <strong>:count</strong> Einträge erstellt.',
'scheduled_at' => 'Geplant am :timestamp',
'add' => [
'title' => 'Add Maintenance',
'success' => 'Maintenance added.',
'failure' => 'Something went wrong adding the Maintenance, please try again.',
'title' => 'Wartungsarbeiten hinzufügen',
'success' => 'Wartungsarbeiten hinzugefügt.',
'failure' => 'Etwas lief schief mit dem Hinzufügen des Zeitplans. Bitte versuchen Sie es erneut.',
],
'edit' => [
'title' => 'Edit Maintenance',
'success' => 'Maintenance has been updated!',
'failure' => 'Something went wrong editing the Maintenance, please try again.',
'title' => 'Planmäßige Wartung bearbeiten',
'success' => 'Wartungsarbeiten wurden aktualisiert!',
'failure' => 'Etwas lief schief mit dem Editieren des Zeitplans. Bitte versuchen Sie es erneut.',
],
'delete' => [
'success' => 'The Maintenance has been deleted and will not show on your status page.',
'failure' => 'The Maintenance could not be deleted, please try again.',
'success' => 'Der Zeitplan wurde gelöscht und wird nicht auf Ihrer Statusseite angezeigt.',
'failure' => 'Der Zeitplan konnte nicht gelöscht werden. Bitte versuchen Sie es erneut.',
],
],
@@ -158,12 +158,12 @@ return [
'subscribers' => [
'subscribers' => 'Abonnenten',
'description' => 'Abonnenten erhalten E-Mail Updates, wenn Vorfälle erstellt oder Komponenten bearbeitet werden.',
'description_disabled' => 'To use this feature, you need allow people to signup for notifications.',
'description_disabled' => 'Um diese Funktion nutzen zu können, musst du zulassen, dass sich Personen für Benachrichtigungen anmelden dürfen.',
'verified' => 'Bestätigt',
'not_verified' => 'Nicht Bestätigt',
'subscriber' => ':email, abonniert am :date',
'no_subscriptions' => 'Aktualisierungen per E-Mail abonnieren',
'global' => 'Globally subscribed',
'global' => 'Alles abonniert',
'add' => [
'title' => 'Einen neuen Abonnenten hinzufügen',
'success' => 'Abonnent hinzugefügt.',
+12 -12
View File
@@ -49,12 +49,12 @@ return [
'name' => 'Name',
'status' => 'Status',
'component' => 'Komponente',
'component_status' => 'Component Status',
'component_status' => 'Komponentenstatus',
'message' => 'Nachricht',
'message-help' => 'Sie können auch Markdown verwenden.',
'occurred_at' => 'Wann ist dieser Vorfall aufgetreten?',
'notify_subscribers' => 'Abonnenten benachrichtigen',
'notify_disabled' => 'Due to scheduled maintenance, notifications about this incident or its components will be suppressed.',
'notify_disabled' => 'Aufgrund von Wartungsarbeiten werden Benachrichtigungen über diesen Vorfall oder seiner Komponenten unterdrückt.',
'visibility' => 'Ereignis Sichtbarkeit',
'stick_status' => 'Vorfall anpinnen',
'stickied' => 'Angepinnt',
@@ -153,16 +153,16 @@ return [
'display-graphs' => 'Graphen auf der Statusseite anzeigen?',
'about-this-page' => 'Über diese Seite',
'days-of-incidents' => 'Wie viele Tage mit Vorfällen sollen gezeigt werden?',
'time_before_refresh' => 'Status page refresh rate (in seconds)',
'major_outage_rate' => 'Major outage threshold (in %)',
'time_before_refresh' => 'Aktualisierungsrate der Statusseite (in Sekunden)',
'major_outage_rate' => 'Grenzwert für schwerwiegende Ausfälle (in %)',
'banner' => 'Banner Bild',
'banner-help' => "It's recommended that you upload files no bigger than 930px wide",
'banner-help' => 'Es wird empfohlen, dass Sie keine Dateien, die breiter als 930 Pixel sind, hochladen',
'subscribers' => 'Personen die Anmeldung für E-Mail-Benachrichtigung erlauben?',
'suppress_notifications_in_maintenance' => 'Suppress notifications when incident occurs during maintenance period?',
'suppress_notifications_in_maintenance' => 'Möchten Sie Benachrichtigungen über einen Vorfall während des Zeitraumes der Wartungsarbeiten unterdrücken?',
'skip_subscriber_verification' => 'Verifizierung der Nutzer überspringen? (Warnung, du könntest gespammt werden)',
'automatic_localization' => 'Die Status-Seite automatisch auf die Sprache deiner Besucher anpassen?',
'enable_external_dependencies' => 'Drittanbieter Abhängigkeiten erlauben (Google Schriftarten, Tracker, etc...)',
'show_timezone' => 'Show the timezone the status page is running in',
'show_timezone' => 'Zeitzone in der sich die Status-Seite befindet anzeigen',
'only_disrupted_days' => 'Im Verlauf nur Tage mit Vorfällen anzeigen?',
],
'analytics' => [
@@ -180,8 +180,8 @@ return [
'security' => [
'allowed-domains' => 'Erlaubte Domains',
'allowed-domains-help' => 'Durch Kommata trennen. Die oben genannte Domain ist standardmäßig erlaubt.',
'always-authenticate' => 'Always authenticate',
'always-authenticate-help' => 'Require login to view any Cachet page',
'always-authenticate' => 'Immer anmelden',
'always-authenticate-help' => 'Anmeldung für alle Cachet Seiten erzwingen',
],
'stylesheet' => [
'custom-css' => 'Benutzerdefiniertes Stylesheet',
@@ -191,7 +191,7 @@ return [
'background-fills' => 'Hintergrunddateien (Komponenten, Vorfälle, Footer)',
'banner-background-color' => 'Banner Background Color',
'banner-padding' => 'Banner Padding',
'fullwidth-banner' => 'Enable full width banner?',
'fullwidth-banner' => 'Banner über komplette Breite?',
'text-color' => 'Schriftfarbe',
'dashboard-login' => 'Dashboard-Button im Footer anzeigen?',
'reds' => 'Rot (Genutzt für Fehler)',
@@ -221,7 +221,7 @@ return [
],
'team' => [
'description' => 'Invite your team members by entering their email addresses here.',
'email' => 'Your Team Members Email Address',
'email' => 'Die E-Mail Adresse deines Teammitgliedes',
],
],
@@ -241,7 +241,7 @@ return [
'remove' => 'Entfernen',
'invite' => 'Einladen',
'signup' => 'Registrieren',
'manage_updates' => 'Manage Updates',
'manage_updates' => 'Updates verwalten',
// Other
'optional' => '* optional',
+38 -38
View File
@@ -13,84 +13,84 @@ return [
'component' => [
'status_update' => [
'mail' => [
'subject' => 'Component Status Updated',
'greeting' => 'A component\'s status was updated!',
'content' => ':name status changed from :old_status to :new_status.',
'action' => 'View',
'subject' => 'Status der Komponente aktualisiert',
'greeting' => 'Ein Komponentenstatus wurde aktualisiert!',
'content' => ':name Status wurde von :old_status zu :new_status geändert.',
'action' => 'Anzeigen',
],
'slack' => [
'title' => 'Component Status Updated',
'content' => ':name status changed from :old_status to :new_status.',
'title' => 'Status der Komponente aktualisiert',
'content' => ':name Status wurde von :old_status zu :new_status geändert.',
],
'sms' => [
'content' => ':name status changed from :old_status to :new_status.',
'content' => ':name Status wurde von :old_status zu :new_status geändert.',
],
],
],
'incident' => [
'new' => [
'mail' => [
'subject' => 'New Incident Reported',
'greeting' => 'A new incident was reported at :app_name.',
'content' => 'Incident :name was reported',
'action' => 'View',
'subject' => 'Neuer Vorfall gemeldet',
'greeting' => 'Ein neuer Vorfall wurde auf der :app_name Status Seite gemeldet.',
'content' => 'Vorfall :name wurde gemeldet',
'action' => 'Anzeigen',
],
'slack' => [
'title' => 'Incident :name Reported',
'content' => 'A new incident was reported at :app_name',
'title' => 'Vorfall :name gemeldet',
'content' => 'Ein neuer Vorfall wurde auf der :app_name Status Seite gemeldet',
],
'sms' => [
'content' => 'A new incident was reported at :app_name.',
'content' => 'Ein neuer Vorfall wurde auf der :app_name Status Seite gemeldet.',
],
],
'update' => [
'mail' => [
'subject' => 'Incident Updated',
'content' => ':name was updated',
'title' => ':name was updated to :new_status',
'action' => 'View',
'subject' => 'Vorfall aktualisiert',
'content' => ':name wurde aktualisiert',
'title' => ':name wurde auf :new_status aktualisiert',
'action' => 'Anzeigen',
],
'slack' => [
'title' => ':name Updated',
'content' => ':name was updated to :new_status',
'title' => ':name aktualisiert',
'content' => ':name wurde auf :new_status aktualisiert',
],
'sms' => [
'content' => 'Incident :name was updated',
'content' => 'Vorfall :name wurde aktualisiert',
],
],
],
'schedule' => [
'new' => [
'mail' => [
'subject' => 'New Schedule Created',
'content' => ':name was scheduled for :date',
'title' => 'A new scheduled maintenance was created.',
'action' => 'View',
'subject' => 'Neuer Zeitplan erstellt',
'content' => ':name wurde für :date geplant',
'title' => 'Eine neue geplante Wartung wurde erstellt.',
'action' => 'Anzeigen',
],
'slack' => [
'title' => 'New Schedule Created!',
'content' => ':name was scheduled for :date',
'title' => 'Neuer Zeitplan erstellt!',
'content' => ':name wurde für :date geplant',
],
'sms' => [
'content' => ':name was scheduled for :date',
'content' => ':name wurde für :date geplant',
],
],
],
'subscriber' => [
'verify' => [
'mail' => [
'subject' => 'Verify Your Subscription',
'content' => 'Click to verify your subscription to :app_name status page.',
'title' => 'Verify your subscription to :app_name status page.',
'action' => 'Verify',
'subject' => 'Bitte bestätigen Sie Ihr Abonnement',
'content' => 'Klicken Sie, um Ihr Abonnement von :app_name Statusseite zu bestätigen.',
'title' => 'Bestätigen Sie Ihr Abonnement für die :app_name Statusseite.',
'action' => 'Bestätigen',
],
],
],
'system' => [
'test' => [
'mail' => [
'subject' => 'Ping from Cachet!',
'content' => 'This is a test notification from Cachet!',
'subject' => 'Ping von Cachet!',
'content' => 'Dies ist eine Test-Benachrichtigung von Cachet!',
'title' => '🔔',
],
],
@@ -98,10 +98,10 @@ return [
'user' => [
'invite' => [
'mail' => [
'subject' => 'Your invitation is inside...',
'content' => 'You have been invited to join :app_name status page.',
'title' => 'You\'re invited to join :app_name status page.',
'action' => 'Accept',
'subject' => 'Ihre Einladung wartet auf Sie...',
'content' => 'Sie wurden eingeladen, um der :app_name Statusseite beizutreten.',
'title' => 'Sie sind dazu eingeladen, der :app_name Statusseite beizutreten.',
'action' => 'Akzeptieren',
],
],
],
+1
View File
@@ -92,6 +92,7 @@ return [
'email' => [
'subscribe' => 'Subscribe to email updates.',
'subscribed' => 'You\'ve been subscribed to email notifications, please check your email to confirm your subscription.',
'updated-subscribe' => 'You\'ve succesfully updated your subscriptions.',
'verified' => 'Your email subscription has been confirmed. Thank you!',
'manage' => 'Manage your subscription',
'unsubscribe' => 'Unsubscribe from email updates.',
+6 -1
View File
@@ -168,7 +168,7 @@ return [
'analytics' => [
'analytics_google' => 'Google Analytics code',
'analytics_gosquared' => 'GoSquared Analytics code',
'analytics_piwik_url' => 'URL of your Piwik instance (without http(s)://)',
'analytics_piwik_url' => 'URL of your Piwik instance',
'analytics_piwik_siteid' => 'Piwik\'s site id',
],
'localization' => [
@@ -229,6 +229,11 @@ return [
'timezone' => 'Select Timezone',
],
'seo' => [
'title' => 'SEO Title',
'description' => 'SEO Description',
],
// Buttons
'add' => 'Add',
'save' => 'Save',
+146
View File
@@ -0,0 +1,146 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
return [
// Components
'components' => [
'last_updated' => 'Last updated :timestamp',
'status' => [
0 => 'Unknown',
1 => 'Operational',
2 => 'Performance Issues',
3 => 'Partial Outage',
4 => 'Major Outage',
],
'group' => [
'other' => 'Other Components',
],
'select_all' => 'Select All',
'deselect_all' => 'Deselect All',
],
// Incidents
'incidents' => [
'none' => 'No incidents reported',
'past' => 'Past Incidents',
'stickied' => 'Stickied Incidents',
'scheduled' => 'Maintenance',
'scheduled_at' => ', scheduled :timestamp',
'posted' => 'Posted :timestamp',
'posted_at' => 'Posted at :timestamp',
'status' => [
1 => 'Investigating',
2 => 'Identified',
3 => 'Watching',
4 => 'Fixed',
],
],
// Schedule
'schedules' => [
'status' => [
0 => 'Upcoming',
1 => 'In Progress',
2 => 'Complete',
],
],
// Service Status
'service' => [
'good' => '[0,1]System operational|[2,*]All systems are operational',
'bad' => '[0,1]The system is experiencing issues|[2,*]Some systems are experiencing issues',
'major' => '[0,1]The system is experiencing major issues|[2,*]Some systems are experiencing major issues',
],
'api' => [
'regenerate' => 'Regenerate API Key',
'revoke' => 'Revoke API Key',
],
// Metrics
'metrics' => [
'filter' => [
'last_hour' => 'Last Hour',
'hourly' => 'Last 12 Hours',
'weekly' => 'Week',
'monthly' => 'Month',
],
],
// Subscriber
'subscriber' => [
'subscribe' => 'Subscribe to status changes and incident updates',
'unsubscribe' => 'Unsubscribe',
'button' => 'Subscribe',
'manage_subscription' => 'Manage subscription',
'manage' => [
'notifications' => 'Notifications',
'notifications_for' => 'Manage notifications for',
'no_subscriptions' => 'You\'re currently subscribed to all updates.',
'update_subscription' => 'Update Subscription',
'my_subscriptions' => 'You\'re currently subscribed to the following updates.',
'manage_at_link' => 'Manage your subscriptions at :link',
],
'email' => [
'subscribe' => 'Subscribe to email updates.',
'subscribed' => 'You\'ve been subscribed to email notifications, please check your email to confirm your subscription.',
'verified' => 'Your email subscription has been confirmed. Thank you!',
'manage' => 'Manage your subscription',
'unsubscribe' => 'Unsubscribe from email updates.',
'unsubscribed' => 'Your email subscription has been cancelled.',
'failure' => 'Something went wrong with the subscription.',
'already-subscribed' => 'Cannot subscribe :email because they\'re already subscribed.',
],
],
'signup' => [
'title' => 'Sign Up',
'username' => 'Username',
'email' => 'Email',
'password' => 'Password',
'success' => 'Your account has been created.',
'failure' => 'Something went wrong with the signup.',
],
'system' => [
'update' => 'There is a newer version of Cachet available. You can learn how to update <a href="https://docs.cachethq.io/docs/updating-cachet">here</a>!',
],
// Modal
'modal' => [
'close' => 'Close',
'subscribe' => [
'title' => 'Subscribe to component updates',
'body' => 'Enter your email address to subscribe to updates for this component. If you\'re already subscribed, you\'ll already receive emails for this component.',
'button' => 'Subscribe',
],
],
// Meta descriptions
'meta' => [
'description' => [
'incident' => 'Details and updates about the :name incident that occurred on :date',
'schedule' => 'Details about the scheduled maintenance period :name starting :startDate',
'subscribe' => 'Subscribe to :app in order to receive updates of incidents and scheduled maintenance periods',
'overview' => 'Stay up to date with the latest service updates from :app.',
],
],
// Other
'home' => 'Home',
'powered_by' => 'Powered by <a href="https://cachethq.io" class="links">Cachet</a>.',
'timezone' => 'Times are shown in :timezone.',
'about_this_site' => 'About This Site',
'rss-feed' => 'RSS',
'atom-feed' => 'Atom',
'feed' => 'Status Feed',
];
+304
View File
@@ -0,0 +1,304 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
return [
'dashboard' => 'Dashboard',
'writeable_settings' => 'The Cachet settings directory is not writeable. Please make sure that <code>./bootstrap/cachet</code> is writeable by the web server.',
// Incidents
'incidents' => [
'title' => 'Incidents & Maintenance',
'incidents' => 'Incidents',
'logged' => '{0}There are no incidents, good work.|[1]You have logged one incident.|[2,*]You have reported <strong>:count</strong> incidents.',
'incident-create-template' => 'Create Template',
'incident-templates' => 'Incident Templates',
'updates' => [
'title' => 'Incident updates for :incident',
'count' => '{0}Zero Updates|[1]One Update|[2]Two Updates|[3,*]Several Updates',
'add' => [
'title' => 'Create new incident update',
'success' => 'Your new incident update has been created.',
'failure' => 'Something went wrong with the incident update.',
],
'edit' => [
'title' => 'Edit incident update',
'success' => 'The incident update has been updated.',
'failure' => 'Something went wrong updating the incident update',
],
],
'reported_by' => 'Reported by :user',
'add' => [
'title' => 'Report an incident',
'success' => 'Incident added.',
'failure' => 'There was an error adding the incident, please try again.',
],
'edit' => [
'title' => 'Edit an incident',
'success' => 'Incident updated.',
'failure' => 'There was an error editing the incident, please try again.',
],
'delete' => [
'success' => 'The incident has been deleted and will not show on your status page.',
'failure' => 'The incident could not be deleted, please try again.',
],
// Incident templates
'templates' => [
'title' => 'Incident Templates',
'add' => [
'title' => 'Create an incident template',
'message' => 'Create your first incident template.',
'success' => 'Your new incident template has been created.',
'failure' => 'Something went wrong with the incident template.',
],
'edit' => [
'title' => 'Edit Template',
'success' => 'The incident template has been updated.',
'failure' => 'Something went wrong updating the incident template',
],
'delete' => [
'success' => 'The incident template has been deleted.',
'failure' => 'The incident template could not be deleted, please try again.',
],
],
],
// Incident Maintenance
'schedule' => [
'schedule' => 'Maintenance',
'logged' => '{0}There has been no Maintenance, good work.|[1]You have logged one schedule.|[2,*]You have reported <strong>:count</strong> schedules.',
'scheduled_at' => 'Scheduled at :timestamp',
'add' => [
'title' => 'Add Maintenance',
'success' => 'Maintenance added.',
'failure' => 'Something went wrong adding the Maintenance, please try again.',
],
'edit' => [
'title' => 'Edit Maintenance',
'success' => 'Maintenance has been updated!',
'failure' => 'Something went wrong editing the Maintenance, please try again.',
],
'delete' => [
'success' => 'The Maintenance has been deleted and will not show on your status page.',
'failure' => 'The Maintenance could not be deleted, please try again.',
],
],
// Components
'components' => [
'components' => 'Components',
'component_statuses' => 'Component Statuses',
'listed_group' => 'Grouped under :name',
'add' => [
'title' => 'Add a component',
'message' => 'You should add a component.',
'success' => 'Component created.',
'failure' => 'Something went wrong with the component group, please try again.',
],
'edit' => [
'title' => 'Edit a component',
'success' => 'Component updated.',
'failure' => 'Something went wrong with the component group, please try again.',
],
'delete' => [
'success' => 'The component has been deleted!',
'failure' => 'The component could not be deleted, please try again.',
],
// Component groups
'groups' => [
'groups' => 'Component group|Component groups',
'no_components' => 'You should add a component group.',
'add' => [
'title' => 'Add a component group',
'success' => 'Component group added.',
'failure' => 'Something went wrong with the component group, please try again.',
],
'edit' => [
'title' => 'Edit a component group',
'success' => 'Component group updated.',
'failure' => 'Something went wrong with the component group, please try again.',
],
'delete' => [
'success' => 'Component group has been deleted!',
'failure' => 'The component group could not be deleted, please try again.',
],
],
],
// Metrics
'metrics' => [
'metrics' => 'Metrics',
'add' => [
'title' => 'Create a metric',
'message' => 'You should add a metric.',
'success' => 'Metric created.',
'failure' => 'Something went wrong with the metric, please try again.',
],
'edit' => [
'title' => 'Edit a metric',
'success' => 'Metric updated.',
'failure' => 'Something went wrong with the metric, please try again.',
],
'delete' => [
'success' => 'The metric has been deleted and will no longer display on your status page.',
'failure' => 'The metric could not be deleted, please try again.',
],
],
// Subscribers
'subscribers' => [
'subscribers' => 'Subscribers',
'description' => 'Subscribers will receive email updates when incidents are created or components are updated.',
'description_disabled' => 'To use this feature, you need allow people to signup for notifications.',
'verified' => 'Verified',
'not_verified' => 'Not verified',
'subscriber' => ':email, subscribed :date',
'no_subscriptions' => 'Subscribed to all updates',
'global' => 'Globally subscribed',
'add' => [
'title' => 'Add a new subscriber',
'success' => 'Subscriber has been added!',
'failure' => 'Something went wrong adding the subscriber, please try again.',
'help' => 'Enter each subscriber on a new line.',
],
'edit' => [
'title' => 'Update subscriber',
'success' => 'Subscriber has been updated!',
'failure' => 'Something went wrong editing the subscriber, please try again.',
],
],
// Team
'team' => [
'team' => 'Team',
'member' => 'Member',
'profile' => 'Profile',
'description' => 'Team Members will be able to add, modify & edit components and incidents.',
'add' => [
'title' => 'Add a new team member',
'success' => 'Team member added.',
'failure' => 'The team member could not be added, please try again.',
],
'edit' => [
'title' => 'Update profile',
'success' => 'Profile updated.',
'failure' => 'Something went wrong updating the profile, please try again.',
],
'delete' => [
'success' => 'Team member has been deleted and will no longer have access to the dashboard!',
'failure' => 'The team member could not be added, please try again.',
],
'invite' => [
'title' => 'Invite a new team member',
'success' => 'An invite has been sent',
'failure' => 'The invite could not be sent, please try again.',
],
],
// Settings
'settings' => [
'settings' => 'Settings',
'app-setup' => [
'app-setup' => 'Application Setup',
'images-only' => 'Only images may be uploaded.',
'too-big' => 'The file you uploaded is too big. Upload an image smaller than :size',
],
'analytics' => [
'analytics' => 'Analytics',
],
'log' => [
'log' => 'Log',
],
'localization' => [
'localization' => 'Localization',
],
'customization' => [
'customization' => 'Customization',
'header' => 'Custom Header HTML',
'footer' => 'Custom Footer HTML',
],
'mail' => [
'mail' => 'Mail',
'test' => 'Test',
'email' => [
'subject' => 'Test notification from Cachet',
'body' => 'This is a test notification from Cachet.',
],
],
'security' => [
'security' => 'Security',
'two-factor' => 'Users without two-factor authentication',
],
'stylesheet' => [
'stylesheet' => 'Stylesheet',
],
'theme' => [
'theme' => 'Theme',
],
'edit' => [
'success' => 'Settings saved.',
'failure' => 'Settings could not be saved.',
],
'credits' => [
'credits' => 'Credits',
'contributors' => 'Contributors',
'license' => 'Cachet is a BSD-3-licensed open source project, released by <a href="https://alt-three.com/?utm_source=cachet&utm_medium=credits&utm_campaign=Cachet%20Credit%20Dashboard" target="_blank">Alt Three Services Limited</a>.',
'backers-title' => 'Backers & Sponsors',
'backers' => 'If you\'d like to support future development, check out the <a href="https://patreon.com/jbrooksuk" target="_blank">Cachet Patreon</a> campaign.',
'thank-you' => 'Thank you to each and every one of the :count contributors.',
],
],
// Login
'login' => [
'login' => 'Login',
'logged_in' => 'You\'re logged in.',
'welcome' => 'Welcome back!',
'two-factor' => 'Please enter your token.',
],
// Sidebar footer
'help' => 'Help',
'status_page' => 'Status Page',
'logout' => 'Logout',
// Notifications
'notifications' => [
'notifications' => 'Notifications',
'awesome' => 'Awesome.',
'whoops' => 'Whoops.',
],
// Widgets
'widgets' => [
'support' => 'Support Cachet',
'support_subtitle' => 'Check out our <strong><a href="https://patreon.com/jbrooksuk" target="_blank">Patreon</a></strong> page!',
'news' => 'Latest News',
'news_subtitle' => 'Get the latest update',
],
// Welcome modal
'welcome' => [
'welcome' => 'Welcome to your new status page, :username!',
'message' => 'You\'re almost ready but you might want to configure these extra settings first...',
'close' => 'I\'m good thanks!',
'steps' => [
'component' => 'Add your components',
'incident' => 'Create an incident',
'customize' => 'Customize your page',
'team' => 'Add your team',
'api' => 'Generate an API token',
'two-factor' => 'Setup Two Factor Authentication',
],
],
];
+248
View File
@@ -0,0 +1,248 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
return [
// Setup form fields
'setup' => [
'email' => 'Email',
'username' => 'Username',
'password' => 'Password',
'site_name' => 'Site Name',
'site_domain' => 'Site Domain',
'site_timezone' => 'Select your timezone',
'site_locale' => 'Select your language',
'enable_google2fa' => 'Enable Google Two Factor Authentication',
'cache_driver' => 'Cache Driver',
'queue_driver' => 'Queue Driver',
'session_driver' => 'Session Driver',
'mail_driver' => 'Mail Driver',
'mail_host' => 'Mail Host',
'mail_address' => 'Mail From Address',
'mail_username' => 'Mail Username',
'mail_password' => 'Mail Password',
],
// Login form fields
'login' => [
'login' => 'Username or Email',
'email' => 'Email',
'password' => 'Password',
'2fauth' => 'Authentication Code',
'invalid' => 'Invalid username or password',
'invalid-token' => 'Invalid token',
'cookies' => 'You must enable cookies to login.',
'rate-limit' => 'Rate limit exceeded.',
'remember_me' => 'Remember me',
],
// Incidents form fields
'incidents' => [
'name' => 'Name',
'status' => 'Status',
'component' => 'Component',
'component_status' => 'Component Status',
'message' => 'Message',
'message-help' => 'You may also use Markdown.',
'occurred_at' => 'When did this incident occur?',
'notify_subscribers' => 'Notify subscribers?',
'notify_disabled' => 'Due to scheduled maintenance, notifications about this incident or its components will be suppressed.',
'visibility' => 'Incident Visibility',
'stick_status' => 'Stick Incident',
'stickied' => 'Stickied',
'not_stickied' => 'Not Stickied',
'public' => 'Viewable by public',
'logged_in_only' => 'Only visible to logged in users',
'templates' => [
'name' => 'Name',
'template' => 'Template',
'twig' => 'Incident Templates can make use of the <a href="http://twig.sensiolabs.org/" target="_blank">Twig</a> templating language.',
],
],
'schedules' => [
'name' => 'Name',
'status' => 'Status',
'message' => 'Message',
'message-help' => 'You may also use Markdown.',
'scheduled_at' => 'When is this maintenance scheduled for?',
'completed_at' => 'When did this maintenance complete?',
'templates' => [
'name' => 'Name',
'template' => 'Template',
'twig' => 'Incident Templates can make use of the <a href="http://twig.sensiolabs.org/" target="_blank">Twig</a> templating language.',
],
],
// Components form fields
'components' => [
'name' => 'Name',
'status' => 'Status',
'group' => 'Group',
'description' => 'Description',
'link' => 'Link',
'tags' => 'Tags',
'tags-help' => 'Comma separated.',
'enabled' => 'Component enabled?',
'groups' => [
'name' => 'Name',
'collapsing' => 'Expand/Collapse options',
'visible' => 'Always expanded',
'collapsed' => 'Collapse the group by default',
'collapsed_incident' => 'Collapse the group, but expand if there are issues',
'visibility' => 'Visibility',
'visibility_public' => 'Visible to public',
'visibility_authenticated' => 'Visible only to logged in users',
],
],
// Action form fields
'actions' => [
'name' => 'Name',
'description' => 'Description',
'start_at' => 'Schedule start time',
'timezone' => 'Timezone',
'schedule_frequency' => 'Schedule frequency (in seconds)',
'completion_latency' => 'Completion latency (in seconds)',
'group' => 'Group',
'active' => 'Active?',
'groups' => [
'name' => 'Group Name',
],
],
// Metric form fields
'metrics' => [
'name' => 'Name',
'suffix' => 'Suffix',
'description' => 'Description',
'description-help' => 'You may also use Markdown.',
'display-chart' => 'Display chart on status page?',
'default-value' => 'Default value',
'calc_type' => 'Calculation of metrics',
'type_sum' => 'Sum',
'type_avg' => 'Average',
'places' => 'Decimal places',
'default_view' => 'Default view',
'threshold' => 'How many minutes of threshold between metric points?',
'visibility' => 'Visibility',
'visibility_authenticated' => 'Visible to authenticated users',
'visibility_public' => 'Visible to everybody',
'visibility_hidden' => 'Always hidden',
'points' => [
'value' => 'Value',
],
],
// Settings
'settings' => [
// Application setup
'app-setup' => [
'site-name' => 'Site Name',
'site-url' => 'Site URL',
'display-graphs' => 'Display graphs on status page?',
'about-this-page' => 'About this page',
'days-of-incidents' => 'How many days of incidents to show?',
'time_before_refresh' => 'Status page refresh rate (in seconds)',
'major_outage_rate' => 'Major outage threshold (in %)',
'banner' => 'Banner Image',
'banner-help' => "It's recommended that you upload files no bigger than 930px wide",
'subscribers' => 'Allow people to signup to email notifications?',
'suppress_notifications_in_maintenance' => 'Suppress notifications when incident occurs during maintenance period?',
'skip_subscriber_verification' => 'Skip verifying of users? (Be warned, you could be spammed)',
'automatic_localization' => 'Automatically localise your status page to your visitor\'s language?',
'enable_external_dependencies' => 'Enable Third Party Dependencies (Google Fonts, Trackers, etc...)',
'show_timezone' => 'Show the timezone the status page is running in',
'only_disrupted_days' => 'Only show days containing incidents in the timeline?',
],
'analytics' => [
'analytics_google' => 'Google Analytics code',
'analytics_gosquared' => 'GoSquared Analytics code',
'analytics_piwik_url' => 'URL of your Piwik instance (without http(s)://)',
'analytics_piwik_siteid' => 'Piwik\'s site id',
],
'localization' => [
'site-timezone' => 'Site timezone',
'site-locale' => 'Site language',
'date-format' => 'Date format',
'incident-date-format' => 'Incident timestamp format',
],
'security' => [
'allowed-domains' => 'Allowed domains',
'allowed-domains-help' => 'Comma separated. The domain set above is automatically allowed by default.',
'always-authenticate' => 'Always authenticate',
'always-authenticate-help' => 'Require login to view any Cachet page',
],
'stylesheet' => [
'custom-css' => 'Custom Stylesheet',
],
'theme' => [
'background-color' => 'Background color',
'background-fills' => 'Background fills (components, incidents, footer)',
'banner-background-color' => 'Banner background color',
'banner-padding' => 'Banner padding',
'fullwidth-banner' => 'Enable full width banner?',
'text-color' => 'Text color',
'dashboard-login' => 'Show dashboard button in the footer?',
'reds' => 'Red (used for errors)',
'blues' => 'Blue (used for information)',
'greens' => 'Green (used for success)',
'yellows' => 'Yellow (used for alerts)',
'oranges' => 'Orange (used for notices)',
'metrics' => 'Metrics fill',
'links' => 'Links',
],
],
'user' => [
'username' => 'Username',
'email' => 'Email',
'password' => 'Password',
'api-token' => 'API Token',
'api-token-help' => 'Regenerating your API token will prevent existing applications from accessing Cachet.',
'gravatar' => 'Change your profile picture at Gravatar.',
'user_level' => 'User Level',
'levels' => [
'admin' => 'Admin',
'user' => 'User',
],
'2fa' => [
'help' => 'Enabling two factor authentication increases security of your account. You will need to download <a href="https://support.google.com/accounts/answer/1066447?hl=en">Google Authenticator</a> or a similar app on to your mobile device. When you login you will be asked to provide a token generated by the app.',
],
'team' => [
'description' => 'Invite your team members by entering their email addresses here.',
'email' => 'Your Team Members Email Address',
],
],
'general' => [
'timezone' => 'Select Timezone',
],
// Buttons
'add' => 'Add',
'save' => 'Save',
'update' => 'Update',
'create' => 'Create',
'edit' => 'Edit',
'delete' => 'Delete',
'submit' => 'Submit',
'cancel' => 'Cancel',
'remove' => 'Remove',
'invite' => 'Invite',
'signup' => 'Sign Up',
'manage_updates' => 'Manage Updates',
// Other
'optional' => '* Optional',
];
+108
View File
@@ -0,0 +1,108 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
return [
'component' => [
'status_update' => [
'mail' => [
'subject' => 'Component Status Updated',
'greeting' => 'A component\'s status was updated!',
'content' => ':name status changed from :old_status to :new_status.',
'action' => 'View',
],
'slack' => [
'title' => 'Component Status Updated',
'content' => ':name status changed from :old_status to :new_status.',
],
'sms' => [
'content' => ':name status changed from :old_status to :new_status.',
],
],
],
'incident' => [
'new' => [
'mail' => [
'subject' => 'New Incident Reported',
'greeting' => 'A new incident was reported at :app_name.',
'content' => 'Incident :name was reported',
'action' => 'View',
],
'slack' => [
'title' => 'Incident :name Reported',
'content' => 'A new incident was reported at :app_name',
],
'sms' => [
'content' => 'A new incident was reported at :app_name.',
],
],
'update' => [
'mail' => [
'subject' => 'Incident Updated',
'content' => ':name was updated',
'title' => ':name was updated to :new_status',
'action' => 'View',
],
'slack' => [
'title' => ':name Updated',
'content' => ':name was updated to :new_status',
],
'sms' => [
'content' => 'Incident :name was updated',
],
],
],
'schedule' => [
'new' => [
'mail' => [
'subject' => 'New Schedule Created',
'content' => ':name was scheduled for :date',
'title' => 'A new scheduled maintenance was created.',
'action' => 'View',
],
'slack' => [
'title' => 'New Schedule Created!',
'content' => ':name was scheduled for :date',
],
'sms' => [
'content' => ':name was scheduled for :date',
],
],
],
'subscriber' => [
'verify' => [
'mail' => [
'subject' => 'Verify Your Subscription',
'content' => 'Click to verify your subscription to :app_name status page.',
'title' => 'Verify your subscription to :app_name status page.',
'action' => 'Verify',
],
],
],
'system' => [
'test' => [
'mail' => [
'subject' => 'Ping from Cachet!',
'content' => 'This is a test notification from Cachet!',
'title' => '🔔',
],
],
],
'user' => [
'invite' => [
'mail' => [
'subject' => 'Your invitation is inside...',
'content' => 'You have been invited to join :app_name status page.',
'title' => 'You\'re invited to join :app_name status page.',
'action' => 'Accept',
],
],
],
];
+28
View File
@@ -0,0 +1,28 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
return [
/*
|--------------------------------------------------------------------------
| Pagination Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used by the paginator library to build
| the simple pagination links. You are free to change them to anything
| you want to customize your views to better match your application.
|
*/
'previous' => 'Previous',
'next' => 'Next',
];
+23
View File
@@ -0,0 +1,23 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
return [
'setup' => 'Setup',
'title' => 'Install Cachet',
'service_details' => 'Service Details',
'env_setup' => 'Environment Setup',
'status_page_setup' => 'Status Page Setup',
'show_support' => 'Show support for Cachet?',
'admin_account' => 'Administrator Account',
'complete_setup' => 'Complete Setup',
'completed' => 'Cachet has been configured successfully!',
'finish_setup' => 'Go to dashboard',
];
+122
View File
@@ -0,0 +1,122 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
return [
/*
|--------------------------------------------------------------------------
| Validation Language Lines
|--------------------------------------------------------------------------
|
| The following language lines contain the default error messages used by
| the validator class. Some of these rules have multiple versions such
| as the size rules. Feel free to tweak each of these messages here.
|
*/
'accepted' => 'The :attribute must be accepted.',
'active_url' => 'The :attribute is not a valid URL.',
'after' => 'The :attribute must be a date after :date.',
'alpha' => 'The :attribute may only contain letters.',
'alpha_dash' => 'The :attribute may only contain letters, numbers, and dashes.',
'alpha_num' => 'The :attribute may only contain letters and numbers.',
'array' => 'The :attribute must be an array.',
'before' => 'The :attribute must be a date before :date.',
'between' => [
'numeric' => 'The :attribute must be between :min and :max.',
'file' => 'The :attribute must be between :min and :max kilobytes.',
'string' => 'The :attribute must be between :min and :max characters.',
'array' => 'The :attribute must have between :min and :max items.',
],
'boolean' => 'The :attribute field must be true or false.',
'confirmed' => 'The :attribute confirmation does not match.',
'date' => 'The :attribute is not a valid date.',
'date_format' => 'The :attribute does not match the format :format.',
'different' => 'The :attribute and :other must be different.',
'digits' => 'The :attribute must be :digits digits.',
'digits_between' => 'The :attribute must be between :min and :max digits.',
'email' => 'The :attribute must be a valid email address.',
'exists' => 'The selected :attribute is invalid.',
'distinct' => 'The :attribute field has a duplicate value.',
'filled' => 'The :attribute field is required.',
'image' => 'The :attribute must be an image.',
'in' => 'The selected :attribute is invalid.',
'in_array' => 'The :attribute field does not exist in :other.',
'integer' => 'The :attribute must be an integer.',
'ip' => 'The :attribute must be a valid IP address.',
'json' => 'The :attribute must be a valid JSON string.',
'max' => [
'numeric' => 'The :attribute may not be greater than :max.',
'file' => 'The :attribute may not be greater than :max kilobytes.',
'string' => 'The :attribute may not be greater than :max characters.',
'array' => 'The :attribute may not have more than :max items.',
],
'mimes' => 'The :attribute must be a file of type: :values.',
'min' => [
'numeric' => 'The :attribute must be at least :min.',
'file' => 'The :attribute must be at least :min kilobytes.',
'string' => 'The :attribute must be at least :min characters.',
'array' => 'The :attribute must have at least :min items.',
],
'not_in' => 'The selected :attribute is invalid.',
'numeric' => 'The :attribute must be a number.',
'present' => 'The :attribute field must be present.',
'regex' => 'The :attribute format is invalid.',
'required' => 'The :attribute field is required.',
'required_if' => 'The :attribute field is required when :other is :value.',
'required_unless' => 'The :attribute field is required unless :other is in :values.',
'required_with' => 'The :attribute field is required when :values is present.',
'required_with_all' => 'The :attribute field is required when :values is present.',
'required_without' => 'The :attribute field is required when :values is not present.',
'required_without_all' => 'The :attribute field is required when none of :values are present.',
'same' => 'The :attribute and :other must match.',
'size' => [
'numeric' => 'The :attribute must be :size.',
'file' => 'The :attribute must be :size kilobytes.',
'string' => 'The :attribute must be :size characters.',
'array' => 'The :attribute must contain :size items.',
],
'string' => 'The :attribute must be a string.',
'timezone' => 'The :attribute must be a valid zone.',
'unique' => 'The :attribute has already been taken.',
'url' => 'The :attribute format is invalid.',
/*
|--------------------------------------------------------------------------
| Custom Validation Language Lines
|--------------------------------------------------------------------------
|
| Here you may specify custom validation messages for attributes using the
| convention "attribute.rule" to name the lines. This makes it quick to
| specify a specific custom language line for a given attribute rule.
|
*/
'custom' => [
'attribute-name' => [
'rule-name' => 'custom-message',
],
],
/*
|--------------------------------------------------------------------------
| Custom Validation Attributes
|--------------------------------------------------------------------------
|
| The following language lines are used to swap attribute place-holders
| with something more reader friendly such as E-Mail Address instead
| of "email". This simply helps us make messages a little cleaner.
|
*/
'attributes' => [],
];

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