František Špaček 2 years ago
parent 11e1932120
commit 7bc2723e31

@ -11,7 +11,7 @@
"doctrine/doctrine-bundle": "^2.12",
"doctrine/doctrine-migrations-bundle": "^3.3",
"doctrine/mongodb-odm": "^2.7",
"doctrine/mongodb-odm-bundle": "^5.*",
"doctrine/mongodb-odm-bundle": "5.*",
"doctrine/orm": "^3.1",
"mongodb/mongodb": "^1.18",
"phpdocumentor/reflection-docblock": "^5.3",

2
composer.lock generated

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "46a368f6c1680011c0f2e135980f8df9",
"content-hash": "169597cc948acc7f627ecd4ff309138e",
"packages": [
{
"name": "doctrine/cache",

@ -0,0 +1,234 @@
let canvas, parent, legend, dataDiv, table;
const urlParams = new URLSearchParams(window.location.search);
const graph_code = urlParams.get('code');
validateUser(graph_code);
let rcTarget = {};
$(document).ready( function () {
canvas = document.getElementById("graphCanvas");
parent = document.getElementById("graphDiv");
legend = document.getElementById("graphLegend");
dataDiv = document.getElementById("dataDiv");
table = new Table(document.getElementById("dataTable"));
document.getElementById('upload').addEventListener('change', handleFileSelect, false);
load_data();
table.reloadEvLi();
reloadShares();
//Click
document.addEventListener('mousemove', (e) => {
const pos = {
x: e.clientX - canvas.offsetLeft,
y: e.clientY - canvas.offsetTop
};
let obj = checkHit(pos);
//show point value
if (obj !== null) {
dataDiv.style.left = pos.x + canvas.offsetLeft + "px";
dataDiv.style.top = pos.y + canvas.offsetTop + "px";
dataDiv.style.display = "block";
dataDiv.innerHTML = "<b>" + obj.name + "</b><br><p>" + obj.value + "</p>";
} else {
dataDiv.style.display = "none";
}
});
$("#exportBtn").on('click', function (e) {
table.reloadData();
exportData('tableData');
});
$("#saveBtn").on('click', function (e) {
table.reloadData();
save_data();
});
$("#drawBtn").on('click', function (e) {
table.reloadData();
submitData();
});
//RIGHT CLICK menu
$(document).bind("click", function(event) {
document.getElementById("rcMenu").style.display = "none";
});
//odebere řádek
$("#rcDelRow").on('click', function (e) {
e.preventDefault();
if (rcTarget.parentElement.parentElement.tagName === "THEAD")
return;
table.removeRow(rcTarget.parentElement);
});
//přidá řádek
$("#rcAddRow").on('click', function (e) {
e.preventDefault();
table.addRow(table, rcTarget);
});
//odebere sloupec
$('#rcDelCol').on('click', function (e) {
e.preventDefault();
table.removeCol(getCellIndex(rcTarget));
});
//přidá sloupec
$('#rcAddCol').on('click', function (e) {
e.preventDefault();
table.addCol(getCellIndex(rcTarget));
});
//Sharing
$('#shareBtn').on('click', function (e) {
e.preventDefault();
let username = document.getElementById("shareUsername").value;
addShare(username);
});
});
//Resize
$(window).on('resize', function () {
resizeCanvas(canvas, parent);
table.reloadData();
drawChart(getSettings(), table.data);
});
function handleFileSelect(evt) {
let files = evt.target.files;
table.importData(files[0], table);
}
function submitData() {
table.reloadData();
drawChart(getSettings(), table.data);
}
function save_data() {
table.reloadData();
let settings = getSettings();
$.ajax({
url: "php/save_data.php",
type: "post",
dataType: "text",
data: {code: graph_code, data: JSON.stringify(table.data), settings: JSON.stringify(settings), name:settings.title},
success: function (result) {
//alert("Saved successfully " + result);
}
});
}
function load_data() {
$.ajax({
url: "php/load_data.php",
type: "post",
dataType: "json",
data: {code: graph_code},
success: function (result) {
if (result.data == null) {
alert("Error: no data found");
return;
}
table.data = JSON.parse(result.data);
table.updateTable();
if (result.settings == null) {
alert("Error: no graph settings found");
} else {
loadSettings(JSON.parse(result.settings));
}
drawChart(getSettings(), table.data);
}
})
}
function getCellIndex(cell) {
let parent = cell.parentElement;
let children = Array.from(parent.children);
for (let i = 0; i < children.length; i++){
if (children[i] === cell) {
return i;
}
}
}
//Nastavení grafu
function getSettings() {
return {
type: document.getElementById('graph_types').value,
y_step: parseFloat(document.getElementById('y_step').value),
b_color: ((document.getElementById('enableBgColor').checked) ? document.getElementById('graphBgColor').value : null),
display_legend: document.getElementById("displayLegend").checked,
display_points: document.getElementById("displayPoints").checked,
display_support_lines: document.getElementById("displaySupportLines").checked,
title: document.getElementById("graphTitle").value,
display_title: document.getElementById("displayTitle").checked,
margin: parseFloat(document.getElementById("graphMargin").value),
custom_x_values: document.getElementById('customXValues').value,
x_label: document.getElementById('xLabel').value,
y_label: document.getElementById('yLabel').value,
};
}
function loadSettings(new_settings) {
document.getElementById('graph_types').value = new_settings.type;
document.getElementById('y_step').value = new_settings.y_step;
if (new_settings.b_color !== null) {
document.getElementById('graphBgColor').value = new_settings.b_color;
document.getElementById('enableBgColor').checked = true;
}
document.getElementById("displayLegend").checked = new_settings.display_legend;
document.getElementById("displayPoints").checked = new_settings.display_points;
document.getElementById("displaySupportLines").checked = new_settings.display_support_lines;
document.getElementById("graphTitle").value = new_settings.title;
document.getElementById("displayTitle").checked = new_settings.display_title;
document.getElementById("graphMargin").value = new_settings.margin;
document.getElementById('customXValues').value = new_settings.custom_x_values;
document.getElementById('xLabel').value = new_settings.x_label;
document.getElementById('yLabel').value = new_settings.y_label;
}
//Sdílení grafu
function reloadShares() {
$.ajax({
url: "php/load_shares.php",
type: "post",
dataType: "text",
data: {code: graph_code},
success: function(result) {
document.getElementById("shareList").innerHTML = result;
}
});
}
function removeShare(username) {
$.ajax({
url: "php/remove_share.php",
type: "post",
dataType: "text",
data: {username: username, code: graph_code},
success: function(result) {
reloadShares();
}
});
}
function addShare(username) {
$.ajax({
url: "php/add_share.php",
type: "post",
dataType: "text",
data: {username: username, code: graph_code},
success: function(result) {
//alert(result);
validateUser(graph_code);
reloadShares();
}
});
}

@ -0,0 +1,105 @@
main {
display: block;
}
#mainDiv {
width: 100%;
display: flex;
padding: 10px;
}
#graphDiv {
width: 75%;
height: 450px;
}
#mainDiv form {
width: 25%;
}
#settings_div {
text-align: center;
width: 100%;
}
#tableDiv {
padding: 0;
overflow: auto;
flex-basis: 75%;
}
#shareDiv {
padding: 5px;
flex-basis: 25%;
margin-left: 5px;
}
#secondaryDiv {
display: flex;
}
#dataTable tr,
#dataTable td,
#dataTable th {
padding: 0;
}
#dataTable td,
#dataTable th {
height: 2em;
}
#dataTable th input {
font-weight: bold;
}
#dataTable input,
#dataTable div {
margin: 0;
width: 100%;
height: 100%;
border: 0;
padding: 0;
}
#dataTable input {
text-align: center;
background-color: transparent;
}
#shareUsername {
width: 100px;
height: 35px;
}
#shareHeader {
text-align: center;
}
@media (max-width: 950px) {
#mainDiv {
display: block
}
#graphDiv {
width: 100%;
}
#settings_div {
width: 100%;
display: block
}
#tableDiv {
width: 100%
}
#shareDiv {
width: 100%
}
#secondaryDiv {
display: block
}
}

@ -1,53 +0,0 @@
main {
display: block;
}
#mainDiv {
width: 100%;
display: flex;
padding: 10px;
}
#graphDiv {
width: 75%;
height: 450px;
}
#settings_div {
text-align: center;
width: 25%;
}
#tableDiv {
padding: 0;
overflow: auto;
flex-basis: 75%;
}
#shareDiv {
padding: 5px;
flex-basis: 25%;
margin-left: 5px;
}
#secondaryDiv {
display: flex;
}
#shareUsername {
width: 100px;
height: 35px;
}
#shareHeader {
text-align: center;
}
@media (max-width: 950px) {
#mainDiv {display: block}
#graphDiv {width: 100%;}
#settings_div {width: 100%; display: block}
#tableDiv {width: 100%}
#shareDiv {width: 100%}
#secondaryDiv {display: block}
}

@ -0,0 +1,56 @@
<?php
namespace App\Controller;
use App\Document\Chart;
use App\Form\Type\ChartType;
use Doctrine\ODM\MongoDB\DocumentManager;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Redirect;
use Symfony\Component\Routing\Annotation\Route;
class ChartController extends AbstractController
{
/*#[Route('/charts', name: 'list_charts')]
public function registerAction(): Response
{
//$form = $this->createForm(RegistrationType::class, new Registration());
return $this->render('.html.twig', []);
}*/
#[Route('/charts/{id}', name: 'edit_chart', requirements: ['id' => '\d+'])]
public function editAction(DocumentManager $dm, Request $request, int $id)
{
$chart = ($id !== null) ? $this->findOrFail($dm, $id) : new Chart();
$form = $this->createForm(ChartType::class, $chart);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$chart = $form->getData();
$dm->persist($chart);
$dm->flush();
//return $this->redirect('/');
}
return $this->render('edit.html.twig', [
'form' => $form->createView()
]);
}
private function findOrFail(DocumentManager $dm, int $id): Chart
{
$chart = $dm->getRepository(Chart::class)->findOneBy(['code' => $id]);
//$chart = $dm->getRepository(Chart::class)->findAll();
if ($chart === null) {
throw $this->createNotFoundException();
}
return $chart;
}
}

