Merge pull request #449 from cachethq/metrics

Add metrics
This commit is contained in:
Joe Cohen
2015-02-22 15:53:24 -06:00
32 changed files with 606 additions and 45 deletions
@@ -18,6 +18,7 @@ class CreateMetricsTable extends Migration
$table->string('name');
$table->string('suffix');
$table->text('description');
$table->integer('default_value');
$table->boolean('display_chart')->default(1);
$table->timestamps();
+5
View File
@@ -70,6 +70,11 @@ return [
'success' => 'Metrik-Punkt angelegt.',
'failure' => 'Es ist ein Fehler bei der Erstellung eines Metrik-Punktes aufgetreten.',
],
'edit' => [
'title' => 'Edit a metric',
'success' => 'Metric updated.',
'failure' => 'Something went wrong with the metric.',
],
],
// Team
+14
View File
@@ -51,6 +51,19 @@ return [
],
],
// Metric form fields
'metrics' => [
'name' => 'Name',
'suffix' => 'Suffix',
'description' => 'Description',
'description-help' => 'You may also use Markdown.',
'display-chart' => 'Display chart on status page?',
'points' => [
'value' => 'Value',
],
],
// Settings
'settings' => [
/// Application setup
@@ -60,6 +73,7 @@ return [
'site-timezone' => 'Wählen Sie Ihre Zeitzone',
'site-locale' => 'Wählen Sie Ihre Sprache',
'date-format' => 'Datumsformat',
'display-graphs' => 'Display graphs on status page?',
'about-this-page' => 'Über diese Seite',
'days-of-incidents' => 'Wie viele (vergangene) Tage sollen angezeigt werden?',
'banner' => 'Banner-Bild',
+9
View File
@@ -37,6 +37,15 @@ return [
'revoke' => 'Revoke API Key',
],
// Metrics
'metrics' => [
'filter' => [
'hourly' => 'Hourly',
'daily' => 'Daily',
'monthly' => 'Monthly',
],
],
// Other
'powered_by' => ':app Status Page is powered by <a href="https://cachethq.io">Cachet</a>.',
'about_this_site' => 'About this site',
+8 -3
View File
@@ -73,9 +73,14 @@ return [
'metrics' => [
'metrics' => 'Metrics',
'add' => [
'title' => 'Create a metric point',
'success' => 'Metric point created.',
'failure' => 'Something went wrong with the metric point.',
'title' => 'Create a metric',
'success' => 'Metric created.',
'failure' => 'Something went wrong with the metric.',
],
'edit' => [
'title' => 'Edit a metric',
'success' => 'Metric updated.',
'failure' => 'Something went wrong with the metric.',
],
],
+15
View File
@@ -52,6 +52,20 @@ return [
],
],
// 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',
'points' => [
'value' => 'Value',
],
],
// Settings
'settings' => [
/// Application setup
@@ -61,6 +75,7 @@ return [
'site-timezone' => 'Site Timezone',
'site-locale' => 'Site Language',
'date-format' => 'Date Format',
'display-graphs' => 'Display graphs on status page?',
'about-this-page' => 'About this page',
'days-of-incidents' => 'How many days of incidents to show?',
'banner' => 'Banner Image',
+14
View File
@@ -52,6 +52,19 @@ return [
],
],
// Metric form fields
'metrics' => [
'name' => 'Nombre',
'suffix' => 'Sufijo',
'description' => 'Descripción',
'description-help' => 'Puedes usar también Markdown.',
'display-chart' => '¿Vizualizar gráfica en la página de estado?',
'points' => [
'value' => 'Valor',
],
],
// Settings
'settings' => [
/// Application setup
@@ -61,6 +74,7 @@ return [
'site-timezone' => 'Zona horaria del sitio',
'site-locale' => 'Idioma del sitio',
'date-format' => 'Formato de la fecha',
'display-graphs' => '¿Visualizar gráficas en la página de estado?',
'about-this-page' => 'Sobre esta página',
'days-of-incidents' => '¿Cuántos días de incidentes mostrar?',
'banner' => 'Imagen de inicio',
+5
View File
@@ -76,6 +76,11 @@ return [
'success' => 'Point de mesure créé.',
'failure' => 'Il s\'est passé quelque chose avec ce point de mesure.',
],
'edit' => [
'title' => 'Edit a metric',
'success' => 'Metric updated.',
'failure' => 'Something went wrong with the metric.',
],
],
// Team
+14
View File
@@ -51,6 +51,19 @@ return [
],
],
// Metric form fields
'metrics' => [
'name' => 'Name',
'suffix' => 'Suffix',
'description' => 'Description',
'description-help' => 'You may also use Markdown.',
'display-chart' => 'Display chart on status page?',
'points' => [
'value' => 'Value',
],
],
// Settings
'settings' => [
/// Application setup
@@ -60,6 +73,7 @@ return [
'site-timezone' => 'Fuseau horaire du site',
'site-locale' => 'Langue du site',
'date-format' => 'Format de date',
'display-graphs' => 'Display graphs on status page?',
'about-this-page' => 'À propos de cette page',
'days-of-incidents' => 'Nombre de jours à afficher ?',
'banner' => 'Bannière',
+10 -1
View File
@@ -77,8 +77,17 @@ Route::group(['before' => 'auth', 'prefix' => 'dashboard', 'namespace' => 'Cache
Route::group(['prefix' => 'metrics'], function () {
Route::get('/', [
'as' => 'dashboard.metrics',
'uses' => 'DashboardController@showMetrics',
'uses' => 'DashMetricController@showMetrics',
]);
Route::get('add', [
'as' => 'dashboard.metrics.add',
'uses' => 'DashMetricController@showAddMetric',
]);
Route::post('add', 'DashMetricController@createMetricAction');
Route::delete('{metric}/delete', 'DashMetricController@deleteMetricAction');
Route::get('{metric}/edit', 'DashMetricController@showEditMetricAction');
Route::post('{metric}/edit', 'DashMetricController@editMetricAction');
});
// Notifications
+1 -1
View File
@@ -6,7 +6,7 @@
<i class="icon ion-navicon"></i>
</div>
<span class="uppercase">
<i class="icon icon ion-android-alert"></i> {{ trans('dashboard.incidents.incidents') }}
<i class="icon ion-android-alert"></i> {{ trans('dashboard.incidents.incidents') }}
</span>
&gt; <small>{{ trans('dashboard.incidents.add.title') }}</small>
</div>
+1 -1
View File
@@ -6,7 +6,7 @@
<i class="icon ion-navicon"></i>
</div>
<span class="uppercase">
<i class="icon icon ion-android-alert"></i> {{ trans('dashboard.incidents.incidents') }}
<i class="icon ion-android-alert"></i> {{ trans('dashboard.incidents.incidents') }}
</span>
&gt; <small>{{ trans('dashboard.incidents.edit.title') }}</small>
</div>
@@ -6,7 +6,7 @@
<i class="icon ion-navicon"></i>
</div>
<span class="uppercase">
<i class="icon icon ion-android-alert"></i> {{ trans('dashboard.incidents.incidents') }}
<i class="icon ion-android-alert"></i> {{ trans('dashboard.incidents.incidents') }}
</span>
<a class="btn btn-sm btn-success pull-right" href="{{ route('dashboard.incidents.add') }}">
{{ trans('dashboard.incidents.add.title') }}
+54
View File
@@ -0,0 +1,54 @@
@extends('layout.dashboard')
@section('content')
<div class="header">
<div class="sidebar-toggler visible-xs">
<i class="icon ion-navicon"></i>
</div>
<span class="uppercase">
<i class="icon ion-stats-bars"></i> {{ trans('dashboard.metrics.metrics') }}
</span>
> <small>{{ trans('dashboard.metrics.add.title') }}</small>
</div>
<div class="content-wrapper">
<div class="row">
<div class="col-md-12">
@include('partials.dashboard.errors')
<form class='form-vertical' name='MetricsForm' role='form' method='POST'>
{{ Form::token() }}
<fieldset>
<div class="form-group">
<label for="metric-name">{{ trans('forms.metrics.name') }}</label>
<input type="text" class="form-control" name="metric[name]" id="metric-name" required value="{{ Input::old('metric.name') }}">
</div>
<div class="form-group">
<label for="metric-suffix">{{ trans('forms.metrics.suffix') }}</label>
<input type="text" class="form-control" name="metric[suffix]" id="metric-suffix" required value="{{ Input::old('metric.suffix') }}">
</div>
<div class="form-group">
<label>{{ trans('forms.metrics.description') }}</label>
<div class='markdown-control'>
<textarea name="metric[description]" class="form-control" rows="5" required>{{ Input::old('metric.description') }}</textarea>
</div>
</div>
<div class="form-group">
<label for="metric-default_value">{{ trans('forms.metrics.default-value') }}</label>
<input type="number" class="form-control" name="metric[default_value]" id="metric-default_value" value="{{ Input::old('metric.default_value') }}">
</div>
<div class="form-group">
<label>{{ trans('forms.metrics.display-chart') }}</label>
<input type="hidden" value="0" name="metric[display_chart]">
<input type="checkbox" value="1" name="metric[display_chart]" class="form-control" {{ Input::old('display_chart') ? 'checked' : null }}>
</div>
</fieldset>
<div class='form-group'>
<div class='btn-group'>
<button type="submit" class="btn btn-success">{{ trans('forms.add') }}</button>
<a class="btn btn-default" href="{{ route('dashboard.metrics') }}">{{ trans('forms.cancel') }}</a>
</div>
</div>
</form>
</div>
</div>
</div>
@stop
@@ -0,0 +1,57 @@
@extends('layout.dashboard')
@section('content')
<div class="header">
<div class="sidebar-toggler visible-xs">
<i class="icon ion-navicon"></i>
</div>
<span class="uppercase">
<i class="icon icon ion-android-alert"></i> {{ trans('dashboard.metrics.metrics') }}
</span>
> <small>{{ trans('dashboard.metrics.edit.title') }}</small>
</div>
<div class="content-wrapper">
<div class="row">
<div class="col-md-12">
@include('partials.dashboard.errors')
<form class='form-vertical' name='MetricsForm' role='form' method='POST'>
{{ Form::token() }}
<fieldset>
<div class="form-group">
<label for="metric-name">{{ trans('forms.metrics.name') }}</label>
<input type="text" class="form-control" name="metric[name]" id="metric-name" required value={{ $metric->name }}>
</div>
<div class="form-group">
<label for="metric-suffix">{{ trans('forms.metrics.suffix') }}</label>
<input type="text" class="form-control" name="metric[suffix]" id="metric-suffix" required value="{{ $metric->suffix }}">
</div>
<div class="form-group">
<label>{{ trans('forms.metrics.description') }}</label>
<div class='markdown-control'>
<textarea name="metric[description]" class="form-control" rows="5" required>{{ $metric->description }}</textarea>
</div>
</div>
<div class="form-group">
<label for="metric-default_value">{{ trans('forms.metrics.default-value') }}</label>
<input type="number" class="form-control" name="metric[default_value]" id="metric-default_value" value="{{ $metric->default_value }}">
</div>
<div class="form-group">
<label>{{ trans('forms.metrics.display-chart') }}</label>
<input type="hidden" value="0" name="metric[display_chart]">
<input type="checkbox" value="1" name="metric[display_chart]" class="form-control" {{ $metric->display_chart ? 'checked' : null }}>
</div>
</fieldset>
<input type="hidden" name="metric[id]" value={{$metric->id}}>
<div class='form-group'>
<div class='btn-group'>
<button type="submit" class="btn btn-success">{{ trans('forms.update') }}</button>
<a class="btn btn-default" href="{{ route('dashboard.metrics') }}">{{ trans('forms.cancel') }}</a>
</div>
</div>
</form>
</div>
</div>
</div>
@stop
+29 -6
View File
@@ -1,16 +1,39 @@
@extends('layout.dashboard')
@section('content')
<div class="header">
<div class="header fixed">
<div class="sidebar-toggler visible-xs">
<i class="icon ion-navicon"></i>
</div>
<i class="ion ion-stats-bars"></i> {{ trans('dashboard.metrics.metrics') }}
<span class="uppercase">
<i class="icon ion-stats-bars"></i> {{ trans('dashboard.metrics.metrics') }}
</span>
<a class="btn btn-sm btn-success pull-right" href="{{ route('dashboard.metrics.add') }}">
{{ trans('dashboard.metrics.add.title') }}
</a>
<div class="clearfix"></div>
</div>
<div class="row">
<div class="col-sm-12">
<h3>{{ trans('dashboard.metrics.metrics') }}</h3>
<p class="lead">Eventually this page will show all of the graphs that make up your metrics.</p>
<div class="content-wrapper header-fixed">
<div class="row">
<div class="col-sm-12">
@include('partials.dashboard.errors')
<div class="striped-list">
@foreach($metrics as $metric)
<div class="row striped-list-item">
<div class="col-md-6">
<i class="{{ $metric->icon }}"></i> <strong>{{ $metric->name }}</strong>
@if($metric->description)
<p><small>{{ Str::words($metric->description, 5) }}</small></p>
@endif
</div>
<div class="col-md-6 text-right">
<a href="/dashboard/metrics/{{ $metric->id }}/edit" class="btn btn-default">{{ trans('forms.edit') }}</a>
<a href="/dashboard/metrics/{{ $metric->id }}/delete" class="btn btn-danger confirm-action" data-method='DELETE'>{{ trans('forms.delete') }}</a>
</div>
</div>
@endforeach
</div>
</div>
</div>
</div>
@stop
@@ -104,6 +104,15 @@
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<label>{{ trans('forms.settings.app-setup.display-graphs') }}</label>
<input type="hidden" value="0" name="display_graphs">
<input type="checkbox" value="1" name="display_graphs" class="form-control" {{ Setting::get('display_graphs') ? 'checked' : null }}>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="form-group">
+4 -4
View File
@@ -21,13 +21,13 @@
@include('partials.components')
{{-- @if(Setting::get('display_graphs'))
@include('partials.graphs')
@endif --}}
@if($displayMetrics && Setting::get('display_graphs'))
@include('partials.graphs')
@endif
<h1>{{ trans('cachet.incidents.past') }}</h1>
@foreach($allIncidents as $incidents)
@include('partials.incidents', $incidents)
@include('partials.incidents', $incidents)
@endforeach
<hr>
@@ -55,12 +55,13 @@
<span>{{ trans('dashboard.team.team') }}</span>
</a>
</li>
{{-- <li {{ set_active('dashboard/metrics') }}>
<li {{ set_active('dashboard/metrics*') }}>
<a href="{{ route('dashboard.metrics') }}">
<i class="ion ion-stats-bats"></i> {{ trans('cachet.dashboard.metrics') }}
<i class="icon ion-stats-bars"></i>
<span>{{ trans('dashboard.metrics.metrics') }}</span>
</a>
</li>
<li {{ set_active('dashboard/notifications') }}>
{{-- <li {{ set_active('dashboard/notifications') }}>
<a href="{{ route('dashboard.notifications') }}">
<i class="ion ion-email"></i> {{ trans('cachet.dashboard.notifications') }}
</a>
+69
View File
@@ -0,0 +1,69 @@
@if($metrics->count() > 0)
<ul class="list-group metrics">
@foreach($metrics as $metric)
<?php
$points = range(0, 10);
foreach($points as $hour) {
$points[$hour] = $metric->getValues($hour);
}
$points = array_reverse($points);
?>
<li class="list-group-item metric">
<div class="row">
<div class="col-xs-10">
<h4>
{{ $metric->name }}
@if($metric->description)
<i class="ion ion-ios-help-outline" data-toggle="tooltip" data-title="{{ $metric->description }}"></i>
@endif
</h4>
</div>
<div class="col-xs-2 text-right">
<small>{{ trans('cachet.metrics.filter.hourly') }}</small>
</div>
</div>
<hr>
<div class="row">
<div class="col-md-12">
<div>
<canvas id="metric-{{ $metric->id }}" height="150" width="600"></canvas>
</div>
</div>
</div>
<script>
var hourList = [];
var date = new Date();
for (var i = 10; i >= 1; i--) {
hourList.push(moment(date).subtract(i, 'hours').seconds(0).format('HH:ss'));
}
hourList.push(moment(date).seconds(0).format('HH:ss'));
var data = {
showTooltips: false,
labels: hourList,
datasets: [{
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: [{{ implode(',', $points) }}]
}]
};
window.onload = function() {
var ctx = document.getElementById("metric-{{ $metric->id }}").getContext("2d");
window.myLine = new Chart(ctx).Line(data, {
scaleShowVerticalLines: true,
pointDot: false,
responsive: true
});
};
</script>
</li>
@endforeach
</ul>
@endif