+ +
+ + +
+ +
| {{ form_row(col.col_name) }} | + {% endfor %} +
|---|
| {{ form_row(col.values[i]) }} | + {% endfor %} +
-
+
- delete row +
- add row +
- remove column +
- copy column +
diff --git a/composer.json b/composer.json
index 884b1d6..7692f41 100644
--- a/composer.json
+++ b/composer.json
@@ -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",
diff --git a/composer.lock b/composer.lock
index ffb75a6..e7631c7 100644
--- a/composer.lock
+++ b/composer.lock
@@ -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",
diff --git a/public/scripts/edit_graph.js b/public/scripts/edit_graph.js
new file mode 100755
index 0000000..89ed17f
--- /dev/null
+++ b/public/scripts/edit_graph.js
@@ -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 = "" + obj.name + "
" + obj.value + "
"; + } 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(); + } + }); +} \ No newline at end of file diff --git a/public/styles/edit_chart.css b/public/styles/edit_chart.css new file mode 100755 index 0000000..6d4abb4 --- /dev/null +++ b/public/styles/edit_chart.css @@ -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 + } +} \ No newline at end of file diff --git a/public/styles/edit_graph.css b/public/styles/edit_graph.css deleted file mode 100755 index ea84d9d..0000000 --- a/public/styles/edit_graph.css +++ /dev/null @@ -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} -} \ No newline at end of file diff --git a/src/Controller/ChartController.php b/src/Controller/ChartController.php new file mode 100644 index 0000000..15738e8 --- /dev/null +++ b/src/Controller/ChartController.php @@ -0,0 +1,56 @@ +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; + } +} diff --git a/src/Controller/UserController.php b/src/Controller/UserController.php index 9acf7c6..192fb7c 100644 --- a/src/Controller/UserController.php +++ b/src/Controller/UserController.php @@ -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() ]); } - } \ No newline at end of file +} diff --git a/src/Document/Chart.php b/src/Document/Chart.php index c920299..86eea11 100644 --- a/src/Document/Chart.php +++ b/src/Document/Chart.php @@ -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; + } } \ No newline at end of file diff --git a/src/Form/Model/Registration.php b/src/Form/Model/Registration.php deleted file mode 100644 index 5eb5923..0000000 --- a/src/Form/Model/Registration.php +++ /dev/null @@ -1,41 +0,0 @@ -user = $user; - } - - public function getUser() - { - return $this->user; - } - - public function getTermsAccepted() - { - return $this->termsAccepted; - } - - public function setTermsAccepted($termsAccepted) - { - $this->termsAccepted = (bool) $termsAccepted; - } -} \ No newline at end of file diff --git a/src/Form/Type/CellType.php b/src/Form/Type/CellType.php new file mode 100644 index 0000000..145c5c9 --- /dev/null +++ b/src/Form/Type/CellType.php @@ -0,0 +1,14 @@ +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, + ]); + } +} \ No newline at end of file diff --git a/src/Form/Type/ColumnType.php b/src/Form/Type/ColumnType.php new file mode 100644 index 0000000..94813cb --- /dev/null +++ b/src/Form/Type/ColumnType.php @@ -0,0 +1,36 @@ +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, + ]); + }*/ +} \ No newline at end of file diff --git a/src/Form/Type/MetadataType.php b/src/Form/Type/MetadataType.php new file mode 100644 index 0000000..8be500e --- /dev/null +++ b/src/Form/Type/MetadataType.php @@ -0,0 +1,68 @@ +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, + ]); + }*/ +} \ No newline at end of file diff --git a/src/Form/Type/RegistrationType.php b/src/Form/Type/RegistrationType.php deleted file mode 100644 index 1bb965e..0000000 --- a/src/Form/Type/RegistrationType.php +++ /dev/null @@ -1,17 +0,0 @@ -add('user', UserType::class); - $builder->add('terms', CheckboxType::class, ['property_path' => 'termsAccepted']); - } -} \ No newline at end of file diff --git a/src/Repository/ChartRepository.php b/src/Repository/ChartRepository.php index 0430061..a185d8f 100644 --- a/src/Repository/ChartRepository.php +++ b/src/Repository/ChartRepository.php @@ -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; diff --git a/src/Repository/UserRepository.php b/src/Repository/UserRepository.php index 3767526..34f21b6 100644 --- a/src/Repository/UserRepository.php +++ b/src/Repository/UserRepository.php @@ -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; diff --git a/templates/edit.html.twig b/templates/edit.html.twig new file mode 100644 index 0000000..a1e990e --- /dev/null +++ b/templates/edit.html.twig @@ -0,0 +1,75 @@ +{% extends 'base.html.twig' %} + +{% block stylesheets %} + {{ parent() }} + + +{% endblock %} + +{% block javascripts %} + {{ parent() }} + +{% endblock %} + +{% block title %} + Edit chart +{% endblock %} + +{% block body %} +| {{ form_row(col.col_name) }} | + {% endfor %} +
|---|
| {{ form_row(col.values[i]) }} | + {% endfor %} +