@ -2,8 +2,8 @@
namespace App\Controller;
use App\Form\Model\Registration;
use App\Form\Type\RegistrationType;
use App\Document\User;
use App\Form\Type\UserType;
use Doctrine\ODM\MongoDB\DocumentManager;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
@ -16,7 +16,7 @@ class UserController extends AbstractController
#[Route('/register', name: 'register')]
public function registerAction(): Response
{
$form = $this->createForm(RegistrationType::class, new Registration());
$form = $this->createForm(UserType::class, new User());
return $this->render('register.html.twig', [
'form' => $form->createView()
@ -26,14 +26,14 @@ class UserController extends AbstractController
#[Route('/create', name: 'create')]
public function createAction(DocumentManager $dm, Request $request)
{
$form = $this->createForm(RegistrationType::class, new Registration());
$form = $this->createForm(UserType::class, new User());
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$registration = $form->getData();
$user = $form->getData();
$dm->persist($registration->getUser());
$dm->persist($user);
$dm->flush();
return $this->redirect('/');
@ -43,4 +43,4 @@ class UserController extends AbstractController
'form' => $form->createView()
]);
}
}
}

@ -24,16 +24,20 @@ class Chart
#[Assert\NotBlank]
protected ?string $code = null;
#[MongoDB\Field(type: 'object')]
#[MongoDB\Field(type: 'raw')]
#[Assert\NotBlank]
protected ?string $metadata = null;
protected $metadata = null;
#[MongoDB\Field(type: 'hash')]
//#[Assert\NotBlank]
protected ?array $table = null;
public function getId(): string
{
return $this->id;
}
public function getNamel(): ?string
public function getName(): ?string
{
return $this->name;
}
@ -53,13 +57,28 @@ class Chart
$this->code = $code;
}
public function getMetadata(): ?string
public function getMetadata()
{
return $this->metadata;
}
public function setMetadata(?string $metadata): void
public function setMetadata($metadata): void
{
$this->metadata = $metadata;
}
public function getTable(): ?array
{
/*$decoded = [];
foreach ($this->table as $key => $value) {
$decoded += json_decode($value);
}
return $decoded;*/
return $this->table;
}
public function setTable(?array $table): void
{
$this->table = $table;
}
}

@ -1,41 +0,0 @@
<?php
// src/Form/Model/Registration.php
namespace App\Form\Model;
use App\Document\User;
use Symfony\Component\Validator\Constraints as Assert;
class Registration
{
/**
* @Assert\Type(type="App\Document\User")
*/
protected $user;
/**
* @Assert\NotBlank()
* @Assert\IsTrue()
*/
protected $termsAccepted;
public function setUser(User $user)
{
$this->user = $user;
}
public function getUser()
{
return $this->user;
}
public function getTermsAccepted()
{
return $this->termsAccepted;
}
public function setTermsAccepted($termsAccepted)
{
$this->termsAccepted = (bool) $termsAccepted;
}
}

@ -0,0 +1,14 @@
<?php
namespace App\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ButtonType as BaseType;
class CellType extends AbstractType
{
public function getParent()
{
return BaseType::class;
}
}

@ -0,0 +1,35 @@
<?php
namespace App\Form\Type;
use App\Document\Chart;
use App\Form\Type\MetadataType;
use App\Form\Type\ColumnType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ChartType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', TextType::class)
->add('code', TextType::class)
->add('metadata', MetadataType::class)
->add('table', CollectionType::class, [
'entry_type' => ColumnType::class,
'allow_add' => true,
/*'prototype' => true,
'prototype_data' => 'Placeholder'*/
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Chart::class,
]);
}
}

@ -0,0 +1,36 @@
<?php
namespace App\Form\Type;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ColumnType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('col_name', TextType::class, [
'label' => false,
])
->add('values', CollectionType::class, [
'entry_type' => TextType::class,
'allow_add' => true,
'prototype' => true,
'prototype_data' => 'Placeholder',
'entry_options' => [
'label' => false,
]
]);
}
/*public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Chart::class,
]);
}*/
}

@ -0,0 +1,68 @@
<?php
namespace App\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\ColorType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class MetadataType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('type', ChoiceType::class, [
'choices' => [
'Point' => 'point',
'Line' => 'line',
'Area' => 'area',
'Pie' => 'pie',
'Bar' => 'bar',
'Stacked' => 'stacked',
],
'label' => 'Chart type',
])
->add('margin', NumberType::class, [
'label' => 'Margin',
'required' => false,
])
->add('xLabel', TextType::class, [
'label' => 'X label',
'required' => false,
])
->add('yLabel', TextType::class, [
'label' => 'Y label',
'required' => false,
])
->add('displayLegend', CheckboxType::class, [
'label' => 'Display legend',
'required' => false,
])
->add('displayPoints', CheckboxType::class, [
'label' => 'Display points',
'required' => false,
])
->add('displaySupport', CheckboxType::class, [
'label' => 'Display support lines',
'required' => false,
])
->add('backgroundColor', ColorType::class, [
'label' => 'Background color',
'required' => false,
])
->add('submit', SubmitType::class, ['label' => 'Provést']);
}
/*public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => User::class,
]);
}*/
}

@ -1,17 +0,0 @@
<?php
// src/Form/Type/RegistrationType.php
namespace App\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\FormBuilderInterface;
class RegistrationType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('user', UserType::class);
$builder->add('terms', CheckboxType::class, ['property_path' => 'termsAccepted']);
}
}

@ -2,7 +2,7 @@
namespace App\Repository;
use App\Entity\Chart;
use App\Document\Chart;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;

@ -2,7 +2,7 @@
namespace App\Repository;
use App\Entity\User;
use App\Document\User;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;

@ -0,0 +1,75 @@
{% extends 'base.html.twig' %}
{% block stylesheets %}
{{ parent() }}
<link href="{{ asset('styles/style.css') }}" rel="stylesheet"/>
<link href="{{ asset('styles/edit_chart.css') }}" rel="stylesheet"/>
{% endblock %}
{% block javascripts %}
{{ parent() }}
<!--<script src={{ asset('/scripts/edit_graph.js') }}></script>-->
{% endblock %}
{% block title %}
Edit chart
{% endblock %}
{% block body %}
<main>
<div id="mainDiv">
<div id="graphDiv">
<canvas id="graphCanvas"></canvas>
<div id="graphLegend"></div>
<div id="dataDiv"></div>
</div>
<!--</div>
<div id="secondaryDiv">-->
{{ form_start(form) }}
<div id="settings_div">
{{ form_row(form.metadata) }}
<button id="saveBtn">Save</button>
<button id="drawBtn">Draw</button>
<br>
<input accept=".xls,.xlsx,.csv,.txt" id="upload" name="files[]" type="file">
<br>
<label for="export_types">export to
</label>
<select id="export_types" name="graph_types">
<option value="txt">txt</option>
<option value="xlsx">xlsx</option>
<option value="png">png</option>
<option value="xml">xml</option>
<option value="csv">csv</option>
</select>
<br>
<button id="exportBtn">Export</button>
</div>
<div id="tableDiv">
<table id="dataTable">
<tr>
{% for col in form.table %}
<th>{{ form_row(col.col_name) }}</th>
{% endfor %}
</tr>
{% for i in 0..form.table[0].values|length-1 %}
<tr>
{% for col in form.table %}
<td>{{ form_row(col.values[i]) }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
</div>
{{ form_end(form) }}
</div>
<div id="rcMenu">
<ul>
<li><a id="rcDelRow" href="">delete row</a></li>
<li><a id="rcAddRow" href="">add row</a></li>
<li><a id="rcDelCol" href="">remove column</a></li>
<li><a id="rcAddCol" href="">copy column</a></li>
</ul>
</div>
</main>
{% endblock %}

@ -1,11 +1,11 @@
<header id="mainHeader">
<div id="logo">
<a href="index.html">EasyCharts</a>
<a href={{ path('homepage') }}>EasyCharts</a>
</div>
<nav>
<a href="docs.html">Documentation</a>
</nav>
<div id="user">
<a href="login.html">Login</a>
<a href={{ path('register') }}>Login</a>
</div>
</header>

@ -0,0 +1,13 @@
{% extends 'base.html.twig' %}
{% block title %}
Login
{% endblock %}
{% block body %}
<main>
<div class="loginDiv">
</div>
</main>
{% endblock %}

@ -1,6 +1,17 @@
{# templates/egister.html.twig #}
{{ form_start(form, {'action': path('create'), 'method': 'POST'}) }}
{% extends 'base.html.twig' %}
{% block title %}
Register
{% endblock %}
{% block body %}
<main>
<div class="loginDiv">
{{ form_start(form, {'action': path('create'), 'method': 'POST'}) }}
{{ form_widget(form) }}
<input type="submit" />
{{ form_end(form) }}
<input type="submit"/>
{{ form_end(form) }}
</div>
</main>
{% endblock %}

@ -7,8 +7,12 @@ $baseDir = dirname($vendorDir);
return array(
'App\\Controller\\IndexController' => $baseDir . '/src/Controller/IndexController.php',
'App\\Entity\\Chart' => $baseDir . '/src/Entity/Chart.php',
'App\\Entity\\User' => $baseDir . '/src/Entity/User.php',
'App\\Controller\\UserController' => $baseDir . '/src/Controller/UserController.php',
'App\\Document\\Chart' => $baseDir . '/src/Document/Chart.php',
'App\\Document\\User' => $baseDir . '/src/Document/User.php',
'App\\Form\\Model\\Registration' => $baseDir . '/src/Form/Model/Registration.php',
'App\\Form\\Type\\RegistrationType' => $baseDir . '/src/Form/Type/RegistrationType.php',
'App\\Form\\Type\\UserType' => $baseDir . '/src/Form/Type/UserType.php',
'App\\Kernel' => $baseDir . '/src/Kernel.php',
'App\\Repository\\ChartRepository' => $baseDir . '/src/Repository/ChartRepository.php',
'App\\Repository\\UserRepository' => $baseDir . '/src/Repository/UserRepository.php',

@ -597,8 +597,12 @@ class ComposerStaticInit4fe506277082b063a84f05968212cec8
public static $classMap = array (
'App\\Controller\\IndexController' => __DIR__ . '/../..' . '/src/Controller/IndexController.php',
'App\\Entity\\Chart' => __DIR__ . '/../..' . '/src/Entity/Chart.php',
'App\\Entity\\User' => __DIR__ . '/../..' . '/src/Entity/User.php',
'App\\Controller\\UserController' => __DIR__ . '/../..' . '/src/Controller/UserController.php',
'App\\Document\\Chart' => __DIR__ . '/../..' . '/src/Document/Chart.php',
'App\\Document\\User' => __DIR__ . '/../..' . '/src/Document/User.php',
'App\\Form\\Model\\Registration' => __DIR__ . '/../..' . '/src/Form/Model/Registration.php',
'App\\Form\\Type\\RegistrationType' => __DIR__ . '/../..' . '/src/Form/Type/RegistrationType.php',
'App\\Form\\Type\\UserType' => __DIR__ . '/../..' . '/src/Form/Type/UserType.php',
'App\\Kernel' => __DIR__ . '/../..' . '/src/Kernel.php',
'App\\Repository\\ChartRepository' => __DIR__ . '/../..' . '/src/Repository/ChartRepository.php',
'App\\Repository\\UserRepository' => __DIR__ . '/../..' . '/src/Repository/UserRepository.php',

Loading…
Cancel
Save

Powered by TurnKey Linux.