first draft

This commit is contained in:
Kevin Papst
2016-10-20 22:10:41 +02:00
parent 94a35ff914
commit 579b962c85
186 changed files with 30734 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
<?php
/*
* This file is part of the Kimai package.
*
* (c) Kevin Papst <kevin@kevinpapst.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Controller;
use TimesheetBundle\Entity\Timesheet;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
/**
* Controller used to manage timesheet contents in the public part of the site.
*
* @Route("/timesheet")
* @Security("has_role('ROLE_CUSTOMER')")
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
class TimesheetController extends Controller
{
/**
* @Route("/", defaults={"page": 1}, name="timesheet")
* @Route("/timesheet/{page}", requirements={"page": "[1-9]\d*"}, name="timesheet_paginated")
* @Method("GET")
* @Cache(smaxage="10")
*/
public function indexAction($page)
{
$entries = $this->getDoctrine()->getRepository(Timesheet::class)->findLatest($page);
return $this->render('TimesheetBundle:timesheet:index.html.twig', ['entries' => $entries]);
}
}

View File

@@ -0,0 +1,105 @@
<?php
/*
* This file is part of the Kimai package.
*
* (c) Kevin Papst <kevin@kevinpapst.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace TimesheetBundle\DataFixtures\ORM;
use AppBundle\Entity\User;
use TimesheetBundle\Entity\Timesheet;
use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use AppBundle\DataFixtures\ORM\LoadFixtures as AppBundleLoadFixtures;
/**
* Defines the sample data to load in the database when running the unit and
* functional tests. Execute this command to load the data:
*
* $ php bin/console doctrine:fixtures:load
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
class LoadFixtures extends AppBundleLoadFixtures
{
const AMOUNT_ACTIVITIES = 20;
const AMOUNT_TIMESHEET = 1000;
const AMOUNT_PROJECTS = 10;
const AMOUNT_CUSTOMER = 10;
/**
* {@inheritdoc}
*/
public function load(ObjectManager $manager)
{
$this->loadTimesheet($manager);
}
private function loadTimesheet(ObjectManager $manager)
{
$amountUsers = count($manager->getRepository(User::class)->findAll());
for ($i = 0; $i <= self::AMOUNT_TIMESHEET; $i++) {
$start = new \DateTime();
$start = $start->modify('- ' . (rand(1, 400)) . ' days');
$start = $start->modify('- ' . (rand(1, 86400)) . ' seconds');
$end = clone $start;
$end = $end->modify('+ '.(rand(1, 43200)).' seconds');
$entry = new Timesheet();
$entry->setProjectid(rand(1, self::AMOUNT_PROJECTS));
$entry->setActivityid(rand(1, self::AMOUNT_ACTIVITIES));
$entry->setStatusid(1); // TODO
$entry->setBillable(true);
$entry->setBudget(0);
$entry->setCleared(false);
$entry->setComment($this->getRandomPhrase());
$entry->setDescription($this->getRandomPhrase());
$entry->setLocation($this->getRandomLocation());
$entry->setStart($start->getTimestamp());
$entry->setEnd($end->getTimestamp());
$entry->setDuration($end->modify('- ' . $start->getTimestamp() . ' seconds')->getTimestamp());
$entry->setUserid(rand(1, $amountUsers));
//$entry->setApproved(false); // TODO
//$entry->setFixedrate(); // TODO
//$entry->setRate(); // TODO
//$entry->setTrackingnumber(); // TODO
$manager->persist($entry);
}
$manager->flush();
}
private function getLocations()
{
return [
'Köln',
'München',
'New York',
'Buenos Aires',
'Hawai',
'Amsterdam',
'London',
'San Francisco',
'Tokio',
'Berlin',
'Sao Paulo',
'Mexico City',
];
}
private function getRandomLocation()
{
$titles = $this->getLocations();
return $titles[array_rand($titles)];
}
}

View File

