Introduce two new dash widgets: welcome and active theme

System warnings have been moved to the system dash widget
Minor styling and language changes
This commit is contained in:
Samuel Georges 2016-05-28 11:10:33 +10:00
parent 8a7f762c71
commit 805c0939ad
60 changed files with 570 additions and 133 deletions

View File

@ -252,7 +252,7 @@
.oc-logo{background-image:url(../images/october-logo.svg);background-position:50% 50%;background-repeat:no-repeat;background-size:contain} .oc-logo{background-image:url(../images/october-logo.svg);background-position:50% 50%;background-repeat:no-repeat;background-size:contain}
.layout.control-tabs.oc-logo-transparent:not(.has-tabs),.layout-cell.oc-logo-transparent{background-size:50% auto;background-repeat:no-repeat;background-image:url(../images/october-logo.svg);background-position:50% 50%;position:relative} .layout.control-tabs.oc-logo-transparent:not(.has-tabs),.layout-cell.oc-logo-transparent{background-size:50% auto;background-repeat:no-repeat;background-image:url(../images/october-logo.svg);background-position:50% 50%;position:relative}
.layout.control-tabs.oc-logo-transparent:not(.has-tabs):after,.layout-cell.oc-logo-transparent:after{content:'';display:table-cell;position:absolute;left:0;top:0;height:100%;width:100%;background:rgba(249,249,249,0.7)} .layout.control-tabs.oc-logo-transparent:not(.has-tabs):after,.layout-cell.oc-logo-transparent:after{content:'';display:table-cell;position:absolute;left:0;top:0;height:100%;width:100%;background:rgba(249,249,249,0.7)}
.report-widget{padding:15px;background:white;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px} .report-widget{padding:15px;background:white;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;font-size:13px}
.report-widget h3{font-size:14px;color:#7e8c8d;text-transform:uppercase;font-weight:600;margin-top:0;margin-bottom:30px} .report-widget h3{font-size:14px;color:#7e8c8d;text-transform:uppercase;font-weight:600;margin-top:0;margin-bottom:30px}
.report-widget .height-100{height:100px} .report-widget .height-100{height:100px}
.report-widget .height-200{height:200px} .report-widget .height-200{height:200px}
@ -260,7 +260,14 @@
.report-widget .height-400{height:400px} .report-widget .height-400{height:400px}
.report-widget .height-500{height:500px} .report-widget .height-500{height:500px}
.report-widget p.report-description{margin-bottom:0;margin-top:15px;font-size:12px;line-height:190%;color:#7e8c8d} .report-widget p.report-description{margin-bottom:0;margin-top:15px;font-size:12px;line-height:190%;color:#7e8c8d}
.report-widget a{color:#7e8c8d;text-decoration:none}
.report-widget a:hover{color:#0181b9;text-decoration:none}
.report-widget p.flash-message.static{margin-bottom:0} .report-widget p.flash-message.static{margin-bottom:0}
.report-widget .icon-circle.success{color:#31ac5f}
.report-widget .icon-circle.primary{color:#34495e}
.report-widget .icon-circle.warning{color:#f0ad4e}
.report-widget .icon-circle.danger{color:#ab2a1c}
.report-widget .icon-circle.info{color:#5bc0de}
.control-treelist ol{padding:0;margin:0;list-style:none} .control-treelist ol{padding:0;margin:0;list-style:none}
.control-treelist ol ol{margin:0;margin-left:15px;padding-left:15px;border-left:1px solid #dbdee0} .control-treelist ol ol{margin:0;margin-left:15px;padding-left:15px;border-left:1px solid #dbdee0}
.control-treelist > ol > li > div.record:before{display:none} .control-treelist > ol > li > div.record:before{display:none}

View File

@ -3,9 +3,10 @@
background: white; background: white;
.box-sizing(border-box); .box-sizing(border-box);
.border-radius(@border-radius-base); .border-radius(@border-radius-base);
font-size: @font-size-base - 1;
h3 { h3 {
font-size: 14px; font-size: @font-size-base;
color: @color-report-widget-title; color: @color-report-widget-title;
text-transform: uppercase; text-transform: uppercase;
font-weight: 600; font-weight: 600;
@ -27,7 +28,24 @@
color: @color-report-widget-description; color: @color-report-widget-description;
} }
a {
color: @color-report-widget-link;
text-decoration: none;
&:hover {
color: @link-color;
text-decoration: none;
}
}
p.flash-message.static { p.flash-message.static {
margin-bottom: 0; margin-bottom: 0;
} }
.icon-circle {
&.success { color: @brand-success; }
&.primary { color: @brand-primary; }
&.warning { color: @brand-warning; }
&.danger { color: @brand-danger; }
&.info { color: @brand-info; }
}
} }

View File

@ -119,6 +119,7 @@
@color-report-widget-title: #7e8c8d; @color-report-widget-title: #7e8c8d;
@color-report-widget-control-inactive: #b6b6b6; @color-report-widget-control-inactive: #b6b6b6;
@color-report-widget-description: @color-report-widget-title; @color-report-widget-description: @color-report-widget-title;
@color-report-widget-link: @color-report-widget-title;
@color-treeview-item-bg: #ffffff; @color-treeview-item-bg: #ffffff;
@color-treeview-item-title: #2b3e50; @color-treeview-item-title: #2b3e50;

View File

@ -1,50 +0,0 @@
<?php
$warnings = [];
$writablePaths = [
temp_path(),
themes_path(),
storage_path(),
storage_path('app'),
storage_path('logs'),
storage_path('framework'),
storage_path('cms'),
storage_path('cms/cache'),
storage_path('cms/twig'),
storage_path('cms/combiner'),
];
$requiredExtensions = [
'GD' => extension_loaded('gd'),
'fileinfo' => extension_loaded('fileinfo'),
'Zip' => class_exists('ZipArchive'),
'cURL' => function_exists('curl_init') && defined('CURLOPT_FOLLOWLOCATION'),
'OpenSSL' => function_exists('openssl_random_pseudo_bytes'),
];
foreach ($writablePaths as $path) {
if (!is_writable($path))
$warnings[] = Lang::get('backend::lang.warnings.permissions', ['name' => '<strong>'.$path.'</strong>']);
}
foreach ($requiredExtensions as $extension => $installed) {
if (!$installed)
$warnings[] = Lang::get('backend::lang.warnings.extension', ['name' => '<strong>'.$extension.'</strong>']);
}
?>
<?php if (count($warnings)): ?>
<div class="callout callout-warning">
<div class="header">
<i class="icon-warning"></i>
<h3><?= e(trans('backend::lang.warnings.tips')) ?></h3>
<p><?= e(trans('backend::lang.warnings.tips_description')) ?></p>
</div>
<div class="content">
<ul>
<?php foreach ($warnings as $warning): ?>
<li><?= $warning ?></li>
<?php endforeach ?>
</ul>
</div>
</div>
<?php endif ?>

View File

@ -3,8 +3,21 @@
# =================================== # ===================================
defaultWidgets: defaultWidgets:
welcome:
class: Backend\ReportWidgets\Welcome
sortOrder: 50
configuration:
ocWidgetWidth: 6
systemStatus: systemStatus:
class: System\ReportWidgets\Status class: System\ReportWidgets\Status
sortOrder: 1 sortOrder: 60
configuration: configuration:
ocWidgetWidth: 10 ocWidgetWidth: 6
activeTheme:
class: Cms\ReportWidgets\ActiveTheme
sortOrder: 70
configuration:
ocWidgetWidth: 4

View File

@ -1,5 +1,3 @@
<?= $this->makePartial('warnings') ?>
<?= Form::open(['class'=>'layout-relative dashboard-container']) ?> <?= Form::open(['class'=>'layout-relative dashboard-container']) ?>
<div id="dashReportContainer" class="report-container loading"> <div id="dashReportContainer" class="report-container loading">

View File

@ -67,8 +67,6 @@ return [
'widget_title_error' => 'Musíte zadat název widgetu', 'widget_title_error' => 'Musíte zadat název widgetu',
'status' => [ 'status' => [
'widget_title_default' => 'Status systému', 'widget_title_default' => 'Status systému',
'online' => 'online',
'maintenance' => 'v údržbě',
'update_available' => '{0} dostupných aktualizací!|{1} dostupná aktualizace!|[2,Inf] dostupných aktualizací!' 'update_available' => '{0} dostupných aktualizací!|{1} dostupná aktualizace!|[2,Inf] dostupných aktualizací!'
] ]
], ],

View File

@ -67,8 +67,6 @@ return [
'widget_title_error' => 'O τίτλος του Widget είναι απαραίτητος.', 'widget_title_error' => 'O τίτλος του Widget είναι απαραίτητος.',
'status' => [ 'status' => [
'widget_title_default' => 'Κατάσταση συστήματος', 'widget_title_default' => 'Κατάσταση συστήματος',
'online' => 'ενεργό',
'maintenance' => 'σε συντήρηση',
'update_available' => '{0} διαθέσιμες ενημερώσεις!|{1} διαθέσιμη ενημέρωση!|[2,Inf] διαθέσιμες ενημερώσεις!', 'update_available' => '{0} διαθέσιμες ενημερώσεις!|{1} διαθέσιμη ενημέρωση!|[2,Inf] διαθέσιμες ενημερώσεις!',
] ]
], ],

View File

@ -67,11 +67,29 @@ return [
'widget_title_error' => 'The Widget Title is required.', 'widget_title_error' => 'The Widget Title is required.',
'status' => [ 'status' => [
'widget_title_default' => 'System status', 'widget_title_default' => 'System status',
'online' => 'online', 'update_available' => '{0} updates available!|{1} update available!|[2,Inf] updates available!',
'maintenance' => 'in maintenance', 'updates_pending' => 'Pending software updates',
'update_available' => '{0} updates available!|{1} update available!|[2,Inf] updates available!' 'updates_nil' => 'Software is up to date',
'updates_link' => 'Update',
'warnings_pending' => 'Some issues need attention',
'warnings_nil' => 'No warnings to display',
'warnings_link' => 'View',
'core_build' => 'System build',
'event_log' => 'Event log',
'request_log' => 'Request log',
'app_birthday' => 'Online since',
],
'welcome' => [
'widget_title_default' => 'Welcome',
'welcome_back_name' => 'Welcome back to :app, :name.',
'welcome_to_name' => 'Welcome to :app, :name.',
'first_sign_in' => 'This is the first time you have signed in.',
'last_sign_in' => 'Your last sign in was',
'view_access_logs' => 'View access logs',
'nice_message' => 'Have a great day!',
] ]
], ],
'user' => [ 'user' => [
'name' => 'Administrator', 'name' => 'Administrator',
'menu_label' => 'Administrators', 'menu_label' => 'Administrators',

View File

@ -67,8 +67,6 @@ return [
'widget_title_error' => 'El título del módulo es obligatorio.', 'widget_title_error' => 'El título del módulo es obligatorio.',
'status' => [ 'status' => [
'widget_title_default' => 'Estado del sistema', 'widget_title_default' => 'Estado del sistema',
'online' => 'en línea',
'maintenance' => 'en mantenimiento',
'update_available' => '{0} actualizaciones disponibles!|{1} actualización disponible!|[2,Inf] actualizaciones disponibles!' 'update_available' => '{0} actualizaciones disponibles!|{1} actualización disponible!|[2,Inf] actualizaciones disponibles!'
] ]
], ],

View File

@ -67,8 +67,6 @@ return [
'widget_title_error' => 'گزینه "عنوان ابزارک" حتما باید وارد شود.', 'widget_title_error' => 'گزینه "عنوان ابزارک" حتما باید وارد شود.',
'status' => [ 'status' => [
'widget_title_default' => 'وضعیت سیستم', 'widget_title_default' => 'وضعیت سیستم',
'online' => 'online',
'maintenance' => 'در حال به روز رسانی',
'update_available' => '{0} به روز رسانی موجود است!|{1} به روز رسانی موجود است!|[2,Inf] به روز رسانی موجود است!', 'update_available' => '{0} به روز رسانی موجود است!|{1} به روز رسانی موجود است!|[2,Inf] به روز رسانی موجود است!',
] ]
], ],

View File

@ -67,8 +67,6 @@ return [
'widget_title_error' => 'Le titre du Widget est obligatoire.', 'widget_title_error' => 'Le titre du Widget est obligatoire.',
'status' => [ 'status' => [
'widget_title_default' => 'État du système', 'widget_title_default' => 'État du système',
'online' => 'en ligne',
'maintenance' => 'en cours de maintenance',
'update_available' => '{0} mise à jour disponible !|{1} mise à jour disponible !|[2,Inf] mises à jour disponibles !' 'update_available' => '{0} mise à jour disponible !|{1} mise à jour disponible !|[2,Inf] mises à jour disponibles !'
] ]
], ],

View File

@ -67,8 +67,6 @@ return [
'widget_title_error' => 'A widget címének megadása kötelező.', 'widget_title_error' => 'A widget címének megadása kötelező.',
'status' => [ 'status' => [
'widget_title_default' => 'Rendszer állapota', 'widget_title_default' => 'Rendszer állapota',
'online' => 'online',
'maintenance' => 'karbantartás',
'update_available' => '{0} frissítés érhető el!|{1} frissítés érhető el!|[2,Inf] frissítés érhető el!' 'update_available' => '{0} frissítés érhető el!|{1} frissítés érhető el!|[2,Inf] frissítés érhető el!'
] ]
], ],

View File

@ -64,8 +64,6 @@ return [
'widget_title_error' => 'Tajuk gawit diperlukan.', 'widget_title_error' => 'Tajuk gawit diperlukan.',
'status' => [ 'status' => [
'widget_title_default' => 'Status sistem', 'widget_title_default' => 'Status sistem',
'online' => 'daring',
'maintenance' => 'dalam perawatan',
'update_available' => '{0} pembaruan tersedia!|{1} pembaruan tersedia!|[2,Inf] pembaruan tersedia!' 'update_available' => '{0} pembaruan tersedia!|{1} pembaruan tersedia!|[2,Inf] pembaruan tersedia!'
] ]
], ],

View File

@ -67,8 +67,6 @@ return [
'widget_title_error' => 'Il titolo del widget è un campo obbligatorio.', 'widget_title_error' => 'Il titolo del widget è un campo obbligatorio.',
'status' => [ 'status' => [
'widget_title_default' => 'Stato del sistema', 'widget_title_default' => 'Stato del sistema',
'online' => 'online',
'maintenance' => 'in manutenzione',
'update_available' => '{0} aggiornamenti disponibili!|{1} aggiornamento disponibile!|[2,Inf] aggiornamenti disponibili!' 'update_available' => '{0} aggiornamenti disponibili!|{1} aggiornamento disponibile!|[2,Inf] aggiornamenti disponibili!'
] ]
], ],

View File

@ -64,8 +64,6 @@ return [
'widget_title_error' => 'ウィジェットタイトルを指定してください。', 'widget_title_error' => 'ウィジェットタイトルを指定してください。',
'status' => [ 'status' => [
'widget_title_default' => 'システム状態', 'widget_title_default' => 'システム状態',
'online' => 'オンライン',
'maintenance' => 'メンテナンスモード',
'update_available' => '{0}個のアップデートが見つかりました。|{1} 個のアップデートが見つかりました。|[2,Inf] 個のアップデートが見つかりました。' 'update_available' => '{0}個のアップデートが見つかりました。|{1} 個のアップデートが見つかりました。|[2,Inf] 個のアップデートが見つかりました。'
], ],
], ],

