added project detail report (#2651)
- avatars via css only - random colors for entities - improves print view - added colors for teams - added color to tag
This commit is contained in:
@@ -1,170 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Utils;
|
||||
|
||||
use App\Entity\User;
|
||||
use Laravolt\Avatar\Avatar;
|
||||
use Laravolt\Avatar\Generator\DefaultGenerator;
|
||||
|
||||
class AvatarService
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $directory;
|
||||
|
||||
public const AVATAR_CONFIG = [
|
||||
'driver' => 'gd',
|
||||
'generator' => DefaultGenerator::class,
|
||||
'ascii' => true,
|
||||
'shape' => 'circle',
|
||||
'width' => 100,
|
||||
'height' => 100,
|
||||
'chars' => 2,
|
||||
'fontSize' => 44,
|
||||
'fontFamily' => null,
|
||||
'uppercase' => true,
|
||||
//'fonts' => ['path/to/OpenSans-Bold.ttf', 'path/to/rockwell.ttf'],
|
||||
'foregrounds' => [
|
||||
'#FFFFFF'
|
||||
],
|
||||
'backgrounds' => [
|
||||
'#f44336',
|
||||
'#E91E63',
|
||||
'#9C27B0',
|
||||
'#673AB7',
|
||||
'#3F51B5',
|
||||
'#2196F3',
|
||||
'#03A9F4',
|
||||
'#00BCD4',
|
||||
'#009688',
|
||||
'#4CAF50',
|
||||
'#8BC34A',
|
||||
'#CDDC39',
|
||||
'#FFC107',
|
||||
'#FF9800',
|
||||
'#FF5722',
|
||||
],
|
||||
'border' => [
|
||||
'size' => 1,
|
||||
'color' => 'background'
|
||||
],
|
||||
'theme' => '*',
|
||||
'themes' => [
|
||||
/*
|
||||
'grayscale-light' => [
|
||||
'backgrounds' => ['#edf2f7', '#e2e8f0', '#cbd5e0'],
|
||||
'foregrounds' => ['#a0aec0'],
|
||||
],
|
||||
'grayscale-dark' => [
|
||||
'backgrounds' => ['#2d3748', '#4a5568', '#718096'],
|
||||
'foregrounds' => ['#e2e8f0'],
|
||||
],
|
||||
*/
|
||||
'colorful' => [
|
||||
'backgrounds' => [
|
||||
'#a972c9',
|
||||
'#9C27B0',
|
||||
'#673AB7',
|
||||
'#5319e7',
|
||||
'#041fd1',
|
||||
'#3F51B5',
|
||||
'#2196F3',
|
||||
'#03A9F4',
|
||||
'#00BCD4',
|
||||
'#006b75',
|
||||
'#009688',
|
||||
'#00bb32',
|
||||
'#4CAF50',
|
||||
'#8BC34A',
|
||||
'#CDDC39',
|
||||
'#FFC107',
|
||||
'#FF9800',
|
||||
'#FF5722',
|
||||
'#f41a00',
|
||||
'#E91E63',
|
||||
'#b60205',
|
||||
'#cc317c',
|
||||
'#d82d80',
|
||||
'#e135f4',
|
||||
'#2d3748',
|
||||
'#4a5568',
|
||||
'#718096',
|
||||
],
|
||||
'foregrounds' => ['#FFFFFF'],
|
||||
],
|
||||
]
|
||||
];
|
||||
|
||||
public function __construct(string $projectDirectory)
|
||||
{
|
||||
$this->setStorageDirectory($projectDirectory . '/public/avatars/');
|
||||
}
|
||||
|
||||
public function getStorageDirectory(): string
|
||||
{
|
||||
return $this->directory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @CloudRequired
|
||||
*/
|
||||
public function setStorageDirectory(string $directory)
|
||||
{
|
||||
$this->directory = realpath($directory);
|
||||
}
|
||||
|
||||
private function getAvatarUrl(User $profile): string
|
||||
{
|
||||
return md5($profile->getId() . '_' . $profile->getDisplayName()) . '.png';
|
||||
}
|
||||
|
||||
private function getImagePath(User $profile): string
|
||||
{
|
||||
return $this->getStorageDirectory() . '/' . $this->getAvatarUrl($profile);
|
||||
}
|
||||
|
||||
public function generateAvatar(User $profile, bool $regenerate = false): bool
|
||||
{
|
||||
if (!$this->hasDependencies()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$filePath = $this->getImagePath($profile);
|
||||
|
||||
if ($regenerate || !file_exists($filePath)) {
|
||||
if (!is_writable(\dirname($filePath))) {
|
||||
return false;
|
||||
}
|
||||
$avatar = new Avatar(self::AVATAR_CONFIG);
|
||||
$avatar->create($profile->getDisplayName())->save($filePath, 90);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getAvatar(User $profile): ?string
|
||||
{
|
||||
if (!empty(trim($profile->getAvatar()))) {
|
||||
return $profile->getAvatar();
|
||||
}
|
||||
|
||||
if (!$this->generateAvatar($profile)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->getAvatarUrl($profile);
|
||||
}
|
||||
|
||||
public function hasDependencies(): bool
|
||||
{
|
||||
return \extension_loaded('gd') && \function_exists('imagettfbbox');
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,13 @@ use App\Entity\Timesheet;
|
||||
|
||||
final class Color
|
||||
{
|
||||
// @see https://clrs.cc
|
||||
public const PALETTE_1 = ['#0074D9', '#7FDBFF', '#39CCCC', '#B10DC9', '#F012BE', '#85144b', '#FF4136', '#FF851B', '#FFDC00', '#3D9970', '#2ECC40', '#01FF70', '#AAAAAA', '#DDDDDD'];
|
||||
// old avatar color set
|
||||
public const PALETTE_2 = ['#a972c9', '#9C27B0', '#673AB7', '#5319e7', '#041fd1', '#3F51B5', '#2196F3', '#03A9F4', '#00BCD4', '#006b75', '#009688', '#00bb32', '#4CAF50', '#8BC34A', '#CDDC39', '#FFC107', '#FF9800', '#FF5722', '#f41a00', '#E91E63', '#b60205', '#cc317c', '#d82d80', '#e135f4', '#2d3748', '#4a5568', '#718096'];
|
||||
// all mixed together
|
||||
public const PALETTE_3 = ['#AAAAAA', '#DDDDDD', '#a972c9', '#9C27B0', '#673AB7', '#041fd1', '#5319e7', '#3F51B5', '#0074D9', '#2196F3', '#03A9F4', '#7FDBFF', '#39CCCC', '#00BCD4', '#006b75', '#009688', '#00bb32', '#4CAF50', '#3D9970', '#2ECC40', '#01FF70', '#8BC34A', '#CDDC39', '#FFDC00', '#FFC107', '#FF851B', '#FF9800', '#FF5722', '#f41a00', '#E91E63', '#85144b', '#b60205', '#FF4136', '#cc317c', '#F012BE', '#d82d80', '#B10DC9', '#e135f4', '#2d3748', '#4a5568', '#718096'];
|
||||
|
||||
public function getTimesheetColor(Timesheet $timesheet): string
|
||||
{
|
||||
$activity = $timesheet->getActivity();
|
||||
@@ -76,6 +83,33 @@ final class Color
|
||||
return $defaultColor ? Constants::DEFAULT_COLOR : null;
|
||||
}
|
||||
|
||||
public function getRandom(?string $input = null): string
|
||||
{
|
||||
if ($input === null) {
|
||||
return $this->getRandomColor();
|
||||
}
|
||||
|
||||
return $this->getRandomFromPalette($input);
|
||||
}
|
||||
|
||||
public function getRandomColor(): string
|
||||
{
|
||||
return sprintf('#%06x', rand(0, 16777215));
|
||||
}
|
||||
|
||||
public function getRandomFromPalette(string $input): string
|
||||
{
|
||||
$id = 0;
|
||||
for ($pos = 0; $pos < \strlen($input); $pos++) {
|
||||
$id += mb_ord($input[$pos], 'UTF-8');
|
||||
}
|
||||
|
||||
$colors = self::PALETTE_3;
|
||||
$key = $id % \count($colors);
|
||||
|
||||
return $colors[$key];
|
||||
}
|
||||
|
||||
public function getFontContrastColor(string $color): string
|
||||
{
|
||||
if (empty($color) || $color[0] !== '#') {
|
||||
|
||||
Reference in New Issue
Block a user