@@ -0,0 +1,604 @@
<?php
/*
* This file is part of the Kimai package.
*
* (c) Kevin Papst <kevin@kevinpapst.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Timesheet entity.
*
* @ORM\Entity(repositoryClass="TimesheetBundle\Repository\TimesheetRepository")
* @ORM\Table(name="timeSheet", indexes={@ORM\Index(name="userID", columns={"userID"}), @ORM\Index(name="projectID", columns={"projectID"}), @ORM\Index(name="activityID", columns={"activityID"})})
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
class Timesheet
{
/**
* @var integer
*
* @ORM\Column(name="start", type="integer", nullable=false)
*/
private $start = '0';
/**
* @var integer
*
* @ORM\Column(name="end", type="integer", nullable=false)
*/
private $end = '0';
/**
* @var integer
*
* @ORM\Column(name="duration", type="integer", nullable=false)
*/
private $duration = '0';
/**
* @var integer
*
* @ORM\Column(name="userID", type="integer", nullable=false)
*/
private $userid;
/**
* @var integer
*
* @ORM\Column(name="projectID", type="integer", nullable=false)
*/
private $projectid;
/**
* @var integer
*
* @ORM\Column(name="activityID", type="integer", nullable=false)
*/
private $activityid;
/**
* @var string
*
* @ORM\Column(name="description", type="text", length=65535, nullable=true)
*/
private $description;
/**
* @var string
*
* @ORM\Column(name="comment", type="text", length=65535, nullable=true)
*/
private $comment;
/**
* @var boolean
*
* @ORM\Column(name="commentType", type="boolean", nullable=false)
*/
private $commenttype = '0';
/**
* @var boolean
*
* @ORM\Column(name="cleared", type="boolean", nullable=false)
*/
private $cleared = '0';
/**
* @var string
*
* @ORM\Column(name="location", type="string", length=50, nullable=true)
*/
private $location;
/**
* @var string
*
* @ORM\Column(name="trackingNumber", type="string", length=30, nullable=true)
*/
private $trackingnumber;
/**
* @var string
*
* @ORM\Column(name="rate", type="decimal", precision=10, scale=2, nullable=false)
*/
private $rate = '0.00';
/**
* @var string
*
* @ORM\Column(name="fixedRate", type="decimal", precision=10, scale=2, nullable=false)
*/
private $fixedrate = '0.00';
/**
* @var string
*
* @ORM\Column(name="budget", type="decimal", precision=10, scale=2, nullable=true)
*/
private $budget;
/**
* @var string
*
* @ORM\Column(name="approved", type="decimal", precision=10, scale=2, nullable=true)
*/
private $approved;
/**
* @var integer
*
* @ORM\Column(name="statusID", type="smallint", nullable=false)
*/
private $statusid;
/**
* @var boolean
*
* @ORM\Column(name="billable", type="boolean", nullable=true)
*/
private $billable;
/**
* @var integer
*
* @ORM\Column(name="timeEntryID", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $timeentryid;
/**
* Set start
*
* @param integer $start
*
* @return KimaiTimesheet
*/
public function setStart($start)
{
$this->start = $start;
return $this;
}
/**
* Get start
*
* @return integer
*/
public function getStart()
{
return $this->start;
}
/**
* Set end
*
* @param integer $end
*
* @return KimaiTimesheet
*/
public function setEnd($end)
{
$this->end = $end;
return $this;
}
/**
* Get end
*
* @return integer
*/
public function getEnd()
{
return $this->end;
}
/**
* Set duration
*
* @param integer $duration
*
* @return KimaiTimesheet
*/
public function setDuration($duration)
{
$this->duration = $duration;
return $this;
}
/**
* Get duration
*
* @return integer
*/
public function getDuration()
{
return $this->duration;
}
/**
* Set userid
*
* @param integer $userid
*
* @return KimaiTimesheet
*/
public function setUserid($userid)
{
$this->userid = $userid;
return $this;
}
/**
* Get userid
*
* @return integer
*/
public function getUserid()
{
return $this->userid;
}
/**
* Set projectid
*
* @param integer $projectid
*
* @return KimaiTimesheet
*/
public function setProjectid($projectid)
{
$this->projectid = $projectid;
return $this;
}
/**
* Get projectid
*
* @return integer
*/
public function getProjectid()
{
return $this->projectid;
}
/**
* Set activityid
*
* @param integer $activityid
*
* @return KimaiTimesheet
*/
public function setActivityid($activityid)
{
$this->activityid = $activityid;
return $this;
}
/**
* Get activityid
*
* @return integer
*/
public function getActivityid()
{
return $this->activityid;
}
/**
* Set description
*
* @param string $description
*
* @return KimaiTimesheet
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set comment
*
* @param string $comment
*
* @return KimaiTimesheet
*/
public function setComment($comment)
{
$this->comment = $comment;
return $this;
}
/**
* Get comment
*
* @return string
*/
public function getComment()
{
return $this->comment;
}
/**
* Set commenttype
*
* @param boolean $commenttype
*
* @return KimaiTimesheet
*/
public function setCommenttype($commenttype)
{
$this->commenttype = $commenttype;
return $this;
}
/**
* Get commenttype
*
* @return boolean
*/
public function getCommenttype()
{
return $this->commenttype;
}
/**
* Set cleared
*
* @param boolean $cleared
*
* @return KimaiTimesheet
*/
public function setCleared($cleared)
{
$this->cleared = $cleared;
return $this;
}
/**
* Get cleared
*
* @return boolean
*/
public function getCleared()
{
return $this->cleared;
}
/**
* Set location
*
* @param string $location
*
* @return KimaiTimesheet
*/
public function setLocation($location)
{
$this->location = $location;
return $this;
}
/**
* Get location
*
* @return string
*/
public function getLocation()
{
return $this->location;
}
/**
* Set trackingnumber
*
* @param string $trackingnumber
*
* @return KimaiTimesheet
*/
public function setTrackingnumber($trackingnumber)
{
$this->trackingnumber = $trackingnumber;
return $this;
}
/**
* Get trackingnumber
*
* @return string
*/
public function getTrackingnumber()
{
return $this->trackingnumber;
}
/**
* Set rate
*
* @param string $rate
*
* @return KimaiTimesheet
*/
public function setRate($rate)
{
$this->rate = $rate;
return $this;
}
/**
* Get rate
*
* @return string
*/
public function getRate()
{
return $this->rate;
}
/**
* Set fixedrate
*
* @param string $fixedrate
*
* @return KimaiTimesheet
*/
public function setFixedrate($fixedrate)
{
$this->fixedrate = $fixedrate;
return $this;
}
/**
* Get fixedrate
*
* @return string
*/
public function getFixedrate()
{
return $this->fixedrate;
}
/**
* Set budget
*
* @param string $budget
*
* @return KimaiTimesheet
*/
public function setBudget($budget)
{
$this->budget = $budget;
return $this;
}
/**
* Get budget
*
* @return string
*/
public function getBudget()
{
return $this->budget;
}
/**
* Set approved
*
* @param string $approved
*
* @return KimaiTimesheet
*/
public function setApproved($approved)
{
$this->approved = $approved;
return $this;
}
/**
* Get approved
*
* @return string
*/
public function getApproved()
{
return $this->approved;
}
/**
* Set statusid
*
* @param integer $statusid
*
* @return KimaiTimesheet
*/
public function setStatusid($statusid)
{
$this->statusid = $statusid;
return $this;
}
/**
* Get statusid
*
* @return integer
*/
public function getStatusid()
{
return $this->statusid;
}
/**
* Set billable
*
* @param boolean $billable
*
* @return KimaiTimesheet
*/
public function setBillable($billable)
{
$this->billable = $billable;
return $this;
}
/**
* Get billable
*
* @return boolean
*/
public function getBillable()
{
return $this->billable;
}
/**
* Get timeentryid
*
* @return integer
*/
public function getTimeentryid()
{
return $this->timeentryid;
}
}

