František Špaček 2 years ago
parent b02b80c612
commit e3f51c95e3

@ -30,6 +30,10 @@ security:
check_path: users_login
logout:
path: users_logout
json_login:
check_path: api_users_login
username_path: email
password_path: password
# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used

@ -166,10 +166,14 @@ class ChartLoader {
let tooltipPos = obj[0].getTooltipPos()
// Adjust tooltip position to fit within the chart div
if (tooltipPos.right.x + this.tooltip.clientWidth <= this.parent.clientWidth - 2)
if (tooltipPos.right.x + this.tooltip.clientWidth <= this.parent.clientWidth - 2) {
this.tooltip.className = "tooltip leftArrow"
this.tooltip.style.left = tooltipPos.right.x + 5 + "px"
else
}
else {
this.tooltip.className = "tooltip rightArrow"
this.tooltip.style.left = tooltipPos.left.x - this.tooltip.clientWidth + "px"
}
// Check if the tooltip extends beyond the bottom edge of the chart div
if (tooltipPos.right.y + this.tooltip.clientHeight <= parent.clientHeight - 2)

@ -214,9 +214,14 @@ class PieSlice extends Circle {
* @returns {Object} An object containing x and y coordinates for the tooltip position.
*/
getTooltipPos() {
let angle = (this.sAngle + this.eAngle) / 2
let pos = {
x: this.x + Math.cos(angle) * this.r,
y: this.y + Math.sin(angle) * this.r
}
return {
right: this.getCenter(),
left: this.getCenter()
right: pos,
left: pos
}
}
}

@ -48,8 +48,8 @@ body {
/* Styles for legend items */
#chartLegend div {
display: inline;
margin: 0 10px 0 10px; /* Spacing between legend items */
width: 50px;
margin: 0 1rem 0 1rem; /* Spacing between legend items */
width: 5rem;
}
/* Styles for the tooltip */
@ -59,8 +59,9 @@ body {
background-color: white;
border: 1px solid grey;
text-align: center;
padding: 5px;
border-radius: 3px;
padding: 0.5rem;
border-radius: 0.1rem;
/*box-shadow: 0.2rem 0.2rem 0.2rem lightgrey;*/
z-index: 1; /* Ensure tooltip appears above other elements */
}
@ -76,7 +77,7 @@ body {
}
/* Styles for tooltip arrow */
#tooltip::after {
.leftArrow::after {
content: ""; /* Create a pseudo-element */
position: absolute; /* Position relative to its containing block */
top: 50%; /* Position vertically centered */
@ -86,3 +87,14 @@ body {
border-style: solid; /* Solid border */
border-color: transparent white transparent transparent; /* Arrow color */
}
.rightArrow::before {
content: ""; /* Create a pseudo-element */
position: absolute; /* Position relative to its containing block */
top: 50%; /* Position vertically centered */
left: 100%; /* Position to the left of the tooltip */
margin-top: -0.5rem; /* Adjust vertical position */
border-width: 0.5rem; /* Size of the arrow */
border-style: solid; /* Solid border */
border-color: transparent transparent transparent white; /* Arrow color */
}

@ -25,6 +25,7 @@ main form {
text-align: center;
overflow: scroll;
flex-basis: 25%;
margin-right: 0.5rem;
}
#settings_div h1{
@ -172,28 +173,26 @@ div[id^="chart_metadata_group"] {
}
/* Media query for smaller screens */
@media (max-width: 950px) {
@media (max-width: 760px) {
#mainDiv {
display: block
flex-direction: column-reverse;
}
#chartDiv {
width: 100%;
width: auto;
flex-basis: 60%;
}
#settings_div {
width: 100%;
display: block
margin-top: 1rem;
width: auto;
flex-basis: 40%;
}
#tableDiv {
width: 100%
}
#shareDiv {
width: 100%
}
#secondaryDiv {
display: block
}

@ -17,16 +17,21 @@ body {
padding: 0;
}
button, #createChart {
button,
#createChart {
background-color: var(--main-dark);
border: none;
color: white;
padding: 10px 15px;
padding: 1rem 1.5rem;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 5px;
margin: 0.3rem;
font-size: 1rem;
}
#createChart {
font-size: 1.5rem;
}
button:hover {
@ -52,7 +57,8 @@ header nav {
justify-content: flex-end;
}
header #homepageLink:hover, header #chartsLink:hover {
header #homepageLink:hover,
header #chartsLink:hover {
background-color: var(--main-highlight);
}
@ -123,7 +129,8 @@ h2 {
flex-direction: column;
}
.loginDiv #user div, .loginDiv form > div {
.loginDiv #user div,
.loginDiv form>div {
width: auto;
display: flex;
flex-direction: column;
@ -133,10 +140,27 @@ h2 {
color: red;
}
.loginDiv #logoutBtn {
.loginDiv #logoutBtn,
#deleteBtn {
color: red;
}
#accountButtonsDiv {
height: 6rem;
display: flex;
flex-direction: column;
justify-content: flex-end;
}
#logoutBtn {
margin-bottom: 2rem;
}
#logoutBtn:hover,
#deleteBtn:hover {
color: darkred;
}
#myCharts {
height: 100%;
width: 100%;
@ -162,7 +186,7 @@ h2 {
flex-direction: column;
}
#myChartList span{
#myChartList span {
width: 80%;
margin: 10px 10%;
/*border: 1px solid var(--main-dark);*/
@ -170,7 +194,7 @@ h2 {
display: flex;
}
#myChartList span a{
#myChartList span a {
text-decoration: none;
display: inline-block;
height: 100%;
@ -187,7 +211,7 @@ h2 {
background-color: var(--main-highlight);
}
#myChartList #removeChart{
#myChartList #removeChart {
color: red;
display: inline-block;
text-align: middle;
@ -195,7 +219,7 @@ h2 {
transition: 300ms;
}
#myChartList #removeChart:hover{
#myChartList #removeChart:hover {
background-color: var(--main-highlight);
color: red;
transition: 300ms;

@ -11,30 +11,27 @@ use FOS\RestBundle\Controller\Annotations as Rest;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
#[Rest\Route(path: '/api/charts', name: 'api_charts')]
#[Rest\Route(path: '/api/charts', name: 'api_charts_')]
class ChartRestController extends AbstractRestController
{
#[Rest\Get('/', name: '_list')]
#[Rest\Get('/', name: 'list')]
public function list(DocumentManager $dm, Request $request) : Response
{
$charts = \array_map(fn(Chart $entity) => ChartOutput::fromEntity($entity)->id, $dm->getRepository(Chart::class)->findAll());
$charts = \array_map(fn(Chart $entity) => ChartOutput::fromEntity($entity)->id, iterator_to_array($this->getUser()->getCharts()));
return $this->respond($charts, Response::HTTP_OK);
}
#[Rest\Get('/{id}', name: '_detail')]//, requirements: ['id' => '\d+'])]
#[Rest\Get('/{id}', name: 'detail')]
public function detail(DocumentManager $dm, Chart $chart): Response
{
//$chart = $this->findOrFail($dm, $id);
$chartDto = ChartOutput::fromEntity($chart);
return $this->respond( $chartDto, Response::HTTP_OK);
}
#[Rest\Put('/insert', name: '_insert')]
#[Rest\Post('/insert', name: 'insert')]
public function insert(DocumentManager $dm, Request $request): Response
{
//$chart = $newChart->toEntity();
$data = json_decode($request->getContent());
$chart = new Chart();
$chart->setName($data->name);
@ -46,15 +43,25 @@ class ChartRestController extends AbstractRestController
return $this->respond( $chart->getName(), Response::HTTP_OK);
}
/*private function findOrFail(DocumentManager $dm, int $id): Chart
#[Rest\Post('/{id}/update', name: 'update')]
public function update(DocumentManager $dm, Request $request, Chart $chart): Response
{
//$chart = $dm->getRepository(Chart::class)->findOneBy(['code' => $id]);
$chart = $dm->getRepository(Chart::class)->findOneBy(['_id' => $id]);
$data = json_decode($request->getContent());
$chart->setName($data->name);
$chart->setMetadata($data->metadata);
$chart->setTable($data->table);
if ($chart === null) {
throw $this->createNotFoundException("Chart was not found");
$dm->persist($chart);
$dm->flush();
return $this->respond( $chart->getName(), Response::HTTP_OK);
}
return $chart ;
}*/
#[Rest\Delete('/{id}/remove', name:'remove')]
public function remove(DocumentManager $dm, Request $request, Chart $chart): Response
{
$dm->remove($chart);
$dm->flush();
return $this->respond( $chart->getName(), Response::HTTP_OK);
}
}

@ -0,0 +1,23 @@
<?php
namespace App\Api\Controller;
use App\Document\User;
use Doctrine\ODM\MongoDB\DocumentManager;
use App\Api\Controller\AbstractRestController;
use FOS\RestBundle\Controller\Annotations as Rest;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Http\Attribute\CurrentUser;
#[Rest\Route(path: '/api/users', name: 'api_users_')]
class UserRestController extends AbstractRestController
{
#[Rest\Post('/login', name: 'login')]
public function login(DocumentManager $dm, #[CurrentUser] ?User $user): Response
{
return $this->json([
'user' => $user ? $user->getId() : null,
]);
}
}

@ -4,6 +4,7 @@ namespace App\Controller;
use App\Document\Chart;
use App\Form\Type\ChartType;
use App\Form\Type\DeleteType;
use Doctrine\ODM\MongoDB\DocumentManager;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
@ -63,11 +64,22 @@ class ChartController extends AbstractController
}
#[Route('/{id}/remove', name: 'remove')]
public function removeAction(DocumentManager $dm, Chart $chart) : Response
public function removeAction(DocumentManager $dm, Request $request, Chart $chart) : Response
{
$form = $this->createForm(DeleteType::class, $chart);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$dm->remove($chart);
//$this->getUser()->removeChart($chart);
$dm->flush();
return $this->redirectToRoute('charts_list');
}
return $this->render('chart/remove.html.twig', [
'form' =>$form->createView(),
'entity' => $chart
]);
}
}

@ -14,4 +14,9 @@ class IndexController extends AbstractController
return $this->render('index.html.twig');
}
#[Route('/docs', name: 'docs')]
public function docsAction(): Response
{
return $this->render('docs.html.twig');
}
}

@ -5,6 +5,7 @@ namespace App\Controller;
use App\Document\User;
use App\Form\Type\UserType;
use App\Form\Type\LoginType;
use App\Form\Type\DeleteType;
use Doctrine\ODM\MongoDB\DocumentManager;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
@ -30,6 +31,9 @@ class UserController extends AbstractController
if ($form->isSubmitted() && $form->isValid()) {
$user = $form->getData();
if ($dm->getRepository(User::class)->findOneBy(['email'=> $user->getEmail()]))
throw $this->createAccessDeniedException('Email již někdo používá');
$hashedPassword = $passwordHasher->hashPassword($user, $user->getPassword());
$user->setPassword($hashedPassword);
@ -83,4 +87,24 @@ class UserController extends AbstractController
'form' => $form->createView()
]);
}
#[Route('/{id}/remove', name: 'remove')]
public function removeAction(DocumentManager $dm, Request $request, User $user) : Response
{
$form = $this->createForm(DeleteType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$user->getCharts()->clear();
$dm->remove($user);
$dm->flush();
return $this->redirectToRoute('userss_list');
}
return $this->render('user/remove.html.twig', [
'form' =>$form->createView(),
'entity' => $user
]);
}
}

@ -0,0 +1,29 @@
<?php
namespace App\Form\Type;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints as Assert;
class DeleteType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$resolver = new OptionsResolver();
$this->configureOptions($resolver);
$builder
->add('button', SubmitType::class, [
'label'=> 'Smazat',
]);
}
public function configureOptions(OptionsResolver $resolver)
{
/*$resolver
->setRequired('entity')
->setAllowedTypes('entity', 'string');*/
}
}

@ -117,6 +117,7 @@
<div id="logo">
<a href="/">EasyCharts</a>
</div>
<nav></nav>
<div id="user">
<a href="/users/login">Přihlásit</a>
</div>

@ -0,0 +1,16 @@
{% extends 'base.html.twig' %}
{% block title %}
Smazat graf
{% endblock %}
{% block body %}
{{ parent() }}
<main>
<div id="myCharts">
<h1>Smazání grafu</h1>
<p>Opravdu chcete smazat graf: {{ entity.name }} ?</p>
{{ form(form) }}
</div>
</main>
{% endblock %}

@ -0,0 +1,16 @@
{% extends 'base.html.twig' %}
{% block title %}
Dokumentace
{% endblock %}
{% block body %}
{{ parent() }}
<h1>Interaktivní grafy</h1>
<section>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Accusamus odio neque est voluptatum
repellat animi dicta aliquam ipsa culpa commodi.
</p>
</section>
{% endblock %}

@ -3,7 +3,10 @@
<a href={{ path('homepage') }} id="homepageLink">Index</a>
</div>
<nav>
<a href={{ path('charts_list') }} id="chartsLink">Charts</a>
<a href={{ path('docs') }}>Dokumentace</a>
{% if app.user %}
<a href={{ path('charts_list') }} id="chartsLink">Moje grafy</a>
{% endif %}
</nav>
<div id="user">
{% if app.user %}

@ -1,7 +1,7 @@
{% extends 'base.html.twig' %}
{% block title %}
Home
Domovská stránka
{% endblock %}
{% block body %}

@ -14,7 +14,10 @@
<button type="submit">Změnit heslo</button>
{{ form_end(form, {'render_rest': false}) }}
<div id="accountButtonsDiv">
<a id="logoutBtn" href="{{ path('users_logout') }}">Odhlásit se</a>
<a id="deleteBtn" href="{{ path('users_remove', {'id': app.user.id}) }}">Smazat uživatelský účet</a>
</div>
</div>
</main>
{% endblock %}

@ -0,0 +1,16 @@
{% extends 'base.html.twig' %}
{% block title %}
Smazat uživatele
{% endblock %}
{% block body %}
{{ parent() }}
<main>
<div id="myCharts">
<h1>Smazání uživatelského účtu</h1>
<p>Opravdu chcete smazat účet: {{ entity.email }} ?</p>
{{ form(form) }}
</div>
</main>
{% endblock %}
Loading…
Cancel
Save

Powered by TurnKey Linux.