Metrics: Added configured locales and themes, refactoring/formatting
This commit is contained in:
parent
4d8e568ff8
commit
e2e2ac0c68
|
@ -70,17 +70,17 @@ return [
|
||||||
'available_themes' => [
|
'available_themes' => [
|
||||||
'12' => 'Engelsystem 36c3 (2019)',
|
'12' => 'Engelsystem 36c3 (2019)',
|
||||||
'10' => 'Engelsystem cccamp19 green (2019)',
|
'10' => 'Engelsystem cccamp19 green (2019)',
|
||||||
'9' => 'Engelsystem cccamp19 yellow (2019)',
|
'9' => 'Engelsystem cccamp19 yellow (2019)',
|
||||||
'8' => 'Engelsystem cccamp19 blue (2019)',
|
'8' => 'Engelsystem cccamp19 blue (2019)',
|
||||||
'7' => 'Engelsystem 35c3 dark (2018)',
|
'7' => 'Engelsystem 35c3 dark (2018)',
|
||||||
'6' => 'Engelsystem 34c3 dark (2017)',
|
'6' => 'Engelsystem 34c3 dark (2017)',
|
||||||
'5' => 'Engelsystem 34c3 light (2017)',
|
'5' => 'Engelsystem 34c3 light (2017)',
|
||||||
'4' => 'Engelsystem 33c3 (2016)',
|
'4' => 'Engelsystem 33c3 (2016)',
|
||||||
'3' => 'Engelsystem 32c3 (2015)',
|
'3' => 'Engelsystem 32c3 (2015)',
|
||||||
'2' => 'Engelsystem cccamp15',
|
'2' => 'Engelsystem cccamp15',
|
||||||
'11' => 'Engelsystem high contrast',
|
'11' => 'Engelsystem high contrast',
|
||||||
'0' => 'Engelsystem light',
|
'0' => 'Engelsystem light',
|
||||||
'1' => 'Engelsystem dark',
|
'1' => 'Engelsystem dark',
|
||||||
],
|
],
|
||||||
|
|
||||||
// Redirect to this site after logging in or when pressing the top-left button
|
// Redirect to this site after logging in or when pressing the top-left button
|
||||||
|
@ -152,7 +152,7 @@ return [
|
||||||
'voucher_start' => null,
|
'voucher_start' => null,
|
||||||
],
|
],
|
||||||
|
|
||||||
// Available locales in /locale/
|
// Available locales in /resources/lang/
|
||||||
'locales' => [
|
'locales' => [
|
||||||
'de_DE' => 'Deutsch',
|
'de_DE' => 'Deutsch',
|
||||||
'en_US' => 'English',
|
'en_US' => 'English',
|
||||||
|
|
|
@ -8,6 +8,7 @@ use Engelsystem\Helpers\Version;
|
||||||
use Engelsystem\Http\Exceptions\HttpForbidden;
|
use Engelsystem\Http\Exceptions\HttpForbidden;
|
||||||
use Engelsystem\Http\Request;
|
use Engelsystem\Http\Request;
|
||||||
use Engelsystem\Http\Response;
|
use Engelsystem\Http\Response;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
use Psr\Log\LogLevel;
|
use Psr\Log\LogLevel;
|
||||||
|
|
||||||
class Controller extends BaseController
|
class Controller extends BaseController
|
||||||
|
@ -62,16 +63,9 @@ class Controller extends BaseController
|
||||||
$now = microtime(true);
|
$now = microtime(true);
|
||||||
$this->checkAuth();
|
$this->checkAuth();
|
||||||
|
|
||||||
$tshirtSizes = [];
|
$userTshirtSizes = $this->formatStats($this->stats->tshirtSizes(), 'tshirt_sizes', 'shirt_size', 'size');
|
||||||
$userSizes = $this->stats->tshirtSizes();
|
$userLocales = $this->formatStats($this->stats->languages(), 'locales', 'language', 'locale');
|
||||||
|
$userThemes = $this->formatStats($this->stats->themes(), 'available_themes', 'theme');
|
||||||
foreach ($this->config->get('tshirt_sizes') as $name => $description) {
|
|
||||||
$size = $userSizes->where('shirt_size', '=', $name)->sum('count');
|
|
||||||
$tshirtSizes[] = [
|
|
||||||
'labels' => ['size' => $name],
|
|
||||||
$size,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
$this->config->get('app_name') . ' stats',
|
$this->config->get('app_name') . ' stats',
|
||||||
|
@ -117,7 +111,12 @@ class Controller extends BaseController
|
||||||
'worklog_seconds' => ['type' => 'gauge', $this->stats->worklogSeconds()],
|
'worklog_seconds' => ['type' => 'gauge', $this->stats->worklogSeconds()],
|
||||||
'vouchers' => ['type' => 'counter', $this->stats->vouchers()],
|
'vouchers' => ['type' => 'counter', $this->stats->vouchers()],
|
||||||
'tshirts_issued' => ['type' => 'counter', 'help' => 'Issued T-Shirts', $this->stats->tshirts()],
|
'tshirts_issued' => ['type' => 'counter', 'help' => 'Issued T-Shirts', $this->stats->tshirts()],
|
||||||
'tshirt_sizes' => ['type' => 'gauge', 'help' => 'The sizes users have configured'] + $tshirtSizes,
|
'tshirt_sizes' => [
|
||||||
|
'type' => 'gauge',
|
||||||
|
'help' => 'The sizes users have configured'
|
||||||
|
] + $userTshirtSizes,
|
||||||
|
'locales' => ['type' => 'gauge', 'help' => 'The locales users have configured'] + $userLocales,
|
||||||
|
'themes' => ['type' => 'gauge', 'help' => 'The themes users have configured'] + $userThemes,
|
||||||
'shifts' => ['type' => 'gauge', $this->stats->shifts()],
|
'shifts' => ['type' => 'gauge', $this->stats->shifts()],
|
||||||
'announcements' => [
|
'announcements' => [
|
||||||
'type' => 'gauge',
|
'type' => 'gauge',
|
||||||
|
@ -212,4 +211,27 @@ class Controller extends BaseController
|
||||||
|
|
||||||
throw new HttpForbidden($message, $headers);
|
throw new HttpForbidden($message, $headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats the stats collection as stats data
|
||||||
|
*
|
||||||
|
* @param Collection $data
|
||||||
|
* @param string $config
|
||||||
|
* @param string $dataField
|
||||||
|
* @param string|null $label
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function formatStats(Collection $data, string $config, string $dataField, ?string $label = null): array
|
||||||
|
{
|
||||||
|
$return = [];
|
||||||
|
foreach ($this->config->get($config) as $name => $description) {
|
||||||
|
$count = $data->where($dataField, '=', $name)->sum('count');
|
||||||
|
$return[] = [
|
||||||
|
'labels' => [($label ?: $dataField) => $name],
|
||||||
|
$count,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,10 @@ use Engelsystem\Models\Message;
|
||||||
use Engelsystem\Models\News;
|
use Engelsystem\Models\News;
|
||||||
use Engelsystem\Models\Question;
|
use Engelsystem\Models\Question;
|
||||||
use Engelsystem\Models\User\PasswordReset;
|
use Engelsystem\Models\User\PasswordReset;
|
||||||
|
use Engelsystem\Models\User\PersonalData;
|
||||||
|
use Engelsystem\Models\User\Settings;
|
||||||
use Engelsystem\Models\User\State;
|
use Engelsystem\Models\User\State;
|
||||||
|
use Engelsystem\Models\User\User;
|
||||||
use Illuminate\Database\Query\Builder as QueryBuilder;
|
use Illuminate\Database\Query\Builder as QueryBuilder;
|
||||||
use Illuminate\Database\Query\Expression as QueryExpression;
|
use Illuminate\Database\Query\Expression as QueryExpression;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
@ -94,8 +97,7 @@ class Stats
|
||||||
*/
|
*/
|
||||||
public function currentlyWorkingUsers(bool $freeloaded = null): int
|
public function currentlyWorkingUsers(bool $freeloaded = null): int
|
||||||
{
|
{
|
||||||
$query = $this
|
$query = User::query()
|
||||||
->getQuery('users')
|
|
||||||
->join('ShiftEntry', 'ShiftEntry.UID', '=', 'users.id')
|
->join('ShiftEntry', 'ShiftEntry.UID', '=', 'users.id')
|
||||||
->join('Shifts', 'Shifts.SID', '=', 'ShiftEntry.SID')
|
->join('Shifts', 'Shifts.SID', '=', 'ShiftEntry.SID')
|
||||||
->where('Shifts.start', '<=', time())
|
->where('Shifts.start', '<=', time())
|
||||||
|
@ -129,11 +131,32 @@ class Stats
|
||||||
*/
|
*/
|
||||||
public function tshirtSizes(): Collection
|
public function tshirtSizes(): Collection
|
||||||
{
|
{
|
||||||
return $this
|
return PersonalData::query()
|
||||||
->getQuery('users_personal_data')
|
|
||||||
->select(['shirt_size', $this->raw('COUNT(shirt_size) AS count')])
|
->select(['shirt_size', $this->raw('COUNT(shirt_size) AS count')])
|
||||||
->whereNotNull('shirt_size')
|
->whereNotNull('shirt_size')
|
||||||
->groupBy('shirt_size')
|
->groupBy(['shirt_size'])
|
||||||
|
->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function languages(): Collection
|
||||||
|
{
|
||||||
|
return Settings::query()
|
||||||
|
->select(['language', $this->raw('COUNT(language) AS count')])
|
||||||
|
->groupBy(['language'])
|
||||||
|
->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function themes(): Collection
|
||||||
|
{
|
||||||
|
return Settings::query()
|
||||||
|
->select(['theme', $this->raw('COUNT(theme) AS count')])
|
||||||
|
->groupBy(['theme'])
|
||||||
->get();
|
->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace Engelsystem\Test\Unit\Controllers\Metrics;
|
namespace Engelsystem\Test\Unit\Controllers\Metrics;
|
||||||
|
|
||||||
|
use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts;
|
||||||
use Engelsystem\Config\Config;
|
use Engelsystem\Config\Config;
|
||||||
use Engelsystem\Controllers\Metrics\Controller;
|
use Engelsystem\Controllers\Metrics\Controller;
|
||||||
use Engelsystem\Controllers\Metrics\MetricsEngine;
|
use Engelsystem\Controllers\Metrics\MetricsEngine;
|
||||||
|
@ -18,9 +19,12 @@ use Symfony\Component\HttpFoundation\ServerBag;
|
||||||
|
|
||||||
class ControllerTest extends TestCase
|
class ControllerTest extends TestCase
|
||||||
{
|
{
|
||||||
|
use ArraySubsetAsserts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers \Engelsystem\Controllers\Metrics\Controller::__construct
|
* @covers \Engelsystem\Controllers\Metrics\Controller::__construct
|
||||||
* @covers \Engelsystem\Controllers\Metrics\Controller::metrics
|
* @covers \Engelsystem\Controllers\Metrics\Controller::metrics
|
||||||
|
* @covers \Engelsystem\Controllers\Metrics\Controller::formatStats
|
||||||
*/
|
*/
|
||||||
public function testMetrics()
|
public function testMetrics()
|
||||||
{
|
{
|
||||||
|
@ -48,6 +52,8 @@ class ControllerTest extends TestCase
|
||||||
$this->assertArrayHasKey('vouchers', $data);
|
$this->assertArrayHasKey('vouchers', $data);
|
||||||
$this->assertArrayHasKey('tshirts_issued', $data);
|
$this->assertArrayHasKey('tshirts_issued', $data);
|
||||||
$this->assertArrayHasKey('tshirt_sizes', $data);
|
$this->assertArrayHasKey('tshirt_sizes', $data);
|
||||||
|
$this->assertArrayHasKey('locales', $data);
|
||||||
|
$this->assertArrayHasKey('themes', $data);
|
||||||
$this->assertArrayHasKey('shifts', $data);
|
$this->assertArrayHasKey('shifts', $data);
|
||||||
$this->assertArrayHasKey('announcements', $data);
|
$this->assertArrayHasKey('announcements', $data);
|
||||||
$this->assertArrayHasKey('questions', $data);
|
$this->assertArrayHasKey('questions', $data);
|
||||||
|
@ -59,6 +65,12 @@ class ControllerTest extends TestCase
|
||||||
$this->assertArrayHasKey('log_entries', $data);
|
$this->assertArrayHasKey('log_entries', $data);
|
||||||
$this->assertArrayHasKey('scrape_duration_seconds', $data);
|
$this->assertArrayHasKey('scrape_duration_seconds', $data);
|
||||||
|
|
||||||
|
$this->assertArraySubset(['tshirt_sizes' => [
|
||||||
|
'type' => 'gauge',
|
||||||
|
['labels' => ['size' => 'L'], 2],
|
||||||
|
['labels' => ['size' => 'XL'], 0]
|
||||||
|
]], $data);
|
||||||
|
|
||||||
return 'metrics return';
|
return 'metrics return';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -113,7 +125,13 @@ class ControllerTest extends TestCase
|
||||||
$this->setExpects($stats, 'vouchers', null, 17);
|
$this->setExpects($stats, 'vouchers', null, 17);
|
||||||
$this->setExpects($stats, 'tshirts', null, 3);
|
$this->setExpects($stats, 'tshirts', null, 3);
|
||||||
$this->setExpects($stats, 'tshirtSizes', null, new Collection([
|
$this->setExpects($stats, 'tshirtSizes', null, new Collection([
|
||||||
(object)['shirt_size' => 'L', 'count' => 2],
|
['shirt_size' => 'L', 'count' => 2],
|
||||||
|
]));
|
||||||
|
$this->setExpects($stats, 'languages', null, new Collection([
|
||||||
|
['language' => 'en_US', 'count' => 5],
|
||||||
|
]));
|
||||||
|
$this->setExpects($stats, 'themes', null, new Collection([
|
||||||
|
['theme' => '1', 'count' => 3],
|
||||||
]));
|
]));
|
||||||
$this->setExpects($stats, 'shifts', null, 142);
|
$this->setExpects($stats, 'shifts', null, 142);
|
||||||
$this->setExpects($stats, 'messages', null, 3);
|
$this->setExpects($stats, 'messages', null, 3);
|
||||||
|
@ -125,6 +143,14 @@ class ControllerTest extends TestCase
|
||||||
'L' => 'Large',
|
'L' => 'Large',
|
||||||
'XL' => 'X Large',
|
'XL' => 'X Large',
|
||||||
]);
|
]);
|
||||||
|
$config->set('locales', [
|
||||||
|
'de_DE' => 'German',
|
||||||
|
'en_US' => 'US English',
|
||||||
|
]);
|
||||||
|
$config->set('available_themes', [
|
||||||
|
'0' => 'Nothing',
|
||||||
|
'1' => 'Testing',
|
||||||
|
]);
|
||||||
|
|
||||||
$this->setExpects($version, 'getVersion', [], '0.42.42');
|
$this->setExpects($version, 'getVersion', [], '0.42.42');
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ use Engelsystem\Models\News;
|
||||||
use Engelsystem\Models\Question;
|
use Engelsystem\Models\Question;
|
||||||
use Engelsystem\Models\User\PasswordReset;
|
use Engelsystem\Models\User\PasswordReset;
|
||||||
use Engelsystem\Models\User\PersonalData;
|
use Engelsystem\Models\User\PersonalData;
|
||||||
|
use Engelsystem\Models\User\Settings;
|
||||||
use Engelsystem\Models\User\State;
|
use Engelsystem\Models\User\State;
|
||||||
use Engelsystem\Models\User\User;
|
use Engelsystem\Models\User\User;
|
||||||
use Engelsystem\Test\Unit\HasDatabase;
|
use Engelsystem\Test\Unit\HasDatabase;
|
||||||
|
@ -58,7 +59,6 @@ class StatsTest extends TestCase
|
||||||
/**
|
/**
|
||||||
* @covers \Engelsystem\Controllers\Metrics\Stats::tshirtSizes
|
* @covers \Engelsystem\Controllers\Metrics\Stats::tshirtSizes
|
||||||
* @covers \Engelsystem\Controllers\Metrics\Stats::raw
|
* @covers \Engelsystem\Controllers\Metrics\Stats::raw
|
||||||
* @covers \Engelsystem\Controllers\Metrics\Stats::getQuery
|
|
||||||
*/
|
*/
|
||||||
public function testTshirtSizes()
|
public function testTshirtSizes()
|
||||||
{
|
{
|
||||||
|
@ -68,11 +68,44 @@ class StatsTest extends TestCase
|
||||||
$sizes = $stats->tshirtSizes();
|
$sizes = $stats->tshirtSizes();
|
||||||
$this->assertCount(2, $sizes);
|
$this->assertCount(2, $sizes);
|
||||||
$this->assertEquals([
|
$this->assertEquals([
|
||||||
(object)['shirt_size' => 'L', 'count' => 2],
|
['shirt_size' => 'L', 'count' => 2],
|
||||||
(object)['shirt_size' => 'XXL', 'count' => 1],
|
['shirt_size' => 'XXL', 'count' => 1],
|
||||||
], $sizes->toArray());
|
], $sizes->toArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \Engelsystem\Controllers\Metrics\Stats::languages
|
||||||
|
*/
|
||||||
|
public function testLanguages()
|
||||||
|
{
|
||||||
|
$this->addUsers();
|
||||||
|
|
||||||
|
$stats = new Stats($this->database);
|
||||||
|
$languages = $stats->languages();
|
||||||
|
$this->assertCount(2, $languages);
|
||||||
|
$this->assertEquals([
|
||||||
|
['language' => 'lo_RM', 'count' => 2],
|
||||||
|
['language' => 'te_ST', 'count' => 7],
|
||||||
|
], $languages->toArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \Engelsystem\Controllers\Metrics\Stats::themes
|
||||||
|
*/
|
||||||
|
public function testThemes()
|
||||||
|
{
|
||||||
|
$this->addUsers();
|
||||||
|
|
||||||
|
$stats = new Stats($this->database);
|
||||||
|
$themes = $stats->themes();
|
||||||
|
$this->assertCount(3, $themes);
|
||||||
|
$this->assertEquals([
|
||||||
|
['theme' => 0, 'count' => 7],
|
||||||
|
['theme' => 1, 'count' => 1],
|
||||||
|
['theme' => 4, 'count' => 1],
|
||||||
|
], $themes->toArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers \Engelsystem\Controllers\Metrics\Stats::announcements
|
* @covers \Engelsystem\Controllers\Metrics\Stats::announcements
|
||||||
|
@ -118,7 +151,7 @@ class StatsTest extends TestCase
|
||||||
$this->addUsers();
|
$this->addUsers();
|
||||||
|
|
||||||
$stats = new Stats($this->database);
|
$stats = new Stats($this->database);
|
||||||
$this->assertEquals(6, $stats->arrivedUsers());
|
$this->assertEquals(7, $stats->arrivedUsers());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -149,6 +182,7 @@ class StatsTest extends TestCase
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers \Engelsystem\Controllers\Metrics\Stats::sessions
|
* @covers \Engelsystem\Controllers\Metrics\Stats::sessions
|
||||||
|
* @covers \Engelsystem\Controllers\Metrics\Stats::getQuery
|
||||||
*/
|
*/
|
||||||
public function testSessions()
|
public function testSessions()
|
||||||
{
|
{
|
||||||
|
@ -223,18 +257,20 @@ class StatsTest extends TestCase
|
||||||
$this->addUser();
|
$this->addUser();
|
||||||
$this->addUser([], ['shirt_size' => 'L']);
|
$this->addUser([], ['shirt_size' => 'L']);
|
||||||
$this->addUser(['arrived' => 1]);
|
$this->addUser(['arrived' => 1]);
|
||||||
$this->addUser(['arrived' => 1, 'got_voucher' => 2], ['shirt_size' => 'XXL']);
|
$this->addUser(['arrived' => 1], [], ['language' => 'lo_RM']);
|
||||||
$this->addUser(['arrived' => 1, 'got_voucher' => 9]);
|
$this->addUser(['arrived' => 1, 'got_voucher' => 2], ['shirt_size' => 'XXL'], ['language' => 'lo_RM']);
|
||||||
$this->addUser(['arrived' => 1, 'got_voucher' => 3, 'force_active' => true]);
|
$this->addUser(['arrived' => 1, 'got_voucher' => 9, 'force_active' => true], [], ['theme' => 1]);
|
||||||
|
$this->addUser(['arrived' => 1, 'got_voucher' => 3], ['theme' => 10]);
|
||||||
$this->addUser(['arrived' => 1, 'active' => 1, 'got_shirt' => true, 'force_active' => true]);
|
$this->addUser(['arrived' => 1, 'active' => 1, 'got_shirt' => true, 'force_active' => true]);
|
||||||
$this->addUser(['arrived' => 1, 'active' => 1, 'got_shirt' => true], ['shirt_size' => 'L']);
|
$this->addUser(['arrived' => 1, 'active' => 1, 'got_shirt' => true], ['shirt_size' => 'L'], ['theme' => 4]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array $state
|
* @param array $state
|
||||||
* @param array $personalData
|
* @param array $personalData
|
||||||
|
* @param array $settings
|
||||||
*/
|
*/
|
||||||
protected function addUser(array $state = [], $personalData = [])
|
protected function addUser(array $state = [], $personalData = [], $settings = [])
|
||||||
{
|
{
|
||||||
$name = 'user_' . Str::random(5);
|
$name = 'user_' . Str::random(5);
|
||||||
|
|
||||||
|
@ -255,6 +291,16 @@ class StatsTest extends TestCase
|
||||||
$personalData->user()
|
$personalData->user()
|
||||||
->associate($user)
|
->associate($user)
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
|
$settings = new Settings(array_merge([
|
||||||
|
'language' => 'te_ST',
|
||||||
|
'theme' => 0,
|
||||||
|
'email_human' => '',
|
||||||
|
'email_shiftinfo' => '',
|
||||||
|
], $settings));
|
||||||
|
$settings->user()
|
||||||
|
->associate($user)
|
||||||
|
->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue