Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add data visualization feature #1673

Closed
renegades12 opened this issue Apr 30, 2020 · 27 comments
Closed

Add data visualization feature #1673

renegades12 opened this issue Apr 30, 2020 · 27 comments
Milestone

Comments

@renegades12
Copy link

It might be a good idea to integrate chart.js to the theme as default and leave an option in the config file.
image
examples

@luiscachog
Copy link

+1 on this feature!!

@gcushen
Copy link
Collaborator

gcushen commented Apr 30, 2020

Plotly.js may be a better option to explore initially since a significant number of users are already using Plotly with Python/R for data analytics/science?

@YonghuiDong
Copy link

I use plotly. It is easy to use, you should have a try.

@gcushen gcushen changed the title Integrating Chart.js to the theme Add data visualization feature Apr 30, 2020
@renegades12
Copy link
Author

@YonghuiDong I would like to try! Do you have tutorials that I could refer to?

@gcushen gcushen added this to the dtat milestone May 1, 2020
@YonghuiDong
Copy link

YonghuiDong commented May 2, 2020

@renegades12 You can check this website: https://plotly.com/graphing-libraries/.

@Bertbk
Copy link
Contributor

Bertbk commented May 5, 2020

@gcushen I also prefer PlotlyJs but there is currently an issue using MathJax v3 and plotlyjs: plotly cannot be loaded. The problem comes from plotlyjs.

See the issue

@HughP
Copy link

HughP commented May 13, 2020

In a lot of my work I'm interested in GIS maps and data. I have looked at amCharts several times: https://www.amcharts.com/ it is not maybe the best fit for this project, but I'd hope that what ever plotting lib was chosen would also support GIS displays. I'm coming at this from a sans R position. I do not use any of the R tooling with Academic.

@Bertbk
Copy link
Contributor

Bertbk commented May 13, 2020

@HughP It seems to be a powerful library. It's a freeware (free of charge if we let an attribution). The source code is available but I do not think it is "open-source" (?) If so, this might be a no-go for certain users.

@lucasfr
Copy link

lucasfr commented May 19, 2020

@gcushen I also prefer PlotlyJs but there is currently an issue using MathJax v3 and plotlyjs: plotly cannot be loaded. The problem comes from plotlyjs.

See the issue

I can't thank you enough for this. Spent hours trying to understand why Plotly wouldn't work with Hugo for me. Is there an alternative to MathJax v3 that could work with Plotly and Hugo? I also do prefer support to Plotly.

@Bertbk
Copy link
Contributor

Bertbk commented May 19, 2020

@lucasfr As far as I know: no. It's simply impossible to use PlotlyJS + Mathjax v3. The problem does not come from Hugo but from PlotlyJs. It checks if mathjax has been loaded, if that is the case, plotlyjs does some stuff about configuration of MathJax, which does not work with mathjax v3 (breaking changes from v2 to v3), leading to a crash of plotlyjs.

As I still use plotlyjs, I simply turn off Mathjax on the pages where I use plotlyjs (math = false). This is quite ugly, I know... :)

@lucasfr
Copy link

lucasfr commented May 19, 2020

@Bertbk thank you. It worked for me too. However I am between a rock and a hard place as I need both some support to maths and plotly. Have even considering going back to MathJaxV2 but haven't been very successful, as I'm not very skilled with CSS and JS.

@Bertbk
Copy link
Contributor

Bertbk commented May 19, 2020

going back to MathJaxV2

That should be easy to do: In the page you want to use mathjax2, ...

  • set math=false
  • add these lines in the end of the .md file (in the body, with your markdown)
<script async src="https://cdn.jsdelivr.net/npm/mathjax@2/MathJax.js?config=TeX-AMS-MML_CHTML"></script>

You can also create a /layouts/partials/custom_js.html (you might need to create the folder, this is NOT in the /themes/academic folder!) file with this inside

<script async src="https://cdn.jsdelivr.net/npm/mathjax@2/MathJax.js?config=TeX-AMS-MML_CHTML"></script>

The problem is that you would need to set math=false everywhere. You can add a parameter, though, but I believe the first solution is the best: it does not affect the other pages and you can revert to MathJax3 easily.

@lucasfr
Copy link

lucasfr commented May 19, 2020

@Bertbk Thank you for the suggestions. I have tried on both .md and .Rmd files without success. It keeps showing equations either between $ $ or \( \).

@Bertbk
Copy link
Contributor

Bertbk commented May 20, 2020

@lucasfr We should switch to the forum and we'll find a solution :)

@HACLLALEX
Copy link

I try to build a chart as a default theme using chartjs. I am using Academia Hugo to be my main theme. Also, There are 3 file added including a json, a theme html and a md.

In the markdown file, I have add a tag called "[chart]". User can thougth this tag to get the new theme. In addition, I create 2 choices to generate a chart. The first one is using JSON. the user just needs to put a json into the tag called "json", then the chart will be generated. The second one is using tag for insert or edit the chart detail. Details as follows:

chart.md


+++
# A section created with the Chart widget.
widget = "chart"  # See https://sourcethemes.com/academic/docs/page-builder/
headless = true  # This file represents a page section.
active = true  # Activate this widget? true/false
weight = 22  # Order that this section will appear.

# Note: a full width section format can be enabled by commenting out the `title` and `subtitle` with a `#`.
title = "Chart"
subtitle = ""
[design]
  # Choose how many columns the section has. Valid values: 1 or 2.
  columns = "2"
  format = "2"  # Change the chart and text position. Valid values: 1 or 2.

[design.background]
  # Apply a background color, gradient, or image.
  #   Uncomment (by removing `#`) an option to apply it.
  #   Choose a light or dark text color by setting `text_color_light`.
  #   Any HTML color name or Hex value is valid.

  # Background color.
  # color = "navy"
  
  # Background gradient.
  # gradient_start = "DeepSkyBlue"
  # gradient_end = "SkyBlue"
  
  # Background image.
  # image = "image.jpg"  # Name of image in `static/img/`.
  # image_darken = 0.6  # Darken the image? Range 0-1 where 0 is transparent and 1 is opaque.

  # Text color (true=light or false=dark).
  # text_color_light = true

[design.spacing]
  # Customize the section spacing. Order is top, right, bottom, left.
  # padding = ["0px", "0px", "0px", "0px"]

[advanced]
 # Custom CSS. 
 css_style = ""
 
 # CSS class.
 css_class = ""
 
 [chart]
 #2 Style for generate chart
 
 #Using JSON to generate a chart
 json="../json/testData3.json"
 
 #Using tag to generate a chart
 id = "myChart"
 chart_label = "Source Rank"
 backgroundColor = "rgba(255,207,47,0.6)"
 borderColor = "rgba(255,207,47)"
 borderWidth = "2"
 yGridLines = "false"
 xGridLines = "false"
 type = ""
 data = "a:1,b:2,c:3,d:4,e:5"

+++

In the html file, If you want to using the the second choice, you need to uncomment the code first, and then comment the getjson part. Also, you need to put the html file to the theme file first.

chart.html


<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels"></script>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
{{ $st := .page }}
{{ $columns := $st.Params.design.columns | default "2" }}
{{ $format := $st.Params.design.format | default "1" }}
<div class="row">
  {{ if ne $columns "1" }}
    <div class="col-12 section-heading text-center">
      {{ with $st.Title }}<h1>{{ . | markdownify | emojify }}</h1>{{ end }}
      {{ with $st.Params.subtitle }}<p>{{ . | markdownify | emojify }}</p>{{ end }}	  
	
	</div>

	{{ if eq $st.Content "" }}
		<div class="col-12">
			<!--<canvas id="{{ $st.Params.chart.id}}" width="600" height="400"></canvas>-->
			<div id="chartInfo" class="chartInfo"></div>
			
		</div>
	{{ else }}
		{{ if eq $format "1"  }}
			<div class="col-12 col-lg-6">
				<!--<canvas id="{{ $st.Params.chart.id}}" width="600" height="400"></canvas>-->
				<div id="chartInfo" class="chartInfo"></div>
			</div>
			<div class="col-12 col-lg-6">
				{{ $st.Content }}
			</div>
		{{ else }}
			<div class="col-12 col-lg-6">
				{{ $st.Content }}
			</div>
			<div class="col-12 col-lg-6">
				<!--<canvas id="{{ $st.Params.chart.id}}" width="600" height="400"></canvas>-->
				<div id="chartInfo" class="chartInfo"></div>
			</div>
		{{ end }}
	{{ end }}
	
  {{ else }}
    <div class="col-12">
      {{ with $st.Title }}<h1>{{ . | markdownify | emojify }}</h1>{{ end }}
      {{ with $st.Params.subtitle }}<p>{{ . | markdownify | emojify }}</p>{{ end }}
	</div>
	{{ if eq $st.Content "" }}
		<div class="col-12">
			<!--<canvas id="{{ $st.Params.chart.id}}" width="600" height="400"></canvas>-->
			<div id="chartInfo" class="chartInfo"></div>
		</div>
	{{ else }}
		{{ if eq $format "1"  }}
			<div class="col-12 col-lg-6">
				<!--<canvas id="{{ $st.Params.chart.id}}" width="600" height="400"></canvas>-->
				<div id="chartInfo" class="chartInfo"></div>
			</div>
			<div class="col-12 col-lg-6">
				{{ $st.Content }}
			</div>
		{{ else }}
			<div class="col-12 col-lg-6">
				{{ $st.Content }}
			</div>
			<div class="col-12 col-lg-6">
				<!--<canvas id="{{ $st.Params.chart.id}}" width="600" height="400"></canvas>-->
				<div id="chartInfo" class="chartInfo"></div>
			</div>
		{{ end }}
	{{ end }}
  {{ end }}
