Zooming fix

main
root 2 years ago
parent 436f889192
commit 8ea1084eb4

@ -23,11 +23,11 @@ class ChartLoader {
}
/** Function for loading chart data from the server
* @param {String} code - The code used to identify the chart data to load
* @param {String} id - The id used to identify the chart
**/
loadData(code) {
loadData(id) {
// Fetch chart data from the server
fetch("/api/charts/" + code, {
fetch("/api/charts/" + id, {
method: 'GET',
headers: {
'Content-Type': 'json'
@ -198,7 +198,7 @@ class ChartLoader {
// Update chart and redraw
chart.updateBounds()
chart.draw()
chart.draw(false)
this.addInteractivity()
}
})
@ -241,7 +241,7 @@ class ChartLoader {
window.addEventListener("resize", e => {
// Resize the chart canvas and redraw the chart
chart.resizeCanvas(this.parent, this.legend.offsetHeight)
chart.draw()
chart.draw(false)
// Reapply interactivity
this.addInteractivity()
@ -259,7 +259,7 @@ class ChartLoader {
// Update chart and redraw
chart.updateBounds()
chart.draw()
chart.draw(false)
this.addInteractivity()
this.mouseMoveFunc(e, chart)
@ -272,7 +272,7 @@ class ChartLoader {
*/
async addInteractivity() {
setTimeout(() => {
//console.time("2")
console.time("2")
// Set dimensions of effect canvas
this.effectCanvas.width = this.canvas.width
this.effectCanvas.height = this.canvas.height
@ -281,7 +281,7 @@ class ChartLoader {
this.detectionCanvas.height = this.canvas.height
// Draw detection map on the detection canvas
this.chart.drawDetectionMap(this.detectionCanvas.getContext("2d"))
//console.timeEnd("2")
console.timeEnd("2")
}, 0)
}
@ -291,6 +291,7 @@ class ChartLoader {
* @param {Array} data - The data to visualize on the chart.
*/
drawChart(chartSettings, data) {
console.time("1")
let zoomManager = new ZoomManager(chartSettings.horizontalZoom, chartSettings.verticalZoom)
// Choose the correct type of chart
@ -332,6 +333,8 @@ class ChartLoader {
this.chart.draw()
console.timeEnd("1")
this.addInteractivity()
this.addListeners(this.chart)
}

@ -17,83 +17,90 @@ class BarChart extends Chart {
/**
* Draws the bar chart on the canvas.
* @param {Boolean} async - Says if the chart should be drawn synchronously or asynchronously
*/
draw() {
draw(async = true) {
// Calculate the number of bars/categories in the chart
this.clear()
let barCount = this.data.length
// Draw the axis without displaying axis values
this.drawAxis(false)
// Define function for async
let fn = () => {
// Divide the space into equal section
// Calculate section size
let size = this.zoomBounds.width / this.dataLen
// Callculate inner size with margin
let innerSize = size * 0.8
// Width of each chart
let bar_width = innerSize * 0.7 / barCount // this.zoom.scaleX
// Divide the space into equal section
// Calculate section size
let size = this.zoomBounds.width / this.dataLen
// Callculate inner size with margin
let innerSize = size * 0.8
// Width of each chart
let bar_width = innerSize * 0.7 / barCount
// Iterate over each data point to draw the bars
for (let i = 0; i < this.dataLen; i++) {
// Counter to determine the position of each bar within a data point
let num = 0
// Iterate over each data point to draw the bars
for (let i = 0; i < this.dataLen; i++) {
// Counter to determine the position of each bar within a data point
let num = 0
this.data.forEach((categ, colId) => {
// Value of the bar
let value = categ.values[i]
// The left position of the bar in section
let left = this.zoomBounds.left + (size * (i + 0.15) + (innerSize * num / barCount))
// The height of the bar relative to the chart scale
let bar_height = value / this.extreme * this.scale * this.zoom.scaleY
// The top position of the bar
let top = this.zoomBounds.xAxis - categ.values[i] / this.extreme * this.scale * this.zoom.scaleY
this.data.forEach((categ, colId) => {
// Value of the bar
let value = categ.values[i]
// The left position of the bar in section
let left = this.zoomBounds.left + (size * (i + 0.15) + (innerSize * num / barCount))
// The height of the bar relative to the chart scale
let bar_height = value / this.extreme * this.scale * this.zoom.scaleY
// The top position of the bar
let top = this.zoomBounds.xAxis - categ.values[i] / this.extreme * this.scale * this.zoom.scaleY
// Increment the bar count
num++
// Increment the bar count
num++
// Create a new Rectangle object representing the current bar
let newObject = new Rectangle(this.ctx, value, colId, left, top, bar_width, bar_height)
// Add the new Rectangle object to the list of objects
this.objects.push(newObject)
// Create a new Rectangle object representing the current bar
let newObject = new Rectangle(this.ctx, value, colId, left, top, bar_width, bar_height)
// Add the new Rectangle object to the list of objects
this.objects.push(newObject)
// Check if the center of the new bar is within the bounds
if (this.isInBounds(newObject.getCenter())) {
// Set the fill color to the category color
this.ctx.fillStyle = categ.color
// Set the line width to 0 to prevent drawing the border
this.ctx.lineWidth = 0
// Draw the filled rectangle representing the current bar
newObject.draw()
}
})
}
// Check if the center of the new bar is within the bounds
if (this.isInBounds(newObject.getCenter())) {
// Set the fill color to the category color
this.ctx.fillStyle = categ.color
// Set the line width to 0 to prevent drawing the border
this.ctx.lineWidth = 0
// Draw the filled rectangle representing the current bar
newObject.draw()
}
})
}
// Draw x-axis labels if enabled
if (this.settings.displayAxisValues) {
// Restore canvas state to undo region clipping
this.ctx.restore()
// Loop through each data point to draw the labels
for (let i = 0; i < this.dataLen; i++) {
let text = (i + 1).toString()
// Draw x-axis labels if enabled
if (this.settings.displayAxisValues) {
// Restore canvas state to undo region clipping
this.ctx.restore()
// Loop through each data point to draw the labels
for (let i = 0; i < this.dataLen; i++) {
let text = (i + 1).toString()
// Begin drawing the text
this.ctx.beginPath()
this.ctx.font = "16px Arial"
this.ctx.fillStyle = "black"
this.ctx.textAlign = "center"
// Begin drawing the text
this.ctx.beginPath()
this.ctx.font = "16px Arial"
this.ctx.fillStyle = "black"
this.ctx.textAlign = "center"
// Calculate the position of the label
let x = this.zoomBounds.left + this.zoomBounds.width / this.dataLen * i + size / 2
let y = this.bounds.bottom + 15
// Calculate the position of the label
let x = this.zoomBounds.left + this.zoomBounds.width / this.dataLen * i + size / 2
let y = this.bounds.bottom + 15
// Draw the label text
this.ctx.fillText(text, x, y)
// Stroke the text
this.ctx.stroke()
// Close the path
this.ctx.closePath()
// Draw the label text
this.ctx.fillText(text, x, y)
// Stroke the text
this.ctx.stroke()
// Close the path
this.ctx.closePath()
}
}
}
// Draw the chart
if (this.settings.displayPoints)
async ? setTimeout(() => fn(), 0) : fn()
}
}

@ -249,6 +249,9 @@ class Chart {
// Filter objects based on the column ID
let objects = chartLoader.chart.objects.filter(object => object.colId == index)
// Add selected shape
if (chartLoader.selectedShapeIndex !== null)
objects.push(this.objects[chartLoader.selectedShapeIndex])
// Set effect canvas opacity and draw effect
chartLoader.effectCanvas.style.opacity = 1

@ -44,9 +44,6 @@ class PointChart extends Chart {
this.ctx.strokeStyle = this.settings.pointBorderColor
}
/*console.log(values)
console.log(this.dataLen)*/
// Iterate over the values to plot each data point
for (let i = 0; i < this.dataLen; i++) {
@ -76,19 +73,16 @@ class PointChart extends Chart {
/**
* Draws the entire PointChart
* @param {Boolean} async - Says if the chart should be drawn synchronously or asynchronously
*/
draw() {
draw(async = true) {
// Clear the canvas and draw the axis
this.clear()
this.drawAxis()
// Draw the data points
let fn = () => this.data.forEach((categ, colId) => { this.drawPoints(categ.values, colId, categ.color) })
if (this.settings.displayPoints)
setTimeout(() => {
console.time("1")
this.data.forEach((categ, colId) => { this.drawPoints(categ.values, colId, categ.color) })
console.timeEnd("1")
}, 0)
async ? setTimeout(() => fn(), 0) : fn()
}
}

@ -74,7 +74,7 @@ class Rectangle extends Shape {
getCenter() {
return {
x: this.x + this.w / 2,
y: 50
y: this.ctx.canvas.clientHeight / 2
}
}

@ -17,47 +17,54 @@ class SmoothLineChart extends PointChart {
/**
* Draws the smooth line chart on the canvas.
* @param {Boolean} async - Says if the chart should be drawn synchronously or asynchronously
*/
draw() {
draw(async = true) {
// Clear the canvas and draw the axis
this.clear()
this.drawAxis()
// Iterate over each category in the data
this.data.forEach(categ => {
// Begin a new path for drawing lines
this.ctx.beginPath()
this.ctx.lineJoin = "round"
this.ctx.strokeStyle = categ.color
// Calculate the starting point for the line
let pos1 = this.getPointPos(0, categ.values[0])
this.ctx.moveTo(pos1.x, pos1.y)
// Draw the Bezier curve for the smooth line
for (let i = 0; i < this.dataLen - 1; i++) {
// Calculate left point coordinates
let leftPos = this.getPointPos(i, categ.values[i])
// Calculate right point coordinates
let rightPos = this.getPointPos(i + 1, categ.values[i + 1])
// Find middle point
let xm = (leftPos.x + rightPos.x) / 2
// Find quarter points
let xl = (leftPos.x + xm) / 2
let xr = (rightPos.x + xm) / 2
// Draw a curve that smoothly connects the points
this.ctx.bezierCurveTo(xl, leftPos.y, xr, rightPos.y, rightPos.x, rightPos.y);
}
this.ctx.stroke()
this.ctx.closePath()
})
// Draw points on the chart if required
if (this.settings.displayPoints)
this.data.forEach((categ, colId) => {this.drawPoints(categ.values, colId, categ.color)})
// Define function for async
let fn = () => {
// Iterate over each category in the data
this.data.forEach(categ => {
// Begin a new path for drawing lines
this.ctx.beginPath()
this.ctx.lineJoin = "round"
this.ctx.strokeStyle = categ.color
// Calculate the starting point for the line
let pos1 = this.getPointPos(0, categ.values[0])
this.ctx.moveTo(pos1.x, pos1.y)
// Draw the Bezier curve for the smooth line
for (let i = 0; i < this.dataLen - 1; i++) {
// Calculate left point coordinates
let leftPos = this.getPointPos(i, categ.values[i])
// Calculate right point coordinates
let rightPos = this.getPointPos(i + 1, categ.values[i + 1])
// Find middle point
let xm = (leftPos.x + rightPos.x) / 2
// Find quarter points
let xl = (leftPos.x + xm) / 2
let xr = (rightPos.x + xm) / 2
// Draw a curve that smoothly connects the points
this.ctx.bezierCurveTo(xl, leftPos.y, xr, rightPos.y, rightPos.x, rightPos.y);
}
this.ctx.stroke()
this.ctx.closePath()
})
// Draw points on the chart if required
if (this.settings.displayPoints)
this.data.forEach((categ, colId) => { this.drawPoints(categ.values, colId, categ.color) })
}
// Draw the chart
if (this.settings.displayPoints)
async ? setTimeout(() => fn(), 0) : fn()
}
}

@ -24,7 +24,7 @@ class StackedChart extends Chart {
for (let i = 0; i < this.dataLen; i++) {
let sum = 0
this.data.forEach(categ => {
categ.values[i] = Math.abs(categ.values[i])
categ.values[i] = Math.abs(categ.values[i]) || 0
sum += categ.values[i]
})
largest = sum > largest ? sum : largest
@ -47,7 +47,7 @@ class StackedChart extends Chart {
this.data.forEach((categ, colId) => {
// Value of the bar segment
let value = categ.values[i]
let value = categ.values[i] || 0
// The height of the bar segment relative to the largest total value
let bar_height = value / largest * this.zoomBounds.height
// The left position of the bar segment

@ -1,153 +1,21 @@
/**
* Initializes variables and event listeners after the DOM content is loaded.
*/
let canvas, parent, legend, dataDiv, table
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)
})*/
})
/*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
function loadEventListeners() {
// Add click event listeners to toggle display of settings submenus
let labels = [...document.getElementsByClassName("submenuLabel")]
labels.forEach(label => {
label.addEventListener('click', e => {
let submenuDiv = e.target.nextElementSibling
// Toggle display of submenu
if (getComputedStyle(submenuDiv).display == "block") {
submenuDiv.style.display = "none"
label.classList.remove("arrow-up")
label.classList.add("arrow-down")
}
table.data = JSON.parse(result.data)
table.updateTable()
if (result.settings == null) {
alert("Error: no graph settings found")
} else {
loadSettings(JSON.parse(result.settings))
else {
submenuDiv.style.display = "block"
label.classList.remove("arrow-down")
label.classList.add("arrow-up")
}
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
}
}
}*/

@ -0,0 +1,153 @@
/**
* Initializes variables and event listeners after the DOM content is loaded.
*/
let canvas, parent, legend, dataDiv, table
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)
})*/
})
/*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
}
}
}*/

@ -47,20 +47,6 @@ class Table {
})
// Add click event listeners to toggle display of settings submenus
let labels = [...document.getElementsByClassName("submenuLabel")]
labels.forEach(label => {
label.addEventListener('click', e => {
let submenuDiv = e.target.nextElementSibling
// Toggle display of submenu
if (getComputedStyle(submenuDiv).display == "block")
submenuDiv.style.display = "none"
else
submenuDiv.style.display = "block"
})
})
this.rcAddRow.addEventListener("mousedown", (e) => { this.addRow() })
this.rcDelRow.addEventListener("mousedown", (e) => { this.delRow() })
this.rcAddCol.addEventListener("mousedown", (e) => { this.addCol() })
@ -141,7 +127,6 @@ class Table {
for (let j = 0; j < cells.length; j++) {
let currentCell = this.tableBody.querySelector(`#chart_table_${j}_values_${pos.row}`)
currentCell.value = ""
console.log(currentCell)
}
}
@ -238,11 +223,15 @@ class Table {
headCell.querySelector("input[type='color']").value = "#FFFFFF"
}
/**
* Deletes the selected column from the table.
*/
delCol() {
let rows = Array.from(this.tableBody.children)
let rowCount = rows.length
let colCount = this.tableBody.lastElementChild.children.length
// Shift existing column data to the left.
let pos = this.getCellPos(this.selectedCell)
for (let i = 0; i < rowCount; i++) {
for (let j = pos.col; j < colCount - 1; j++) {
@ -252,22 +241,26 @@ class Table {
}
}
// Shift existing column titles to the left.
for (let i = pos.col; i < colCount - 1; i++) {
let currentCell = this.tableHead.querySelector(`#chart_table_${i}_col_name`)
let previousCell = this.tableHead.querySelector(`#chart_table_${i + 1}_col_name`)
currentCell.value = previousCell.value
}
// Shift existing column colors to the left.
for (let i = pos.col; i < colCount - 1; i++) {
let currentCell = this.tableHead.querySelector(`#chart_table_${i}_color`)
let previousCell = this.tableHead.querySelector(`#chart_table_${i + 1}_color`)
currentCell.value = previousCell.value
}
// Remove the last cell from each row.
rows.forEach(row => {
row.removeChild(row.lastElementChild)
})
// Remove the last header cell.
this.tableHead.lastElementChild.removeChild(this.tableHead.lastElementChild.lastElementChild)
}
}

@ -23,27 +23,55 @@ main {
}
/* Styles for submenu label */
.submenuLabel + div {
.submenuLabel+div {
display: none;
}
/* Styles for chart metadata groups */
div[id^="chart_metadata_group"] {
padding: 0.5em; /* Padding around metadata groups */
margin-bottom: 0.5em; /* Margin below metadata groups */
background-color: var(--side); /* Background color */
padding: 0.5em;
/* Padding around metadata groups */
margin-bottom: 0.5em;
/* Margin below metadata groups */
background-color: var(--side);
/* Background color */
}
/* Style for arrow after submenu label */
.submenuLabel::after {
content: " ";
border: solid black;
border-width: 0 2px 2px 0;
display: inline-block;
padding: 0.2rem;
margin-left: 0.5rem;
}
.arrow-down::after {
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
}
.arrow-up::after {
transform: rotate(225deg);
-webkit-transform: rotate(225deg);
}
/* Styles for the table container div */
#tableDiv {
padding: 0; /* Remove padding */
overflow: auto; /* Add scrollbars if content overflows */
flex-basis: 100%; /* Set the size of the table area */
padding: 0;
/* Remove padding */
overflow: auto;
/* Add scrollbars if content overflows */
flex-basis: 100%;
/* Set the size of the table area */
}
/* Styles for secondary div */
#secondaryDiv {
display: flex; /* Use flexbox layout */
display: flex;
/* Use flexbox layout */
}
/* Styles for table elements */
@ -55,7 +83,8 @@ div[id^="chart_metadata_group"] {
#dataTable td,
#dataTable th {
height: 2em; /* Set height of table cells */
height: 2em;
/* Set height of table cells */
}
/* Styles for table input elements */
@ -106,7 +135,7 @@ div[id^="chart_metadata_group"] {
width: 180px;
}
#rcMenu ul{
#rcMenu ul {
list-style-type: none;
padding-left: 10px;
width: 180px;
@ -119,7 +148,7 @@ div[id^="chart_metadata_group"] {
display: block;
}
#rcMenu a:hover{
#rcMenu a:hover {
background-color: lightgrey;
}

@ -18,14 +18,14 @@ class ChartRestController extends AbstractRestController
#[Rest\Get('/', name: '_list')]
public function list(DocumentManager $dm, Request $request) : Response
{
$rooms = \array_map(fn(Chart $entity) => ChartOutput::fromEntity($entity), $dm->getRepository(Chart::class)->findAll);
return $this->respond($rooms, Response::HTTP_OK);
$charts = \array_map(fn(Chart $entity) => ChartOutput::fromEntity($entity)->id, $dm->getRepository(Chart::class)->findAll());
return $this->respond($charts, Response::HTTP_OK);
}
#[Rest\Get('/{id}', name: '_detail', requirements: ['id' => '\d+'])]
public function detail(DocumentManager $dm, int $id): Response
#[Rest\Get('/{id}', name: '_detail')]//, requirements: ['id' => '\d+'])]
public function detail(DocumentManager $dm, Chart $chart): Response
{
$chart = $this->findOrFail($dm, $id);
//$chart = $this->findOrFail($dm, $id);
$chartDto = ChartOutput::fromEntity($chart);
return $this->respond( $chartDto, Response::HTTP_OK);
@ -47,13 +47,15 @@ class ChartRestController extends AbstractRestController
return $this->respond( $chart->getName(), Response::HTTP_OK);
}
private function findOrFail(DocumentManager $dm, int $id): Chart
/*private function findOrFail(DocumentManager $dm, int $id): Chart
{
$room = $dm->getRepository(Chart::class)->findOneBy(['code' => $id]);
if ($room === null) {
//$chart = $dm->getRepository(Chart::class)->findOneBy(['code' => $id]);
$chart = $dm->getRepository(Chart::class)->findOneBy(['_id' => $id]);
if ($chart === null) {
throw $this->createNotFoundException("Chart was not found");
}
return $room ;
}
return $chart ;
}*/
}

@ -11,21 +11,21 @@ use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Redirect;
use Symfony\Component\Routing\Annotation\Route;
#[Route(path: '/charts', name: 'charts')]
class ChartController extends AbstractController
{
/*#[Route('/charts', name: 'list_charts')]
public function registerAction(): Response
#[Route('/', name: '_list')]
public function list(DocumentManager $dm, Request $request) : Response
{
//$form = $this->createForm(RegistrationType::class, new Registration());
return $this->render('.html.twig', []);
}*/
$charts = $dm->getRepository(Chart::class)->findAll();
return $this->render('list.html.twig', [
'charts' => $charts
]);
}
#[Route('/charts/{id}/edit', name: 'edit_chart', requirements: ['id' => '\d+'])]
public function editAction(DocumentManager $dm, Request $request, int $id)
#[Route('/{id}/edit', name: '_edit')]
public function editAction(DocumentManager $dm, Request $request, Chart $chart) : Response
{
$chart = ($id !== null) ? $this->findOrFail($dm, $id) : new Chart();
$form = $this->createForm(ChartType::class, $chart);
$form->handleRequest($request);
@ -39,21 +39,20 @@ class ChartController extends AbstractController
}
return $this->render('edit.html.twig', [
'chartForm' => $form
'chartForm' => $form,
'id' => $chart->getId(),
]);
}
#[Route('/charts/{id}', name: 'display_chart', requirements: ['id' => '\d+'])]
public function displayAction(DocumentManager $dm, Request $request, int $id)
#[Route('/{id}', name: '_display')]
public function displayAction(DocumentManager $dm, Chart $chart) : Response
{
$chart = ($id !== null) ? $this->findOrFail($dm, $id) : new Chart();
return $this->render('chart.html.twig', [
'code' => $id
'id' => $chart->getId()
]);
}
private function findOrFail(DocumentManager $dm, int $id): Chart
/*private function findOrFail(DocumentManager $dm, int $id): Chart
{
$chart = $dm->getRepository(Chart::class)->findOneBy(['code' => $id]);
//$chart = $dm->getRepository(Chart::class)->findAll();
@ -62,5 +61,5 @@ class ChartController extends AbstractController
}
return $chart;
}
}*/
}

@ -17,13 +17,16 @@ class ChartType extends AbstractType
$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'*/
]);
->add('metadata', MetadataType::class);
if (sizeof($options['data']->getTable()[0]['values']) <= 1000)
$builder
->add('table', CollectionType::class, [
'entry_type' => ColumnType::class,
'allow_add' => true,
/*'prototype' => true,
'prototype_data' => 'Placeholder'*/
]);
}
public function configureOptions(OptionsResolver $resolver)

@ -1,6 +1,7 @@
<?php
namespace App\Form\Type;
use App\Document\Chart;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\Extension\Core\Type\ColorType;
@ -16,7 +17,7 @@ class ColumnType extends AbstractType
$builder
->add('col_name', TextType::class, [
'label' => false,
'attr'=>['autocomplete' => 'off']
'attr' => ['autocomplete' => 'off']
])
->add('color', ColorType::class, [
'label' => false,
@ -26,7 +27,7 @@ class ColumnType extends AbstractType
'allow_add' => true,
'entry_options' => [
'label' => false,
'attr'=>['autocomplete' => 'off']
'attr' => ['autocomplete' => 'off']
],
'required' => false
]);

@ -38,19 +38,26 @@ class MetadataType extends AbstractType
],
'label' => 'Chart type',
])
->add('margin', IntegerType::class, [
'label' => 'Margin',
'required' => false,
'constraints' => [
new Assert\PositiveOrZero()
],
])
->add(
$builder->create('group0', FormType::class, [
'inherit_data' => true,
'label' => 'Margin settings',
'label_attr' => ['class' => 'submenuLabel arrow-down']
])
->add('margin', IntegerType::class, [
'label' => 'Margin',
'required' => false,
'constraints' => [
new Assert\PositiveOrZero()
],
])
)
// Title settings
->add(
$builder->create('group1', FormType::class, [
'inherit_data' => true,
'label' => 'Title settings',
'label_attr' => ['class' => 'submenuLabel']
'label_attr' => ['class' => 'submenuLabel arrow-down']
])
->add('title', TextType::class, [
'label' => 'Title',
@ -71,7 +78,7 @@ class MetadataType extends AbstractType
$builder->create('group2', FormType::class, [
'inherit_data' => true,
'label' => 'Labels',
'label_attr' => ['class' => 'submenuLabel']
'label_attr' => ['class' => 'submenuLabel arrow-down']
])
->add('xLabel', TextType::class, [
'label' => 'X label',
@ -106,7 +113,7 @@ class MetadataType extends AbstractType
$builder->create('group3', FormType::class, [
'inherit_data' => true,
'label' => 'Legend settings',
'label_attr' => ['class' => 'submenuLabel']
'label_attr' => ['class' => 'submenuLabel arrow-down']
])
->add('displayLegend', CheckboxType::class, [
'label' => 'Display legend',
@ -122,7 +129,7 @@ class MetadataType extends AbstractType
$builder->create('group4', FormType::class, [
'inherit_data' => true,
'label' => 'Point Settings',
'label_attr' => ['class' => 'submenuLabel']
'label_attr' => ['class' => 'submenuLabel arrow-down']
])
->add('displayPoints', CheckboxType::class, [
'label' => 'Display points',
@ -152,7 +159,7 @@ class MetadataType extends AbstractType
$builder->create('group5', FormType::class, [
'inherit_data' => true,
'label' => 'Zoom Settings',
'label_attr' => ['class' => 'submenuLabel']
'label_attr' => ['class' => 'submenuLabel arrow-down']
])
->add('horizontalZoom', CheckboxType::class, [
'label' => 'Enable horizontal zoom',
@ -167,20 +174,22 @@ class MetadataType extends AbstractType
'label' => 'Background color',
'required' => false,
])
->add('submit', SubmitType::class, ['label' => 'Provést']);
->add('submit', SubmitType::class, ['label' => 'Uložit a vykreslit']);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'constraints' => array(
new Assert\Callback(function($data){
// $data is instance of object (or array) with all properties
// you can compare Count1, Count2 and Count 3
// and raise validation errors
})
$resolver->setDefaults(
array(
'constraints' => array(
new Assert\Callback(function ($data) {
// $data is instance of object (or array) with all properties
// you can compare Count1, Count2 and Count 3
// and raise validation errors
})
)
)
));
);
/*$resolver->setDefaults([
'type' => 'point',
'margin'=> 5,

@ -38,7 +38,7 @@
// Create ChartLoader instance
let chartLoader = new ChartLoader(canvas, effectCanvas, detectionCanvas, parent, legend, tooltip)
chartLoader.loadData({{ code }})
chartLoader.loadData({{ id | json_encode() | raw() }})
})
</script>
{% endblock %}

@ -9,16 +9,19 @@
{% block javascripts %}
{{ parent() }}
<script type="text/javascript" src={{ asset('/scripts/table.js') }}></script>
<script>
// Execute when DOM content is fully loaded
document.addEventListener("DOMContentLoaded", function(event){
// Get DOM elements
let tableElement = document.getElementById("dataTable")
let rcMenu = document.getElementById("rcMenu")
<script type="text/javascript" src={{ asset('/scripts/edit_chart.js') }}></script>
<script>
// Execute when DOM content is fully loaded
document.addEventListener("DOMContentLoaded", function (event) { // Get DOM elements
loadEventListeners()
let tableElement = document.getElementById("dataTable")
let rcMenu = document.getElementById("rcMenu")
let table = new Table(tableElement, rcMenu)
})
</script>
})
</script>
{% endblock %}
{% block title %}
@ -30,36 +33,40 @@
<main>
{{ form_start(chartForm) }}
<div id="mainDiv">
<iframe id="chartDiv" src={{ "https://spacek.blue/charts/" ~ field_value(chartForm.code) }}></iframe>
<div id="settings_div">
{{ form_row(chartForm.name) }}
{{ form_row(chartForm.code) }}
{{ form_row(chartForm.name) }}
{{ form_row(chartForm.code) }}
{{ form_row(chartForm.metadata) }}
<!--<button id="saveBtn">Save</button>
<button id="drawBtn">Draw</button>-->
<button id="drawBtn">Draw</button>-->
</div>
<iframe id="chartDiv" src={{ "https://spacek.blue/charts/" ~ id }}></iframe>
</div>
<div id="secondaryDiv">
<div id="tableDiv">
<table id="dataTable">
<thead>
<tr>
{% for col in chartForm.table %}
<th>{{ form_row(col.col_name) }}{{ form_row(col.color) }}</th>
{% endfor %}
</tr>
</thead>
{% for i in 0..chartForm.table[0].values|length-1 %}
<tr>
{% for col in chartForm.table %}
<td>{{ form_row(col.values[i]) }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
{% if chartForm.table is defined %}
<table id="dataTable">
<thead>
<tr>
{% for col in chartForm.table %}
<th>{{ form_row(col.col_name) }}{{ form_row(col.color) }}</th>
{% endfor %}
</tr>
</thead>
{% for i in 0..chartForm.table[0].values|length-1 %}
<tr>
{% for col in chartForm.table %}
<td>{{ form_row(col.values[i]) }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
{% else %}
<strong>Příliš mnoho hodnot, použijte API</strong>
{% endif %}
</div>
</div>
{{ form_end(chartForm) }}
{{ form_end(chartForm) }}
<div id="rcMenu">
<ul>
<li><a id="rcAddRow" href="">add row</a></li>

@ -3,7 +3,7 @@
<a href={{ path('homepage') }}>EasyCharts</a>
</div>
<nav>
<a href="docs.html">Documentation</a>
<a href={{ path('charts_list') }}>Charts</a>
</nav>
<div id="user">
<a href={{ path('register') }}>Login</a>

@ -0,0 +1,16 @@
{% extends 'base.html.twig' %}
{% block title %}
List
{% endblock %}
{% block body %}
{{ parent() }}
<main>
<ul>
{% for chart in charts %}
<li><a href={{ chart.id ~ "/edit" }}>{{ chart.name }}</a></li>
{% endfor %}
</ul>
</main>
{% endblock %}
Loading…
Cancel
Save

Powered by TurnKey Linux.