View File

@@ -0,0 +1,47 @@
<?php
/*
* This file is part of the Kimai package.
*
* (c) Kevin Papst <kevin@kevinpapst.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace TimesheetBundle\EventListener;
use AppBundle\Event\ConfigureMainMenuEvent;
use AppBundle\Event\ConfigureAdminMenuEvent;
/**
* Class Menu
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
class Menu
{
/**
* @param \AppBundle\Event\ConfigureMainMenuEvent $event
*/
public function onMainMenuConfigure(ConfigureMainMenuEvent $event)
{
$menu = $event->getMenu();
$item = $menu->addChild('Timesheet', array('route' => 'timesheet'));
$item->setLabel('menu.timesheet');
$item->setChildrenAttribute('icon', 'clock-o');
}
/**
* @param \AppBundle\Event\ConfigureAdminMenuEvent $event
*/
public function onAdminMenuConfigure(ConfigureAdminMenuEvent $event)
{
$menu = $event->getMenu();
$item = $menu->addChild('TimeAdmin', array('route' => 'timesheet'));
//$item->setLabel('menu.admin_timesheet');
$item->setChildrenAttribute('icon', 'clock-o');
}
}

View File

@@ -0,0 +1,54 @@
<?php
/*
* This file is part of the Kimai package.
*
* (c) Kevin Papst <kevin@kevinpapst.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Repository;
use TimesheetBundle\Entity\Timesheet;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query;
use Pagerfanta\Adapter\DoctrineORMAdapter;
use Pagerfanta\Pagerfanta;
/**
* Class TimesheetRepository
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
class TimesheetRepository extends EntityRepository
{
/**
* @return Query
*/
public function queryLatest()
{
return $this->getEntityManager()
->createQuery('
SELECT p
FROM TimesheetBundle:Timesheet p
ORDER BY p.start DESC
');
}
/**
* @param int $page
*
* @return Pagerfanta
*/
public function findLatest($page = 1)
{
$paginator = new Pagerfanta(new DoctrineORMAdapter($this->queryLatest(), false));
$paginator->setMaxPerPage(25);
$paginator->setCurrentPage($page);
return $paginator;
}
}

View File

@@ -0,0 +1,43 @@
{% extends 'base.html.twig' %}
{% block body_id 'timesheet_index' %}
{% block main %}
{% if entries %}
<table class="table table-striped">
<thead>
<tr>
<th><i class="fa fa-calendar"></i> {{ 'label.date'|trans }}</th>
<th><i class="fa fa-circle-o"></i> {{ 'label.start'|trans }}</th>
<th><i class="fa fa-circle"></i> {{ 'label.end'|trans }}</th>
<th><i class="fa fa-clock-o"></i> {{ 'label.duration'|trans }}</th>
<th><i class="fa fa-user"></i> {{ 'label.user'|trans }}</th>
<th>{{ 'label.description'|trans }}</th>
</tr>
</thead>
<tbody>
{% for entry in entries %}
<tr>
<td>{{ entry.start|date("m/d/Y") }}</td>
<td>{{ entry.start|date("H:i") }}</td>
<td>{{ entry.end|date("H:i") }}</td>
<td>{{ entry.duration|gmdate }}</td>
<td>{{ entry.userid }}</td>
<td>{{ entry.description }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<div class="well">{{ 'post.no_posts_found'|trans }}</div>
{% endif %}
<div class="navigation text-center">
{{ pagerfanta(entries, 'twitter_bootstrap3_translated', { routeName: 'timesheet_paginated' }) }}
</div>
{% endblock %}
{% block sidebar %}
{{ parent() }}
{% endblock %}

View File

@@ -0,0 +1,23 @@
<?php
/*
* This file is part of the Kimai package.
*
* (c) Kevin Papst <kevin@kevinpapst.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace TimesheetBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
/**
* This class defines the Bundle for all Timesheet related topics
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
class TimesheetBundle extends Bundle
{
}