</div>
<script>

console.log("chart ");
	//console.log({{ $st.Content }});
	var id = {{ $st.Params.chart.id }};
	var text = {{ $st.Params.chart.text }};
	var label = {{$st.Params.chart.chart_label }};
	var backgroundColor = {{ $st.Params.chart.backgroundColor }};
	var borderColor = {{ $st.Params.chart.borderColor }};
	var borderWidth = {{ $st.Params.chart.borderWidth }};
	var yGridLines = {{ $st.Params.chart.yGridLines }};
	var xGridLines = {{ $st.Params.chart.xGridLines }};
	var chartData = {{ $st.Params.chart.data }};
	var test = {{ $st.Params.chart.id }};
	var json = {{ $st.Params.chart.json }};
	var canvasCount = 0;
	
	console.log(json);
	console.log(id);
	//console.log(label);
	//console.log(text);
	//console.log(chartData);
	//console.log("label: " + label + " backgroundColor: " + backgroundColor + " borderColor: " + borderColor + " borderWidth: " + borderWidth + " yGridLines: " + yGridLines + " xGridLines: " + xGridLines );
	
	//getJSON part
	$.getJSON(json, function (result) { 
		console.log("getJson");
		console.log(result);
		canvasCount = $('canvas').length;
		console.log(canvasCount);
		var num = 0;
		if(canvasCount == 0){
			var t_canvas = document.createElement("canvas");
			t_canvas.style.width = "600px";
			t_canvas.style.height = "400px";
			$(".chartInfo")[canvasCount].appendChild(t_canvas);
			var barChart = new Chart(t_canvas, result);
	
		} else if((canvasCount != 0)){
			var t_canvas = document.createElement("canvas");
			for(var i=0;i<canvasCount;i++){
				num++;
				t_canvas.style.width = "600px";
				t_canvas.style.height = "400px";
				$(".chartInfo")[num].appendChild(t_canvas);
				console.log("num: " + num);
			}
			var barChart = new Chart(t_canvas, result);
		}
	})
	.fail(function (jqxhr, status, error) { 
		console.log('alert', status, error) }
	);


	/*
	//the other choice
	canvasCount = $('canvas').length;
	console.log(canvasCount);
	var num = 0;
	if(canvasCount == 0){
		var t_canvas = document.createElement("canvas");
		t_canvas.style.width = "600px";
		t_canvas.style.height = "400px";
		$(".chartInfo")[canvasCount].appendChild(t_canvas);
		var chars = chartData.split(',');
		console.log(chars);
		
		var myMap = new Map();
	
		for(var i=0;i<chars.length;i++){
			var char = chars[i].split(':');
			console.log(char);
			for(var j=0;j<char.length;j++){
				myMap.set(char[0],char[1])
			}
		}
		
		const mapSort1 = new Map([...myMap.entries()].sort((a, b) => b[1] - a[1]));
		console.log(mapSort1);
		
		var t_arr1 =[];
		var t_arr2 = [];
		
		for(var [key,value] of mapSort1){
			//console.log(key + "," + value);
			t_arr1.push(key);
			t_arr2.push(value);
		}
		console.log(t_arr1);
		console.log(t_arr2);
		
		var chartData = {
		  label: label,
		  data: t_arr2,
		  backgroundColor: backgroundColor,
		  borderColor: borderColor,
		  borderWidth: 2,
		  hoverBorderWidth: 0
		};

		var chartOptions = {
		  scales: {
			yAxes: [{
			  categoryPercentage: 1.5,
			  barPercentage: 0.5,
			  gridLines: {
				display:false
			  }
			}],
			xAxes: [{
			  gridLines: {
				display:false
			  }
			}],
		  },
		  elements: {
			rectangle: {
			  borderSkipped: 'center',
			}
		  },
		  tooltips: {
			enabled: false
		  },
		  hover: {
			  animationDuration: 0
		  },
		  plugins: {
			datalabels: {
				color: 'rgb(0,0,0)',
				anchor: 'end',
				align: 'end'				
			}
		  }
		};
		
		var barChart = new Chart(t_canvas, {
		  type: 'horizontalBar',
		  data: {
			labels: t_arr1,
			datasets: [chartData],
		  },
		  options: chartOptions
		});

	} else if((canvasCount != 0)){
		
		var t_canvas = document.createElement("canvas");
		for(var i=0;i<canvasCount;i++){
			num++;
			t_canvas.style.width = "600px";
			t_canvas.style.height = "400px";
			$(".chartInfo")[num].appendChild(t_canvas);
			console.log("num: " + num);
		}
		var chars = chartData.split(',');
		console.log(chars);
		
		var myMap = new Map();
	
		for(var i=0;i<chars.length;i++){
			var char = chars[i].split(':');
			console.log(char);
			for(var j=0;j<char.length;j++){
				myMap.set(char[0],char[1])
			}
		}
		
		const mapSort1 = new Map([...myMap.entries()].sort((a, b) => b[1] - a[1]));
		console.log(mapSort1);
		
		var t_arr1 =[];
		var t_arr2 = [];
		
		for(var [key,value] of mapSort1){
			//console.log(key + "," + value);
			t_arr1.push(key);
			t_arr2.push(value);
		}
		console.log(t_arr1);
		console.log(t_arr2);
		
		var chartData = {
		  label: label,
		  data: t_arr2,
		  backgroundColor: backgroundColor,
		  borderColor: borderColor,
		  borderWidth: 2,
		  hoverBorderWidth: 0
		};

		var chartOptions = {
		  scales: {
			yAxes: [{
			  categoryPercentage: 1.5,
			  barPercentage: 0.5,
			  gridLines: {
				display:false
			  }
			}],
			xAxes: [{
			  gridLines: {
				display:false
			  }
			}],
		  },
		  elements: {
			rectangle: {
			  borderSkipped: 'center',
			}
		  },
		  tooltips: {
			enabled: false
		  },
		  hover: {
			  animationDuration: 0
		  },
		  plugins: {
			datalabels: {
				color: 'rgb(0,0,0)',
				anchor: 'end',
				align: 'end'				
			}
		  }
		};
		
		var barChart = new Chart(t_canvas, {
		  type: 'horizontalBar',
		  data: {
			labels: t_arr1,
			datasets: [chartData],
		  },
		  options: chartOptions
		});
		
	}
	*/
		
