Permissions

main
František Špaček 2 years ago
parent e3f51c95e3
commit 23a92f9660

@ -39,8 +39,8 @@ security:
# Note: Only the *first* access control that matches will be used # Note: Only the *first* access control that matches will be used
access_control: access_control:
# - { path: ^/admin, roles: ROLE_ADMIN } # - { path: ^/admin, roles: ROLE_ADMIN }
#role_hierarchy: role_hierarchy:
# ROLE_ADMIN: ROLE_USER ROLE_ADMIN: ROLE_USER
when@test: when@test:
security: security:

@ -121,15 +121,11 @@ class ChartLoader {
return mostCommonIndex return mostCommonIndex
} }
getEffectObjects() {
}
/** /**
* Handles mouse movement events for interactivity. * Handles mouse movement events for interactivity.
* @param {MouseEvent} e - The mouse event object. * @param {MouseEvent} e - The mouse event object.
* @param {Chart} chart - The chart object associated with the mouse movement. * @param {Chart} chart - The chart object associated with the mouse movement.
*/ */
mouseMoveFunc(e, chart) { mouseMoveFunc(e, chart) {
// Get mouse position // Get mouse position
const pos = { const pos = {
@ -188,13 +184,88 @@ class ChartLoader {
} }
} }
touchHandler(event) {
// Skip when zooming
if (event.touches.length === 2)
return
var touches = event.changedTouches,
first = touches[0],
type = "";
switch (event.type) {
case "touchstart": type = "mousedown"; break;
case "touchmove": type = "mousemove"; break;
case "touchend": type = "mouseup"; break;
default: return;
}
var simulatedEvent = document.createEvent("MouseEvent");
simulatedEvent.initMouseEvent(type, true, true, window, 1,
first.screenX, first.screenY,
first.clientX, first.clientY, false,
false, false, false, 0/*left*/, null);
first.target.dispatchEvent(simulatedEvent);
event.preventDefault();
}
mapTouchToMouseWheel(element) {
let lastDist = 0;
let touchStarted = false;
element.addEventListener('touchstart', (event) => {
if (event.touches.length === 2) {
let x = event.touches[0].clientX + event.touches[1].clientX
let y = event.touches[0].clientY + event.touches[1].clientY
lastDist = Math.sqrt(x * x + y * y)
touchStarted = true;
e.stopPropagation()
event.preventDefault();
}
}, { passive: false });
element.addEventListener('touchmove', (event) => {
if (touchStarted && event.touches.length === 2) {
let x = event.touches[0].clientX + event.touches[1].clientX
let y = event.touches[0].clientY + event.touches[1].clientY
const curDist = Math.sqrt(x * x + y * y)
const deltaY = lastDist - curDist
const wheelEvent = new WheelEvent('wheel', {
deltaY: deltaY,
bubbles: true,
cancelable: true,
view: window
});
element.dispatchEvent(wheelEvent);
lastTouchY = currentTouchY;
e.stopPropagation()
event.preventDefault();
}
}, { passive: false });
element.addEventListener('touchend', (event) => {
touchStarted = false;
});
}
/** /**
* Adds event listeners to enable interactivity on the chart. * Adds event listeners to enable interactivity on the chart.
* @param {Chart} chart - The chart object to which listeners will be added. * @param {Chart} chart - The chart object to which listeners will be added.
*/ */
addListeners(chart) { addListeners(chart) {
document.addEventListener("touchstart", this.touchHandler, true);
document.addEventListener("touchmove", this.touchHandler, true);
document.addEventListener("touchend", this.touchHandler, true);
document.addEventListener("touchcancel", this.touchHandler, true);
this.mapTouchToMouseWheel(document);
// Mousemove event listener for tracking mouse movement // Mousemove event listener for tracking mouse movement
document.addEventListener('mousemove', (e) => { document.addEventListener("mousemove", (e) => {
this.mouseMoveFunc(e, chart) this.mouseMoveFunc(e, chart)
if (this.panningEnabled === true) { if (this.panningEnabled === true) {
@ -241,6 +312,17 @@ class ChartLoader {
this.panningEnabled = false this.panningEnabled = false
}) })
// Removes hover effects and tooltip when mouse leaves the chart
document.addEventListener("mouseout", (e) => {
if (this.selectedShapeIndex === null) {
this.tooltip.style.display = "none"
}
else {
let effectCtx = this.effectCanvas.getContext("2d")
this.chart.drawEffect(effectCtx, [chart.objects[this.selectedShapeIndex]])
}
})
// Window resize event listener for resizing the chart canvas // Window resize event listener for resizing the chart canvas
window.addEventListener("resize", e => { window.addEventListener("resize", e => {
// Resize the chart canvas and redraw the chart // Resize the chart canvas and redraw the chart

@ -18,4 +18,7 @@ function loadEventListeners() {
} }
}) })
}) })
let importElement = document.getElementById("import")
//importElement.addEventListener
} }

@ -51,6 +51,8 @@ class Table {
this.rcDelRow.addEventListener("mousedown", (e) => { this.delRow() }) this.rcDelRow.addEventListener("mousedown", (e) => { this.delRow() })
this.rcAddCol.addEventListener("mousedown", (e) => { this.addCol() }) this.rcAddCol.addEventListener("mousedown", (e) => { this.addCol() })
this.rcDelCol.addEventListener("mousedown", (e) => { this.delCol() }) this.rcDelCol.addEventListener("mousedown", (e) => { this.delCol() })
this.get
} }
handleContextMenu(rcMenu, tableElement, pos) { handleContextMenu(rcMenu, tableElement, pos) {

@ -82,16 +82,26 @@ div[id^="chart_metadata_group"] {
/* Remove padding */ /* Remove padding */
overflow: auto; overflow: auto;
/* Add scrollbars if content overflows */ /* Add scrollbars if content overflows */
flex-basis: 100%; flex-basis: 75%;
/* Set the size of the table area */ /* Set the size of the table area */
} }
/* Div for file import and export */
#fileDiv {
flex-basis: 25%;
background-color: var(--main);
margin-right: 0.5rem;
display: flex;
flex-direction: column;
padding: 0.5rem;
}
/* Styles for secondary div */ /* Styles for secondary div */
#secondaryDiv { #secondaryDiv {
flex-basis: 40%; flex-basis: 40%;
width: auto;
display: flex; display: flex;
margin: 1rem; margin: 0 1rem 0 1rem;
text-align: center;
} }
/* Styles for table elements */ /* Styles for table elements */
@ -144,6 +154,54 @@ div[id^="chart_metadata_group"] {
border-width: 0; border-width: 0;
} }
/* Styles for settings container */
#settings_div{
padding: 0.5rem;
background-color: var(--main);
}
#settings_div h2{
color: var(--dark);
}
table {
width: 100%;
}
table, th, td {
border-collapse: collapse;
}
th, td {
padding: 0.4rem;
border: 1px solid darkgrey;
min-width: 8rem;
text-align: center;
}
/* Styles for even rows of table */
tr:nth-child(even) td:not(.UI_remove_row){
background-color: var(--main);
}
th {
background-color: var(--main-dark);
}
th div {
color: var(--light);
}
th input {
padding: 0;
margin: 0;
}
[contenteditable] {
outline: 0 solid transparent;
}
#rcMenu { #rcMenu {
z-index: 1000; z-index: 1000;
position: absolute; position: absolute;
@ -194,6 +252,6 @@ div[id^="chart_metadata_group"] {
} }
#secondaryDiv { #secondaryDiv {
display: block flex-direction: column;
} }
} }

@ -1,63 +0,0 @@
/* Styles for graph container */
#graphDiv {
height: 400px;
}
/* Styles for settings container */
#settings_div{
width: 300px;
padding: 5px;
background-color: var(--main);
}
#settings_div h2{
color: var(--dark);
}
#shareDiv{
width: 300px;
padding: 5px;
background-color: var(--side);
}
#shareDiv h2{
color: var(--dark);
}
table {
margin-top: 20px;
width: 100%;
}
table, th, td {
border-collapse: collapse;
}
th, td {
padding: 4px;
border: 1px solid darkgrey;
min-width: 100px;
text-align: center;
}
/* Styles for even rows of table */
tr:nth-child(even) td:not(.UI_remove_row){
background-color: var(--main);
}
th {
background-color: var(--main-dark);
}
th div {
color: var(--light);
}
th input {
padding: 0;
margin: 0;
}
[contenteditable] {
outline: 0 solid transparent;
}

@ -17,6 +17,10 @@ body {
padding: 0; padding: 0;
} }
input {
text-align: center;
}
button, button,
#createChart { #createChart {
background-color: var(--main-dark); background-color: var(--main-dark);
@ -49,6 +53,7 @@ header #logo {
text-align: center; text-align: center;
flex-basis: 20%; flex-basis: 20%;
display: flex; display: flex;
justify-content: stretch;
} }
header nav { header nav {
@ -58,7 +63,8 @@ header nav {
} }
header #homepageLink:hover, header #homepageLink:hover,
header #chartsLink:hover { header #chartsLink:hover,
header #docsLink:hover {
background-color: var(--main-highlight); background-color: var(--main-highlight);
} }
@ -164,7 +170,7 @@ h2 {
#myCharts { #myCharts {
height: 100%; height: 100%;
width: 100%; width: 100%;
margin: 0.5rem; margin: 1rem;
text-align: center; text-align: center;
background-color: var(--main); background-color: var(--main);
display: block; display: block;
@ -224,3 +230,21 @@ h2 {
color: red; color: red;
transition: 300ms; transition: 300ms;
} }
/* Media query for smaller screens */
@media (max-width: 600px) {
header {
flex-direction: column;
justify-content: stretch;
}
header nav {
display: flex;
flex-direction: column;
text-align: center;
}
header #logo a {
width: 100%;
}
}

@ -32,11 +32,15 @@ class ChartRestController extends AbstractRestController
#[Rest\Post('/insert', name: 'insert')] #[Rest\Post('/insert', name: 'insert')]
public function insert(DocumentManager $dm, Request $request): Response public function insert(DocumentManager $dm, Request $request): Response
{ {
if ($this->getUser() === null)
throw $this->createAccessDeniedException('Uživatel musí být přihlášen!');
$data = json_decode($request->getContent()); $data = json_decode($request->getContent());
$chart = new Chart(); $chart = new Chart();
$chart->setName($data->name); $chart->setName($data->name);
$chart->setMetadata($data->metadata); $chart->setMetadata($data->metadata);
$chart->setTable($data->table); $chart->setTable($data->table);
$this->getUser()->addChart($chart);
$dm->persist($chart); $dm->persist($chart);
$dm->flush(); $dm->flush();
@ -46,6 +50,9 @@ class ChartRestController extends AbstractRestController
#[Rest\Post('/{id}/update', name: 'update')] #[Rest\Post('/{id}/update', name: 'update')]
public function update(DocumentManager $dm, Request $request, Chart $chart): Response public function update(DocumentManager $dm, Request $request, Chart $chart): Response
{ {
if ($chart->getUser() !== $this->getUser())
throw $this->createAccessDeniedException('Tento graf patří jinému uživateli!');
$data = json_decode($request->getContent()); $data = json_decode($request->getContent());
$chart->setName($data->name); $chart->setName($data->name);
$chart->setMetadata($data->metadata); $chart->setMetadata($data->metadata);
@ -59,6 +66,9 @@ class ChartRestController extends AbstractRestController
#[Rest\Delete('/{id}/remove', name:'remove')] #[Rest\Delete('/{id}/remove', name:'remove')]
public function remove(DocumentManager $dm, Request $request, Chart $chart): Response public function remove(DocumentManager $dm, Request $request, Chart $chart): Response
{ {
if ($chart->getUser() !== $this->getUser())
throw $this->createAccessDeniedException('Tento graf patří jinému uživateli!');
$dm->remove($chart); $dm->remove($chart);
$dm->flush(); $dm->flush();

@ -18,7 +18,9 @@ class ChartController extends AbstractController
#[Route('/', name: 'list')] #[Route('/', name: 'list')]
public function list(DocumentManager $dm, Request $request) : Response public function list(DocumentManager $dm, Request $request) : Response
{ {
//$charts = $dm->getRepository(Chart::class)->findAll(); if ($this->getUser() === null)
return $this->redirectToRoute('users_login');
$charts = $this->getUser()->getCharts(); $charts = $this->getUser()->getCharts();
return $this->render('chart/list.html.twig', [ return $this->render('chart/list.html.twig', [
'charts' => $charts 'charts' => $charts
@ -28,6 +30,12 @@ class ChartController extends AbstractController
#[Route('/{id}/edit', name: 'edit')] #[Route('/{id}/edit', name: 'edit')]
public function editAction(DocumentManager $dm, Request $request, Chart $chart) : Response public function editAction(DocumentManager $dm, Request $request, Chart $chart) : Response
{ {
if ($chart->getUser() !== $this->getUser()) {
if ($this->getUser() !== null)
throw $this->createAccessDeniedException('Tento graf patří jinému uživateli!');
return $this->redirectToRoute('users_login');
}
$form = $this->createForm(ChartType::class, $chart); $form = $this->createForm(ChartType::class, $chart);
$form->handleRequest($request); $form->handleRequest($request);
@ -47,6 +55,9 @@ class ChartController extends AbstractController
#[Route('/create', name: 'create')] #[Route('/create', name: 'create')]
public function createAction(DocumentManager $dm) : Response public function createAction(DocumentManager $dm) : Response
{ {
if ($this->getUser() === null)
throw $this->createAccessDeniedException('Uživatel musí být přihlášen!');
$chart = new Chart(); $chart = new Chart();
$dm->persist($chart); $dm->persist($chart);
$this->getUser()->addChart($chart); $this->getUser()->addChart($chart);
@ -66,12 +77,17 @@ class ChartController extends AbstractController
#[Route('/{id}/remove', name: 'remove')] #[Route('/{id}/remove', name: 'remove')]
public function removeAction(DocumentManager $dm, Request $request, Chart $chart) : Response public function removeAction(DocumentManager $dm, Request $request, Chart $chart) : Response
{ {
if ($chart->getUser() !== $this->getUser()) {
if ($this->getUser() !== null)
throw $this->createAccessDeniedException('Tento graf patří jinému uživateli!');
return $this->redirectToRoute('users_login');
}
$form = $this->createForm(DeleteType::class, $chart); $form = $this->createForm(DeleteType::class, $chart);
$form->handleRequest($request); $form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
$dm->remove($chart); $dm->remove($chart);
//$this->getUser()->removeChart($chart);
$dm->flush(); $dm->flush();
return $this->redirectToRoute('charts_list'); return $this->redirectToRoute('charts_list');

@ -31,8 +31,11 @@ class UserController extends AbstractController
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
$user = $form->getData(); $user = $form->getData();
if ($dm->getRepository(User::class)->findOneBy(['email'=> $user->getEmail()])) if ($dm->getRepository(User::class)->findOneBy(['email'=> $user->getEmail()])) {
throw $this->createAccessDeniedException('Email již někdo používá'); if ($this->getUser() !== null)
throw $this->createAccessDeniedException('Účet patří jinému uživateli!');
return $this->redirectToRoute('users_login');
}
$hashedPassword = $passwordHasher->hashPassword($user, $user->getPassword()); $hashedPassword = $passwordHasher->hashPassword($user, $user->getPassword());
$user->setPassword($hashedPassword); $user->setPassword($hashedPassword);
@ -42,7 +45,7 @@ class UserController extends AbstractController
$security->login($user); $security->login($user);
return $this->redirect('/'); return $this->redirectToRoute('homepage');
} }
return $this->render('user/register.html.twig', [ return $this->render('user/register.html.twig', [
@ -69,8 +72,13 @@ class UserController extends AbstractController
#[Route('/{id}/edit', name: 'edit')] #[Route('/{id}/edit', name: 'edit')]
public function editAction(DocumentManager $dm, Request $request, UserPasswordHasherInterface $passwordHasher, User $user) public function editAction(DocumentManager $dm, Request $request, UserPasswordHasherInterface $passwordHasher, User $user)
{ {
$form = $this->createForm(UserType::class, $user); if ($user !== $this->getUser()) {
if ($this->getUser() !== null)
throw $this->createAccessDeniedException('Účet patří jinému uživateli!');
return $this->redirectToRoute('users_login');
}
$form = $this->createForm(UserType::class, $user);
$form->handleRequest($request); $form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
@ -91,6 +99,9 @@ class UserController extends AbstractController
#[Route('/{id}/remove', name: 'remove')] #[Route('/{id}/remove', name: 'remove')]
public function removeAction(DocumentManager $dm, Request $request, User $user) : Response public function removeAction(DocumentManager $dm, Request $request, User $user) : Response
{ {
if ($user !== $this->getUser())
throw $this->createAccessDeniedException('Účet patří jinému uživateli!');
$form = $this->createForm(DeleteType::class, $user); $form = $this->createForm(DeleteType::class, $user);
$form->handleRequest($request); $form->handleRequest($request);

@ -172,7 +172,7 @@ class MetadataType extends AbstractType
) )
// Background settings // Background settings
->add( ->add(
$builder->create('group5', FormType::class, [ $builder->create('group6', FormType::class, [
'inherit_data' => true, 'inherit_data' => true,
'label' => 'Nastavení pozadí', 'label' => 'Nastavení pozadí',
'label_attr' => ['class' => 'submenuLabel arrow-down'] 'label_attr' => ['class' => 'submenuLabel arrow-down']

@ -2,7 +2,6 @@
{% block stylesheets %} {% block stylesheets %}
{{ parent() }} {{ parent() }}
<link href="{{ asset('styles/style.css') }}" rel="stylesheet"/>
<link href="{{ asset('styles/edit_chart.css') }}" rel="stylesheet"/> <link href="{{ asset('styles/edit_chart.css') }}" rel="stylesheet"/>
{% endblock %} {% endblock %}
@ -12,15 +11,15 @@
<script type="text/javascript" src={{ asset('/scripts/edit_chart.js') }}></script> <script type="text/javascript" src={{ asset('/scripts/edit_chart.js') }}></script>
<script> <script>
// Execute when DOM content is fully loaded // Execute when DOM content is fully loaded
document.addEventListener("DOMContentLoaded", function (event) { // Get DOM elements document.addEventListener("DOMContentLoaded", function (event) { // Get DOM elements
loadEventListeners() loadEventListeners()
let tableElement = document.getElementById("dataTable") let tableElement = document.getElementById("dataTable")
let rcMenu = document.getElementById("rcMenu") let rcMenu = document.getElementById("rcMenu")
let table = new Table(tableElement, rcMenu) let table = new Table(tableElement, rcMenu)
}) })
</script> </script>
{% endblock %} {% endblock %}
@ -38,11 +37,22 @@
{{ form_row(chartForm.name) }} {{ form_row(chartForm.name) }}
{{ form_row(chartForm.metadata) }} {{ form_row(chartForm.metadata) }}
<!--<button id="saveBtn">Save</button> <!--<button id="saveBtn">Save</button>
<button id="drawBtn">Draw</button>--> <button id="drawBtn">Draw</button>-->
</div> </div>
<iframe id="chartDiv" src={{ path('charts_display', {'id': id}) }}></iframe> <iframe id="chartDiv" src={{ path('charts_display', {'id': id} ) }}></iframe>
</div> </div>
<div id="secondaryDiv"> <div id="secondaryDiv">
<div id="fileDiv">
<label for="import">Nahrát soubor</label>
<input accept=".csv,.txt" id="import" type="file">
<label for="export">Exportovat</label>
<select id="export">
<option value="txt">txt</option>
<option value="csv">csv</option>
<option value="txt">xml</option>
<option value="txt">png</option>
</select>
</div>
<div id="tableDiv"> <div id="tableDiv">
{% if chartForm.table is defined %} {% if chartForm.table is defined %}
<table id="dataTable"> <table id="dataTable">

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

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

Loading…
Cancel
Save

Powered by TurnKey Linux.