View File

@ -67,8 +67,6 @@ return [
'widget_title_error' => 'Logrīka virsraksts ir obligāts.', 'widget_title_error' => 'Logrīka virsraksts ir obligāts.',
'status' => [ 'status' => [
'widget_title_default' => 'Sistēmas statuss', 'widget_title_default' => 'Sistēmas statuss',
'online' => 'online',
'maintenance' => 'atkopšana',
'update_available' => '{0} atjauninājumi pieejami!|{1} atjauninājums pieejams!|[2,Inf] atjauninājumi pieejami!' 'update_available' => '{0} atjauninājumi pieejami!|{1} atjauninājums pieejams!|[2,Inf] atjauninājumi pieejami!'
] ]
], ],

View File

@ -64,8 +64,6 @@ return [
'widget_title_error' => 'Tittel er obligatorisk.', 'widget_title_error' => 'Tittel er obligatorisk.',
'status' => [ 'status' => [
'widget_title_default' => 'Systemstatus', 'widget_title_default' => 'Systemstatus',
'online' => 'online',
'maintenance' => 'in maintenance',
'update_available' => '{0} oppdateringer tilgjengelig!|{1} oppdatering tilgjengelig!|[2,Inf] oppdateringer tilgjengelig!' 'update_available' => '{0} oppdateringer tilgjengelig!|{1} oppdatering tilgjengelig!|[2,Inf] oppdateringer tilgjengelig!'
] ]
], ],

View File

@ -67,8 +67,6 @@ return [
'widget_title_error' => 'Een widget titel is verplicht.', 'widget_title_error' => 'Een widget titel is verplicht.',
'status' => [ 'status' => [
'widget_title_default' => 'Systeemstatus', 'widget_title_default' => 'Systeemstatus',
'online' => 'online',
'maintenance' => 'in onderhoud',
'update_available' => '{0} updates beschikbaar!|{1} update beschikbaar!|[2,Inf] updates beschikbaar!', 'update_available' => '{0} updates beschikbaar!|{1} update beschikbaar!|[2,Inf] updates beschikbaar!',
], ],
], ],

View File

@ -67,8 +67,6 @@ return [
'widget_title_error' => 'Nazwa widgetu jest wymagana.', 'widget_title_error' => 'Nazwa widgetu jest wymagana.',
'status' => [ 'status' => [
'widget_title_default' => 'Status systemu', 'widget_title_default' => 'Status systemu',
'online' => 'online',
'maintenance' => 'w konserwacji',
'update_available' => '{0} dostępnych aktualizacji!|{1} dostępna aktualizacja!|[2,Inf] dostępne aktualizacje!' 'update_available' => '{0} dostępnych aktualizacji!|{1} dostępna aktualizacja!|[2,Inf] dostępne aktualizacje!'
] ]
], ],

View File

@ -67,8 +67,6 @@ return [
'widget_title_error' => 'O título do widget é necessário.', 'widget_title_error' => 'O título do widget é necessário.',
'status' => [ 'status' => [
'widget_title_default' => 'Status do Sistema', 'widget_title_default' => 'Status do Sistema',
'online' => 'online',
'maintenance' => 'em manutenção',
'update_available' => '{0} atualizações disponíveis!|{1} atualização disponível!|[2,Inf] atualizações disponíveis!', 'update_available' => '{0} atualizações disponíveis!|{1} atualização disponível!|[2,Inf] atualizações disponíveis!',
], ],
], ],

View File

@ -67,8 +67,6 @@ return [
'widget_title_error' => 'Заголовок виджета обязателен.', 'widget_title_error' => 'Заголовок виджета обязателен.',
'status' => [ 'status' => [
'widget_title_default' => 'Статус системы', 'widget_title_default' => 'Статус системы',
'online' => 'Онлайн',
'maintenance' => 'в разработке',
'update_available' => '{0} нет новый обновлений!|{1} доступно новое обновление!|[2,Inf] доступны новые обновления!' 'update_available' => '{0} нет новый обновлений!|{1} доступно новое обновление!|[2,Inf] доступны новые обновления!'
] ]
], ],

View File

@ -67,8 +67,6 @@ return [
'widget_title_error' => 'En widgets titel är tvingande.', 'widget_title_error' => 'En widgets titel är tvingande.',
'status' => [ 'status' => [
'widget_title_default' => 'Systemstatus', 'widget_title_default' => 'Systemstatus',
'online' => 'online',
'maintenance' => 'i underhåll',
'update_available' => '{0} uppdateringar tillgängliga!|{1} uppdatering tillgänglig!|[2,Inf] uppdateringar tillgängliga!' 'update_available' => '{0} uppdateringar tillgängliga!|{1} uppdatering tillgänglig!|[2,Inf] uppdateringar tillgängliga!'
] ]
], ],

View File

@ -67,8 +67,6 @@ return [
'widget_title_error' => 'Eklenti Başlığı gerekli.', 'widget_title_error' => 'Eklenti Başlığı gerekli.',
'status' => [ 'status' => [
'widget_title_default' => 'Sistem durumu', 'widget_title_default' => 'Sistem durumu',
'online' => 'yayında',
'maintenance' => 'bakım modunda',
'update_available' => '{0} güncelleme var!|{1} güncelleme var!|[2,Inf] güncelleme var!' 'update_available' => '{0} güncelleme var!|{1} güncelleme var!|[2,Inf] güncelleme var!'
] ]
], ],

View File

@ -67,8 +67,6 @@ return [
'widget_title_error' => '需要小工具标题.', 'widget_title_error' => '需要小工具标题.',
'status' => [ 'status' => [
'widget_title_default' => '系统状态', 'widget_title_default' => '系统状态',
'online' => '在线',
'maintenance' => '维护中',
'update_available' => '{0} 更新可用!|{1} 更新可用!|[2,Inf] 更新可用!' 'update_available' => '{0} 更新可用!|{1} 更新可用!|[2,Inf] 更新可用!'
] ]
], ],

View File

@ -64,8 +64,6 @@ return [
'widget_title_error' => '需要元件標題', 'widget_title_error' => '需要元件標題',
'status' => [ 'status' => [
'widget_title_default' => '系統狀態', 'widget_title_default' => '系統狀態',
'online' => '在線',
'maintenance' => '維護中',
'update_available' => '{0} 更新可用!|{1} 更新可用!|[2,Inf] 更新可用!' 'update_available' => '{0} 更新可用!|{1} 更新可用!|[2,Inf] 更新可用!'
] ]
], ],

View File

@ -37,4 +37,26 @@ class AccessLog extends Model
return $record; return $record;
} }
/**
* Returns a recent entry, latest entry is not considered recent
* if the creation day is the same as today.
* @return self
*/
public static function getRecent($user)
{
$records = static::where('user_id', $user->id)
->orderBy('created_at', 'desc')
->limit(2)
->get()
;
if (!count($records)) {
return null;
}
$first = $records->first();
return !$first->created_at->isToday() ? $first : $records->pop();
}
} }

View File

@ -0,0 +1,65 @@
<?php namespace Backend\ReportWidgets;
use BackendAuth;
use Backend\Models\AccessLog;
use Backend\Classes\ReportWidgetBase;
use Backend\Models\BrandSetting;
use Exception;
/**
* User welcome report widget.
*
* @package october\backend
* @author Alexey Bobkov, Samuel Georges
*/
class Welcome extends ReportWidgetBase
{
/**
* @var string A unique alias to identify this widget.
*/
protected $defaultAlias = 'welcome';
/**
* Renders the widget.
*/
public function render()
{
try {
$this->loadData();
}
catch (Exception $ex) {
traceLog($ex);
$this->vars['error'] = $ex->getMessage();
}
return $this->makePartial('widget');
}
public function defineProperties()
{
return [
'title' => [
'title' => 'backend::lang.dashboard.widget_title_label',
'default' => 'backend::lang.dashboard.welcome.widget_title_default',
'type' => 'string',
'validationPattern' => '^.+$',
'validationMessage' => 'backend::lang.dashboard.widget_title_error',
]
];
}
/**
* {@inheritDoc}
*/
protected function loadAssets()
{
$this->addCss('css/welcome.css', 'core');
}
protected function loadData()
{
$this->vars['user'] = $user = BackendAuth::getUser();
$this->vars['appName'] = BrandSetting::get('app_name');
$this->vars['lastSeen'] = AccessLog::getRecent($user);
}
}

View File

@ -0,0 +1,24 @@
.widget-welcome .welcome-container {
margin-top: -15px;
overflow: hidden; /* clearfix */
}
.widget-welcome .welcome-message {
margin-left: 220px;
color: #7e8c8d;
margin-top: 15px;
}
.widget-welcome .welcome-message strong {
color: #666;
}
.widget-welcome .welcome-logo {
background: #f9f9f9;
width: 200px;
padding: 15px;
float: left;
}
.widget-welcome .welcome-logo .oc-logo {
height: 80px;
}

View File

@ -0,0 +1,39 @@
<div class="report-widget widget-welcome">
<h3><?= e(trans($this->property('title'))) ?></h3>
<?php if (!isset($error)): ?>
<div class="welcome-container">
<div class="welcome-logo">
<div class="oc-logo"></div>
</div>
<div class="welcome-message">
<?php if ($lastSeen): ?>
<p>
<?= e(trans('backend::lang.dashboard.welcome.welcome_back_name', ['app'=>$appName, 'name'=>$user->first_name])) ?>
<?= e(trans('backend::lang.dashboard.welcome.last_sign_in')) ?>
</p>
<p>
<strong><?= Backend::dateTime($lastSeen->created_at, ['formatAlias' => 'dateTimeLongMin']) ?></strong>
</p>
<p>
<a href="<?= Backend::url('backend/accesslogs') ?>"><?= e(trans('backend::lang.dashboard.welcome.view_access_logs')) ?></a>
</p>
<?php else: ?>
<p>
<?= e(trans('backend::lang.dashboard.welcome.welcome_to_name', ['app'=>$appName, 'name'=>$user->first_name])) ?>
</p>
<p>
<?= e(trans('backend::lang.dashboard.welcome.first_sign_in')) ?>
</p>
<p>
<?= e(trans('backend::lang.dashboard.welcome.nice_message')) ?>
</p>
<?php endif ?>
</div>
</div>
<?php else: ?>
<div class="callout callout-warning">
<div class="content"><?= e($error) ?></div>
</div>
<?php endif ?>
</div>

View File

@ -30,4 +30,4 @@
<input type="hidden" data-widget-alias name="widgetAliases[]" value="<?= $widgetAlias ?>"/> <input type="hidden" data-widget-alias name="widgetAliases[]" value="<?= $widgetAlias ?>"/>
<input type="hidden" data-widget-order name="widgetSortOrders[]" value="<?= $sortOrder ?>"/> <input type="hidden" data-widget-order name="widgetSortOrders[]" value="<?= $sortOrder ?>"/>
</div> </div>
</li> </li>

View File

@ -12,6 +12,12 @@ return [
'delete_success' => 'Šablony úspěšně smazány: :count.', 'delete_success' => 'Šablony úspěšně smazány: :count.',
'file_name_required' => 'Je nutno vyplnit Název souboru.' 'file_name_required' => 'Je nutno vyplnit Název souboru.'
], ],
'dashboard' => [
'active_theme' => [
'online' => 'online',
'maintenance' => 'v údržbě',
]
],
'theme' => [ 'theme' => [
'not_found_name' => "Téma ':name' nebylo nalezeno.", 'not_found_name' => "Téma ':name' nebylo nalezeno.",
'active' => [ 'active' => [

View File

@ -12,6 +12,12 @@ return [
'delete_success' => 'Τα πρότυπα τα οποία διαγράφηκαν επιτυχώς: :count.', 'delete_success' => 'Τα πρότυπα τα οποία διαγράφηκαν επιτυχώς: :count.',
'file_name_required' => 'Το πεδίο του Ονόματος του Αρχείου είναι υποχρεωτικό.', 'file_name_required' => 'Το πεδίο του Ονόματος του Αρχείου είναι υποχρεωτικό.',
], ],
'dashboard' => [
'active_theme' => [
'online' => 'ενεργό',
'maintenance' => 'σε συντήρηση',
]
],
'theme' => [ 'theme' => [
'not_found_name' => "Το θέμα ':name' δεν βρέθηκε.", 'not_found_name' => "Το θέμα ':name' δεν βρέθηκε.",
'active' => [ 'active' => [

View File

@ -13,6 +13,14 @@ return [
'file_name_required' => 'The File Name field is required.', 'file_name_required' => 'The File Name field is required.',
'safe_mode_enabled' => 'Safe mode is currently enabled.', 'safe_mode_enabled' => 'Safe mode is currently enabled.',
], ],
'dashboard' => [
'active_theme' => [
'widget_title_default' => 'Website',
'online' => 'Online',
'maintenance' => 'In maintenance',
'manage_themes' => 'Manage themes',
]
],
'theme' => [ 'theme' => [
'not_found_name' => "The theme ':name' is not found.", 'not_found_name' => "The theme ':name' is not found.",
'active' => [ 'active' => [

View File

@ -12,6 +12,12 @@ return [
'delete_success' => 'Los templates fueron borrados satisfactoriamente: :count.', 'delete_success' => 'Los templates fueron borrados satisfactoriamente: :count.',
'file_name_required' => 'Falta el nombre del campo del archivo.', 'file_name_required' => 'Falta el nombre del campo del archivo.',
], ],
'dashboard' => [
'active_theme' => [
'online' => 'en línea',
'maintenance' => 'en mantenimiento',
]
],
'theme' => [ 'theme' => [
'not_found_name' => "El tema ':name' no se ha encontrado.", 'not_found_name' => "El tema ':name' no se ha encontrado.",
'active' => [ 'active' => [

View File

@ -12,6 +12,12 @@ return [
'delete_success' => 'تعداد :count فایل با موفقیت حذف شد.', 'delete_success' => 'تعداد :count فایل با موفقیت حذف شد.',
'file_name_required' => 'نام فایل را وارد نمایید.' 'file_name_required' => 'نام فایل را وارد نمایید.'
], ],
'dashboard' => [
'active_theme' => [
'online' => 'online',
'maintenance' => 'در حال به روز رسانی',
]
],
'theme' => [ 'theme' => [
'not_found_name' => "یافتن قالبی با نام ':name یافت نشد.'", 'not_found_name' => "یافتن قالبی با نام ':name یافت نشد.'",
'active' => [ 'active' => [

View File

@ -13,6 +13,12 @@ return [
'file_name_required' => 'Le nom du fichier est requis.', 'file_name_required' => 'Le nom du fichier est requis.',
'safe_mode_enabled' => 'Le mode protégé est activé.', 'safe_mode_enabled' => 'Le mode protégé est activé.',
], ],
'dashboard' => [
'active_theme' => [
'online' => 'en ligne',
'maintenance' => 'en cours de maintenance',
]
],
'theme' => [ 'theme' => [
'not_found_name' => 'Le thème ":name" na pas été trouvé.', 'not_found_name' => 'Le thème ":name" na pas été trouvé.',
'active' => [ 'active' => [

View File

@ -13,6 +13,12 @@ return [
'file_name_required' => 'A Fájlnév mező kitöltése kötelező.', 'file_name_required' => 'A Fájlnév mező kitöltése kötelező.',
'safe_mode_enabled' => 'A biztonságos mód jelenleg engedélyezett.' 'safe_mode_enabled' => 'A biztonságos mód jelenleg engedélyezett.'
], ],
'dashboard' => [
'active_theme' => [
'online' => 'online',
'maintenance' => 'karbantartás',
]
],
'theme' => [ 'theme' => [
'not_found_name' => "A következő sablon nem található: ':name'", 'not_found_name' => "A következő sablon nem található: ':name'",
'active' => [ 'active' => [

View File

@ -12,6 +12,12 @@ return [
'delete_success' => 'Acuan: :count berhasil dihapus.', 'delete_success' => 'Acuan: :count berhasil dihapus.',
'file_name_required' => 'Bidang nama berkas diperlukan.' 'file_name_required' => 'Bidang nama berkas diperlukan.'
], ],
'dashboard' => [
'active_theme' => [
'online' => 'daring',
'maintenance' => 'dalam perawatan',
]
],
'theme' => [ 'theme' => [
'active' => [ 'active' => [
'not_set' => 'Tema aktif tidak diatur.', 'not_set' => 'Tema aktif tidak diatur.',

View File

@ -12,6 +12,12 @@ return [
'delete_success' => 'Template eliminati correttamente: :count.', 'delete_success' => 'Template eliminati correttamente: :count.',
'file_name_required' => 'Il campo Nome file è obbligatorio.' 'file_name_required' => 'Il campo Nome file è obbligatorio.'
], ],
'dashboard' => [
'active_theme' => [
'online' => 'online',
'maintenance' => 'in manutenzione',
]
],
'theme' => [ 'theme' => [
'not_found_name' => "Tema ':name' non trovato.", 'not_found_name' => "Tema ':name' non trovato.",
'active' => [ 'active' => [

View File

@ -12,6 +12,12 @@ return [
'delete_success' => ':count個のテンプレートを削除しました。', 'delete_success' => ':count個のテンプレートを削除しました。',
'file_name_required' => 'ファイル名フィールドが必要です。', 'file_name_required' => 'ファイル名フィールドが必要です。',
], ],
'dashboard' => [
'active_theme' => [
'online' => 'オンライン',
'maintenance' => 'メンテナンスモード',
]
],
'theme' => [ 'theme' => [
'active' => [ 'active' => [
'not_set' => "アクティブなテーマが設定されていません。", 'not_set' => "アクティブなテーマが設定されていません。",

View File

@ -12,6 +12,12 @@ return [
'delete_success' => 'Tika veiksmīgi izdzēstas veidnes: :count.', 'delete_success' => 'Tika veiksmīgi izdzēstas veidnes: :count.',
'file_name_required' => 'Faila nosaukuma lauks ir obligāts.' 'file_name_required' => 'Faila nosaukuma lauks ir obligāts.'
], ],
'dashboard' => [
'active_theme' => [
'online' => 'online',
'maintenance' => 'atkopšana',
]
],
'theme' => [ 'theme' => [
'not_found_name' => "Tēma ':name' netika atrasta.", 'not_found_name' => "Tēma ':name' netika atrasta.",
'active' => [ 'active' => [

View File

@ -12,6 +12,12 @@ return [
'delete_success' => 'Templates som ble slettet: :count.', 'delete_success' => 'Templates som ble slettet: :count.',
'file_name_required' => 'Filnavnfeltet er obligatorisk.' 'file_name_required' => 'Filnavnfeltet er obligatorisk.'
], ],
'dashboard' => [
'active_theme' => [
'online' => 'online',
'maintenance' => 'in maintenance',
]
],
'theme' => [ 'theme' => [
'not_found_name' => "Tema ':name' ble ikke funnet.", 'not_found_name' => "Tema ':name' ble ikke funnet.",
'active' => [ 'active' => [

View File

@ -12,6 +12,12 @@ return [
'delete_success' => 'Templates zijn succesvol verwijderd: :count.', 'delete_success' => 'Templates zijn succesvol verwijderd: :count.',
'file_name_required' => 'Het invullen van een bestandsnaam is verplicht.', 'file_name_required' => 'Het invullen van een bestandsnaam is verplicht.',
], ],
'dashboard' => [
'active_theme' => [
'online' => 'online',
'maintenance' => 'in onderhoud',
]
],
'theme' => [ 'theme' => [
'not_found_name' => 'Het thema \':name\' is niet gevonden.', 'not_found_name' => 'Het thema \':name\' is niet gevonden.',
'active' => [ 'active' => [

View File

@ -12,6 +12,12 @@ return [
'delete_success' => 'Szablony zostały prawidłowo usunięte: :count.', 'delete_success' => 'Szablony zostały prawidłowo usunięte: :count.',
'file_name_required' => 'Pole Nazwa Pliku jest wymagane.' 'file_name_required' => 'Pole Nazwa Pliku jest wymagane.'
], ],
'dashboard' => [
'active_theme' => [
'online' => 'online',
'maintenance' => 'w konserwacji',
]
],
'theme' => [ 'theme' => [
'not_found_name' => "Motyw ':name' nie został odnaleziony.", 'not_found_name' => "Motyw ':name' nie został odnaleziony.",
'active' => [ 'active' => [

View File

@ -12,6 +12,12 @@ return [
'delete_success' => 'Templates apagados com sucesso: :count.', 'delete_success' => 'Templates apagados com sucesso: :count.',
'file_name_required' => 'O campo de Nome do Arquivo é necessário.', 'file_name_required' => 'O campo de Nome do Arquivo é necessário.',
], ],
'dashboard' => [
'active_theme' => [
'online' => 'online',
'maintenance' => 'em manutenção',
]
],
'theme' => [ 'theme' => [
'not_found_name' => 'O tema ":name" não foi encontrado.', 'not_found_name' => 'O tema ":name" não foi encontrado.',
'active' => [ 'active' => [

View File

@ -12,6 +12,12 @@ return [
'delete_success' => 'Шаблоны были успешно удалены: :count.', 'delete_success' => 'Шаблоны были успешно удалены: :count.',
'file_name_required' => 'Пожалуйста, укажите имя файла шаблона.' 'file_name_required' => 'Пожалуйста, укажите имя файла шаблона.'
], ],
'dashboard' => [
'active_theme' => [
'online' => 'Онлайн',
'maintenance' => 'в разработке',
]
],
'theme' => [ 'theme' => [
'not_found_name' => "Тема ':name' не найдена.", 'not_found_name' => "Тема ':name' не найдена.",
'active' => [ 'active' => [

View File

@ -12,6 +12,12 @@ return [
'delete_success' => 'Mallarna är nu raderade: :count.', 'delete_success' => 'Mallarna är nu raderade: :count.',
'file_name_required' => 'Filnamnsfältet är obligatoriskt.' 'file_name_required' => 'Filnamnsfältet är obligatoriskt.'
], ],
'dashboard' => [
'active_theme' => [
'online' => 'online',
'maintenance' => 'i underhåll',
]
],
'theme' => [ 'theme' => [
'not_found_name' => "Kunde inte hitta temat ':name'.", 'not_found_name' => "Kunde inte hitta temat ':name'.",
'active' => [ 'active' => [

View File

@ -12,6 +12,12 @@ return [
'delete_success' => ':count şablon başarıyla silindi.', 'delete_success' => ':count şablon başarıyla silindi.',
'file_name_required' => 'Dosya adı alanı gereklidir.' 'file_name_required' => 'Dosya adı alanı gereklidir.'
], ],
'dashboard' => [
'active_theme' => [
'online' => 'yayında',
'maintenance' => 'bakım modunda',
]
],
'theme' => [ 'theme' => [
'not_found_name' => "':name' isimli tema bulunamadı.", 'not_found_name' => "':name' isimli tema bulunamadı.",
'active' => [ 'active' => [

View File

@ -12,6 +12,12 @@ return [
'delete_success' => '模板成功删除: :count.', 'delete_success' => '模板成功删除: :count.',
'file_name_required' => '需要文件名字段.' 'file_name_required' => '需要文件名字段.'
], ],
'dashboard' => [
'active_theme' => [
'online' => '在线',
'maintenance' => '维护中',
]
],
'theme' => [ 'theme' => [
'not_found_name' => "主题 ':name' 没找到.", 'not_found_name' => "主题 ':name' 没找到.",
'active' => [ 'active' => [

View File

@ -12,6 +12,12 @@ return [
'delete_success' => '模板成功刪除: :count.', 'delete_success' => '模板成功刪除: :count.',
'file_name_required' => '需要檔案名字串.' 'file_name_required' => '需要檔案名字串.'
], ],
'dashboard' => [
'active_theme' => [
'online' => '在線',
'maintenance' => '維護中',
]
],
'theme' => [ 'theme' => [
'not_found_name' => "主題 ':name' 沒找到.", 'not_found_name' => "主題 ':name' 沒找到.",
'active' => [ 'active' => [

View File

@ -0,0 +1,62 @@
<?php namespace Cms\ReportWidgets;
use Cms\Classes\Theme;
use Cms\Models\MaintenanceSetting;
use Backend\Classes\ReportWidgetBase;
use Exception;
/**
* Active theme report widget.
*
* @package october\backend
* @author Alexey Bobkov, Samuel Georges
*/
class ActiveTheme extends ReportWidgetBase
{
/**
* @var string A unique alias to identify this widget.
*/
protected $defaultAlias = 'activetheme';
/**
* Renders the widget.
*/
public function render()
{
try {
$this->loadData();
}
catch (Exception $ex) {
$this->vars['error'] = $ex->getMessage();
}
return $this->makePartial('widget');
}
public function defineProperties()
{
return [
'title' => [
'title' => 'backend::lang.dashboard.widget_title_label',
'default' => 'cms::lang.dashboard.active_theme.widget_title_default',
'type' => 'string',
'validationPattern' => '^.+$',
'validationMessage' => 'backend::lang.dashboard.widget_title_error',
]
];
}
/**
* {@inheritDoc}
*/
protected function loadAssets()
{
$this->addCss('css/activetheme.css', 'core');
}
protected function loadData()
{
$this->vars['theme'] = Theme::getActiveTheme();
$this->vars['inMaintenance'] = MaintenanceSetting::get('is_enabled');
}
}

View File

@ -0,0 +1,4 @@
.widget-activetheme .theme-thumbnail {
margin-top: -15px;
margin-bottom: 15px;
}

View File

@ -0,0 +1,33 @@
<div class="report-widget widget-activetheme">
<h3><?= e(trans($this->property('title'))) ?></h3>
<?php if (!isset($error)): ?>
<div class="theme-thumbnail">
<img src="<?= $theme->getPreviewImageUrl() ?>" alt="" class="img-responsive" />
</div>
<ul class="list-inline">
<li>
<a href="<?= Backend::url('system/settings/update/october/cms/maintenance_settings') ?>">
<?php if ($inMaintenance): ?>
<i class="icon-circle warning"></i>
<span class="text-warning">
<?= e(trans('cms::lang.dashboard.active_theme.maintenance')) ?>
</span>
<?php else: ?>
<i class="icon-circle success"></i>
<span class="text-success">
<?= e(trans('cms::lang.dashboard.active_theme.online')) ?>
</span>
<?php endif ?>
</a>
</li>
<li>
<a href="<?= Backend::url('cms/themes') ?>"><?= e(trans('cms::lang.dashboard.active_theme.manage_themes')) ?></a>
</li>
</ul>
<?php else: ?>
<div class="callout callout-warning">
<div class="content"><?= e($error) ?></div>
</div>
<?php endif ?>
</div>

View File

@ -309,7 +309,7 @@
li { li {
margin: 0; margin: 0;
padding: 7px 15px; padding: 7px 15px 6px;
list-style: none; list-style: none;
display: block; display: block;
font-size: @font-size-base - 1; font-size: @font-size-base - 1;
@ -322,6 +322,7 @@
a { a {
color: @color-status-list-text; color: @color-status-list-text;
text-decoration: none;
&:hover { &:hover {
color: @link-color; color: @link-color;
text-decoration: none; text-decoration: none;
@ -343,7 +344,6 @@
float: right; float: right;
display: inline-block; display: inline-block;
padding: 1px 5px; padding: 1px 5px;
font-size: @font-size-base;
.border-radius(@border-radius-base); .border-radius(@border-radius-base);
&:not(.link) { &:not(.link) {

View File

@ -30,10 +30,9 @@
padding: 10px 30px 10px 15px; padding: 10px 30px 10px 15px;
z-index: @zindex-flashmessage; z-index: @zindex-flashmessage;
word-wrap: break-word; word-wrap: break-word;
text-shadow: 0 -1px 0px rgba(0,0,0,.25); text-shadow: 0 -1px 0px rgba(0,0,0,.15);
text-align: center; text-align: center;
.box-shadow(inset 0 -2px 0 rgba(0,0,0,.1)); .box-shadow(@overlay-box-shadow);
.border-radius(@border-radius-base); .border-radius(@border-radius-base);
&.fade { &.fade {
@ -67,10 +66,11 @@
} }
&.static { &.static {
position: static!important; position: static !important;
width: auto!important; width: auto !important;
display: block!important; display: block !important;
margin-left: 0!important; margin-left: 0 !important;
.box-shadow(none);
} }
} }

View File

@ -1622,9 +1622,9 @@ to{background-position:0 0}
.report-container .title-value span.goal-meter-indicator{height:31px;top:4px;width:15px;margin-right:10px} .report-container .title-value span.goal-meter-indicator{height:31px;top:4px;width:15px;margin-right:10px}
.report-container .title-value span.goal-meter-indicator span{width:15px} .report-container .title-value span.goal-meter-indicator span{width:15px}
.control-status-list > ul{margin-bottom:0;padding:0} .control-status-list > ul{margin-bottom:0;padding:0}
.control-status-list > ul li{margin:0;padding:7px 15px;list-style:none;display:block;font-size:13px;color:#7e8c8d;border-bottom:1px solid #f0f0f0} .control-status-list > ul li{margin:0;padding:7px 15px 6px;list-style:none;display:block;font-size:13px;color:#7e8c8d;border-bottom:1px solid #f0f0f0}
.control-status-list > ul li:last-child{border-bottom:none} .control-status-list > ul li:last-child{border-bottom:none}
.control-status-list > ul li a{color:#7e8c8d} .control-status-list > ul li a{color:#7e8c8d;text-decoration:none}
.control-status-list > ul li a:hover{color:#0181b9;text-decoration:none} .control-status-list > ul li a:hover{color:#0181b9;text-decoration:none}
.control-status-list > ul li .status-text{margin:0 5px} .control-status-list > ul li .status-text{margin:0 5px}
.control-status-list > ul li .status-text.muted{color:#999999} .control-status-list > ul li .status-text.muted{color:#999999}
@ -1638,7 +1638,7 @@ a.control-status-list > ul li .status-text.info:hover{color:#245269}
a.control-status-list > ul li .status-text.warning:hover{color:#66512c} a.control-status-list > ul li .status-text.warning:hover{color:#66512c}
.control-status-list > ul li .status-text.danger{color:#a94442} .control-status-list > ul li .status-text.danger{color:#a94442}
a.control-status-list > ul li .status-text.danger:hover{color:#843534} a.control-status-list > ul li .status-text.danger:hover{color:#843534}
.control-status-list > ul li .status-label{float:right;display:inline-block;padding:1px 5px;font-size:14px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px} .control-status-list > ul li .status-label{float:right;display:inline-block;padding:1px 5px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}
.control-status-list > ul li .status-label:not(.link){color:white;letter-spacing:1px;font-family:monospace} .control-status-list > ul li .status-label:not(.link){color:white;letter-spacing:1px;font-family:monospace}
.control-status-list > ul li .status-icon{display:inline-block;text-align:center;color:white;width:22px;height:22px;line-height:22px;position:relative;top:-1px;-webkit-border-radius:100px;-moz-border-radius:100px;border-radius:100px} .control-status-list > ul li .status-icon{display:inline-block;text-align:center;color:white;width:22px;height:22px;line-height:22px;position:relative;top:-1px;-webkit-border-radius:100px;-moz-border-radius:100px;border-radius:100px}
.control-status-list > ul li .status-icon > i{font-size:10px} .control-status-list > ul li .status-icon > i{font-size:10px}
@ -1714,7 +1714,7 @@ div.scoreboard .control-chart .canvas + ul{margin-left:0}
div.scoreboard .scoreboard-offset{padding-left:20px} div.scoreboard .scoreboard-offset{padding-left:20px}
body.slim-container div.scoreboard{padding:0 20px} body.slim-container div.scoreboard{padding:0 20px}
#layout-canvas .flash-message{display:none} #layout-canvas .flash-message{display:none}
.flash-message{position:fixed;width:500px;left:50%;top:13px;margin-left:-250px;color:#ffffff;font-size:14px;padding:10px 30px 10px 15px;z-index:10300;word-wrap:break-word;text-shadow:0 -1px 0px rgba(0,0,0,0.25);text-align:center;-webkit-box-shadow:inset 0 -2px 0 rgba(0,0,0,0.1);box-shadow:inset 0 -2px 0 rgba(0,0,0,0.1);-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px} .flash-message{position:fixed;width:500px;left:50%;top:13px;margin-left:-250px;color:#ffffff;font-size:14px;padding:10px 30px 10px 15px;z-index:10300;word-wrap:break-word;text-shadow:0 -1px 0px rgba(0,0,0,0.15);text-align:center;-webkit-box-shadow:0 1px 6px rgba(0,0,0,0.12),0 1px 4px rgba(0,0,0,0.24);box-shadow:0 1px 6px rgba(0,0,0,0.12),0 1px 4px rgba(0,0,0,0.24);-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}
.flash-message.fade{opacity:0;filter:alpha(opacity=0);-webkit-transition:all 0.5s,width 0s;transition:all 0.5s,width 0s;-webkit-transform:scale(0.9);-ms-transform:scale(0.9);transform:scale(0.9)} .flash-message.fade{opacity:0;filter:alpha(opacity=0);-webkit-transition:all 0.5s,width 0s;transition:all 0.5s,width 0s;-webkit-transform:scale(0.9);-ms-transform:scale(0.9);transform:scale(0.9)}
.flash-message.fade.in{opacity:1;filter:alpha(opacity=100);-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)} .flash-message.fade.in{opacity:1;filter:alpha(opacity=100);-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}
.flash-message.success{background:#8da85e} .flash-message.success{background:#8da85e}
@ -1723,7 +1723,7 @@ body.slim-container div.scoreboard{padding:0 20px}
.flash-message.info{background:#5fb6f5} .flash-message.info{background:#5fb6f5}
.flash-message button{float:none;position:absolute;right:10px;top:8px;color:white;outline:none} .flash-message button{float:none;position:absolute;right:10px;top:8px;color:white;outline:none}
.flash-message button:hover{color:white} .flash-message button:hover{color:white}
.flash-message.static{position:static !important;width:auto !important;display:block !important;margin-left:0 !important} .flash-message.static{position:static !important;width:auto !important;display:block !important;margin-left:0 !important;-webkit-box-shadow:none;box-shadow:none}
@media (max-width:768px){.flash-message{left:10px;right:10px;top:10px;margin-left:0;width:auto} @media (max-width:768px){.flash-message{left:10px;right:10px;top:10px;margin-left:0;width:auto}
} }
[class^="flag-"],[class*=" flag-"]{background-image:url("images/flag-icons-small.png");width:16px;height:16px;line-height:16px;vertical-align:middle;display:inline-block;margin:-3px 2px 0 2px} [class^="flag-"],[class*=" flag-"]{background-image:url("images/flag-icons-small.png");width:16px;height:16px;line-height:16px;vertical-align:middle;display:inline-block;margin:-3px 2px 0 2px}

View File

@ -1,11 +1,13 @@
<?php namespace System\ReportWidgets; <?php namespace System\ReportWidgets;
use Lang;
use BackendAuth; use BackendAuth;
use System\Models\Parameters; use System\Models\Parameters;
use System\Classes\UpdateManager; use System\Classes\UpdateManager;
use Backend\Classes\ReportWidgetBase; use Backend\Classes\ReportWidgetBase;
use System\Models\EventLog; use System\Models\EventLog;
use System\Models\RequestLog; use System\Models\RequestLog;
use System\Models\PluginVersion;
use Exception; use Exception;
/** /**
@ -16,6 +18,11 @@ use Exception;
*/ */
class Status extends ReportWidgetBase class Status extends ReportWidgetBase
{ {
/**
* @var string A unique alias to identify this widget.
*/
protected $defaultAlias = 'status';
/** /**
* Renders the widget. * Renders the widget.
*/ */
@ -49,9 +56,54 @@ class Status extends ReportWidgetBase
$manager = UpdateManager::instance(); $manager = UpdateManager::instance();
$this->vars['canUpdate'] = BackendAuth::getUser()->hasAccess('system.manage_updates'); $this->vars['canUpdate'] = BackendAuth::getUser()->hasAccess('system.manage_updates');
$this->vars['updates'] = $manager->check(); $this->vars['updates'] = $manager->check();
$this->vars['warnings'] = false; $this->vars['warnings'] = $this->getSystemWarnings();
$this->vars['coreBuild'] = Parameters::get('system::core.build'); $this->vars['coreBuild'] = Parameters::get('system::core.build');
$this->vars['eventLog'] = EventLog::count(); $this->vars['eventLog'] = EventLog::count();
$this->vars['requestLog'] = RequestLog::count(); $this->vars['requestLog'] = RequestLog::count();
$this->vars['appBirthday'] = PluginVersion::orderBy('created_at')->pluck('created_at');
}
public function onLoadWarningsForm()
{
$this->vars['warnings'] = $this->getSystemWarnings();
return $this->makePartial('warnings_form');
}
protected function getSystemWarnings()
{
$warnings = [];
$writablePaths = [
temp_path(),
themes_path(),
storage_path(),
storage_path('app'),
storage_path('logs'),
storage_path('framework'),
storage_path('cms'),
storage_path('cms/cache'),
storage_path('cms/twig'),
storage_path('cms/combiner'),
];
$requiredExtensions = [
'GD' => extension_loaded('gd'),
'fileinfo' => extension_loaded('fileinfo'),
'Zip' => class_exists('ZipArchive'),
'cURL' => function_exists('curl_init') && defined('CURLOPT_FOLLOWLOCATION'),
'OpenSSL' => function_exists('openssl_random_pseudo_bytes'),
];
foreach ($writablePaths as $path) {
if (!is_writable($path)) {
$warnings[] = Lang::get('backend::lang.warnings.permissions', ['name' => '<strong>'.$path.'</strong>']);
}
}
foreach ($requiredExtensions as $extension => $installed) {
if (!$installed) {
$warnings[] = Lang::get('backend::lang.warnings.extension', ['name' => '<strong>'.$extension.'</strong>']);
}
}
return $warnings;
} }
} }

View File

@ -0,0 +1,24 @@
<div class="modal-header">
<button type="button" class="close" data-dismiss="popup" aria-hidden="true">&times;</button>
<h4 class="modal-title"><?= e(trans('backend::lang.warnings.tips')) ?></h4>
</div>
<div class="modal-body">
<?php if (count($warnings)): ?>
<p><?= e(trans('backend::lang.warnings.tips_description')) ?></p>
<ul>
<?php foreach ($warnings as $warning): ?>
<li><?= $warning ?></li>
<?php endforeach ?>
</ul>
<?php else: ?>
<p>No warnings to display</p>
<?php endif ?>
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-default"
data-dismiss="popup">
<?= e(trans('backend::lang.form.close')) ?>
</button>
</div>

View File

@ -7,52 +7,75 @@
<li> <li>
<?php if ($updates): ?> <?php if ($updates): ?>
<span class="status-icon warning"><i class="icon-exclamation"></i></span> <span class="status-icon warning"><i class="icon-exclamation"></i></span>
<span class="status-text warning">Pending software updates</span> <span class="status-text warning">
<?= e(trans('backend::lang.dashboard.status.updates_pending')) ?>
</span>
<?php if ($canUpdate): ?> <?php if ($canUpdate): ?>
<a href="<?= Backend::url('system/updates') ?>" class="status-label link">Update</a> <a href="<?= Backend::url('system/updates') ?>" class="status-label link"><?= e(trans('backend::lang.dashboard.status.updates_link')) ?></a>
<?php endif ?> <?php endif ?>
<?php else: ?> <?php else: ?>
<span class="status-icon success"><i class="icon-check"></i></span> <span class="status-icon success"><i class="icon-check"></i></span>
<span class="status-text success">Software is up to date</span> <span class="status-text success">
<?= e(trans('backend::lang.dashboard.status.updates_nil')) ?>
</span>
<?php endif ?> <?php endif ?>
</li> </li>
<li> <li>
<?php if ($warnings): ?> <?php if ($warnings): ?>
<span class="status-icon warning"><i class="icon-exclamation"></i></span> <span class="status-icon warning"><i class="icon-exclamation"></i></span>
<span class="status-text warning">Some issues need attention</span> <span class="status-text warning">
<a href="#todo" class="status-label link">View</a> <?= e(trans('backend::lang.dashboard.status.warnings_pending')) ?>
</span>
<a
href="javascript:;"
data-control="popup"
data-size="large"
data-handler="<?= $this->getEventHandler('onLoadWarningsForm') ?>"
class="status-label link"><?= e(trans('backend::lang.dashboard.status.warnings_link')) ?></a>
<?php else: ?> <?php else: ?>
<span class="status-icon success"><i class="icon-check"></i></span> <span class="status-icon success"><i class="icon-check"></i></span>
<span class="status-text success">No warnings to display</span> <span class="status-text success">
<?= e(trans('backend::lang.dashboard.status.warnings_nil')) ?>
</span>
<?php endif ?> <?php endif ?>
</li> </li>
<?php if ($coreBuild): ?> <?php if ($coreBuild): ?>
<li> <li>
<span class="status-icon"><i class="icon-info"></i></span> <span class="status-icon"><i class="icon-info"></i></span>
<span class="status-text">System build</span> <span class="status-text">
<span class="status-label primary"><?= $coreBuild ?></span> <?= e(trans('backend::lang.dashboard.status.core_build')) ?>
</span>
<a href="<?= Backend::url('system/updates') ?>" class="status-label primary"><?= $coreBuild ?></a>
</li> </li>
<?php endif ?> <?php endif ?>
<li> <li>
<span class="status-icon"><i class="icon-info"></i></span> <span class="status-icon"><i class="icon-info"></i></span>
<span class="status-text">Event log items</span> <span class="status-text">
<span class="status-label primary"><?= $eventLog ?></span> <?= e(trans('backend::lang.dashboard.status.event_log')) ?>
</span>
<a href="<?= Backend::url('system/eventlogs') ?>" class="status-label primary"><?= $eventLog ?></a>
</li> </li>
<li> <li>
<span class="status-icon"><i class="icon-info"></i></span> <span class="status-icon"><i class="icon-info"></i></span>
<span class="status-text">Request log items</span> <span class="status-text">
<span class="status-label primary"><?= $requestLog ?></span> <?= e(trans('backend::lang.dashboard.status.request_log')) ?>
</span>
<a href="<?= Backend::url('system/requestlogs') ?>" class="status-label primary"><?= $requestLog ?></a>
</li> </li>
<!-- <?php if ($appBirthday): ?>
<li> <li>
<span class="status-icon"><i class="icon-info"></i></span> <span class="status-icon"><i class="icon-info"></i></span>
<span class="status-text">Online since</span> <span class="status-text">
<span class="status-label link">4th April 2014</span> <?= e(trans('backend::lang.dashboard.status.app_birthday')) ?>
</li> </span>
--> <span class="status-label link"><?= Backend::dateTime($appBirthday, ['formatAlias' => 'dateLong']) ?></span>
</li>
<?php endif ?>
</ul> </ul>
</div> </div>
<?php else: ?> <?php else: ?>
<p class="flash-message static warning"><?= e($error) ?></p> <div class="callout callout-warning">
<div class="content"><?= e($error) ?></div>
</div>
<?php endif ?> <?php endif ?>
</div> </div>