</script>

testData.json


{	
	"type": "horizontalBar",
	"data": {
		"labels": ["apple", "banana", "orange", "lemon", "punch", "melon", "pear", "cherry", "mango", "strawberry", "coconut"],
		"datasets": [{
			"label": "fruit value",
			"data": ["23", "21", "19", "18", "17", "16", "16", "15", "11", "9", "9"],
			"backgroundColor": "rgba(255,207,47,0.6)",
			"borderColor": "rgba(255,207,47,0.6)",
			"borderWidth": "2",
			"hoverBorderWidth": "0"
		}]
	},
	"options": {
		"scales": {
			"yAxes": [{
				"categoryPercentage": "1.5",
				"barPercentage": "0.5",
				"gridLines": {
					"display":false
				}
			}],
			"xAxes": [{
				"gridLines": {
					"display":false
				}
			}]
		},
		"elements": {
			"rectangle": {
				"borderSkipped": "center"
			}
		},
		"tooltips": {
			"enabled": false
		},
		"hover": {
			"animationDuration": "0"
		},
		"plugins": {
			"datalabels": {
				"color": "rgb(0,0,0)",
				"anchor": "end",
				"align": "end"	
			}
		}
	}
}


@HughP
Copy link

HughP commented Jun 16, 2020 via email

@HACLLALEX
Copy link

HACLLALEX commented Jun 17, 2020

@HughP Thank you for the reply, I will try it. If there is any questions please feel free to let me know.

@HughP
Copy link

HughP commented Jun 17, 2020

@HACLLALEX do you have a demonstration website working with this code? or a git repo? I'm trying to follow along on my own website. Is this chart designed to be on the main page (or some other page that uses widgets OR is this chart designed to be in a blog post, embedded in some sort of .md file (talk, course, project, etc)?

@HACLLALEX
Copy link

HACLLALEX commented Jun 17, 2020

@HughP This is the git repo with this code.
The chart is designed to be a widgets.

html file location:

themes\academia-hugo\layouts\partials\widgets\chart.html

markdown file location:

content\home\chart.md

Json file location:

static\json

hope this helps

@HACLLALEX
Copy link

HACLLALEX commented Jun 19, 2020

I make a shortcode to generate a chart by JSON and I have some update of my code.
For the shortcode, I add an HTML file and the location is

hugo-with-chartjs/layouts/shortcodes/chart.html

if you want to use this shortcode. You need to add the code like {{< chart id="[chartId]" json="[JSON]" >}} into the markdown file. Then, the Chart will be generated.

Simple location:

hugo-with-chartjs/content/home/shortcode.md

For the update of my code, To clearly for building chart. I rewrite the HTML file which is designed to be a widget. If you insert id and a JSON into each tag like

 [chart] 
 #Using JSON to generate a chart
 id = "myChart2"
 json="../json/testData4.json"

Then, the chart will be generated. Besides, I have kept the old version and the location will be

hugo-with-chartjs/themes/academia-hugo/layouts/partials/widgets/chart_16062020.html

my git repo is updated too. Please have a look at it.

@lucasfr
Copy link

lucasfr commented Jun 20, 2020

@Bertbk

According to this new comment on Plotly repository, it is possible to load Plotly and MathJax v3. Has anyone tried this on Hugo + Academic?

plotly/plotly.js#4563 (comment)

@Bertbk
Copy link
Contributor

Bertbk commented Jun 22, 2020

@lucasfr It works like a charm! Thanks!

@gcushen Using plotly + MathJax 3 works with hugo+academic, provided this line is set before loading plotly (it's still kind of a hack...)

<script>
  window.PlotlyConfig = {MathJaxConfig: 'local'}
</script>

For others, if you are interested, this is part of my layouts/partials/custom_head.html file:

{{ if .Params.plotly }}
<script>
  window.PlotlyConfig = {MathJaxConfig: 'local'}
</script>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
{{ end }}

A plotly = true parameters has to be set in the frontmatter of my markdown file where I want plotly to be displayed.

@lucasfr
Copy link

lucasfr commented Jun 23, 2020

Thank you for the guidance, @Bertbk. Worked here too...

@aashigupta19
Copy link

Hey, I and my team would like to give it a try if you allow us? @Bertbk @renegades12 @gcushen

@gcushen
Copy link
Collaborator

gcushen commented Aug 24, 2020

Documentation and demo:

Possible future improvements (feel free to submit a PR):

  • show progress indicator whilst loading plot

@HughP
Copy link

HughP commented Aug 25, 2020

Is this in the 4.8 branch or the 5.0 branch. The netify hosted Academic site which has documentation for the chart in it has the latest version as 4.8 but I would expect a new feature to be added to the WIP version... Which one do I need to clone?

@rodrigoalcarazdelaosa
Copy link
Contributor

Is this in the 4.8 branch or the 5.0 branch. The netify hosted Academic site which has documentation for the chart in it has the latest version as 4.8 but I would expect a new feature to be added to the WIP version... Which one do I need to clone?

You want to clone the latest master

JungPhilipp pushed a commit to JungPhilipp/hugo-academic that referenced this issue Feb 17, 2021
Adds chart shortcode with support for Plotly JSON chart format.

Given Plotly formatted line-chart.json in page bundle, use
{{< chart data="line-chart" >}}

Close HugoBlox#1673
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants