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

How to add dynamic charts using Cedar #81

Closed
hhkaos opened this issue Oct 21, 2017 · 4 comments
Closed

How to add dynamic charts using Cedar #81

hhkaos opened this issue Oct 21, 2017 · 4 comments

Comments

@hhkaos
Copy link
Member

hhkaos commented Oct 21, 2017

I would like to add some dynamic charts using Cedar to my storymap, something like this:

screen shot 2017-10-21 at 18 40 46

So the first approach I'm trying is adding this simple Cedar example to the storymap.

Note: I have publish the source code in this repo

As you would notice everything works in development environment (using grunt server and opening localhost:8080/src/?appid=d2134b4665df4fdea6077a9255315484), you just need to click the second bullet "Población de Madrid" to check it. But after running grunt the deployed app doesn't. It is because I'm not adding the libraries properly as you can notice in the console (you see the problem opening this deployment).

screen shot 2017-10-21 at 18 53 46

I tried to follow all the instructions @ssylvia gave in this talk, so what I did is:

Step 1) I added a DOM element to the storymap item using the WYSIWYG builder

<div id="chart">&nbsp;</div>

Step 2) Then I added the libraries directly to the src/index.html (this is by my own xD)

<script type="text/javascript" src="lib-app/cedar/d3.min.js"></script>
<script type="text/javascript" src="lib-app/cedar/vega.js"></script>
<script type="text/javascript" src="lib-app/cedar/cedar.js"></script>

Note: I guess this is the problem, I have also tried adding the libraries to src/app/storymaps/common/Core.js and src/app/main-config.js but I couldn't make it work. And I also tried to understand the Gruntfile.js... but I didn't ^_^''

Step 3) And finally I subscribed to the story-loaded-map event in the src/app/custom-scripts.js

topic.subscribe("story-loaded-map", function(result){
    if ( result.index !== null ){
      console.log("The map", result.id, "has been loaded from the section", result.index);
      
      if ( result.id === "9545a91d0f284c6fb32f816e19925b35"){
        // We are in 'Vision general'
        var serviceUrl = "http://maps2.dcgis.dc.gov/dcgis/rest/services/SampleWorldCities/MapServer/0",
        xField = "POP_CLASS",
        toolTipTitle = "{POP_CLASS}";
        // Creamos el gráfico con las propiedades:
        var chart = new Cedar({
          //Tipo de gráfico
          "type": "bar",
          //Dataset
          "dataset": {
            "url":serviceUrl,
            //En esta query lo que hacemos es un conteo de las ciudades que hay en cada POP_CLASS
            "query": {
              "groupByFieldsForStatistics": xField,
              "outStatistics": [{
                "statisticType": "count",
                "onStatisticField": "OBJECTID",
                "outStatisticFieldName": "count_SUM"
              }]
            },
            //En mappings definimos que representamos: En X cada POP_CLASS y en Y el conteo de las ciudades en cada POP_CLASS
            "mappings":{
              "x": {"field":xField,"label":"Rangos de población"},
              "y": {"field":"count_SUM","label":"Número de ciudades"},
              "sort": "count_SUM DESC"
            }
          },
          //En tooltip definimos la ventana emergente al pasar el ratón por encima
          "tooltip": {
            "id": "tooltip-url",
            "title": toolTipTitle,
            "content": "{count_SUM} Ciudades"
          }
        });
        //Mostramos el gráfico
        chart.show({
          elementId: "#chart",
          autolabels: true
        });
      }
    }else
    console.log("The map", result.id, "has been loaded from a Main Stage Action");
    
    
  });

And as I previously said, it works in development but it doesn't in production because there is no lib-app folder inside deploy, so I need some help understanding how should I include this dependencies inside the built.

By the way, I have also tried reading the Developer Guide inside the README but I didn't find anything about this.

If you could help me here you would make me very very happy 💃 (hehe)

Thanks in advance!,
Raul

@ntkog
Copy link

ntkog commented Oct 21, 2017

For the resources problem , take a look to this PR . A little explanation : Cedar was not loading then the following code will crash :

        var chart = new Cedar({
          //Tipo de gráfico
          "type": "bar",
          //Dataset
          "dataset": {
            "url":serviceUrl,
            //En esta query lo que hacemos es un conteo de las ciudades que hay en cada POP_CLASS
            "query": {
              "groupByFieldsForStatistics": xField,
              "outStatistics": [{
                "statisticType": "count",
                "onStatisticField": "OBJECTID",
                "outStatisticFieldName": "count_SUM"
              }]
            },
            //En mappings definimos que representamos: En X cada POP_CLASS y en Y el conteo de las ciudades en cada POP_CLASS
            "mappings":{
              "x": {"field":xField,"label":"Rangos de población"},
              "y": {"field":"count_SUM","label":"Número de ciudades"},
              "sort": "count_SUM DESC"
            }
          },
          //En tooltip definimos la ventana emergente al pasar el ratón por encima
          "tooltip": {
            "id": "tooltip-url",
            "title": toolTipTitle,
            "content": "{count_SUM} Ciudades"
          }
        });
        //Mostramos el gráfico
        chart.show({
          elementId: "#chart",
          autolabels: true
        });

@hhkaos
Copy link
Member Author

hhkaos commented Oct 22, 2017

Thanks @ntkog ! this solves my issue.

@glazou is this fine? would you recommend me to load them using require or something different?

Thanks one more time! 👯

@asizer
Copy link
Contributor

asizer commented Oct 25, 2017

Hi @hhkaos,

There are a number of ways to do what you're trying to do.

  1. I think the easiest, with the fewest changes, is to put Cedar in the resources/ folder and reference it from there. That entire folder gets copied over in the build process to deploy/ as is, so no need to change the gruntfile.

  2. Another option, as @ntkog suggested, is to leave Cedar in lib-app where you put it, and then add lib-app/cedar to the grunt copy task. That way, lib-app/cedar will also be copied over to deploy/, and you'll be able to reference it in both the dev and built versions.

  3. If you wanted to take advantage of the minification and concatenation process happening at build time and use Cedar as a module, put Cedar in lib-app and then add it and its dependencies to both the dojoConfig object found in main-config.js and the build paths in the requirejs task in the gruntfile. Also, since you're referencing Cedar from the custom-scripts file, which is outside the files that requirejs looks for modules in at build time, you'll need to explicitly include cedar in the build config in the grunt file, as well as copying over its chart types json to deploy/app/charts. Then, you'll need to require(['cedar'], ... in custom-scripts in the function where you're using Cedar.

(note: I tried including Cedar in any number of require or define statements that already exist at the tops of files, and kept getting a multipleDefine error. Not sure if that's unique to Cedar, or a problem with how I'm setting up dojoConfig, or some other issue, but I could only get this to work when using require(['cedar']... inside of existing requires/defines)

I've tried to implement this last strategy on a fork of your repo. Take a look at the last two commits here:
https://github.com/asizer/custom-storymap-journal/commits/master
It seems like this could be cleaned up a bit, particularly with needing to copy over the additional charts folder. I'll update here if I come up with something better.

Here are the changes and some explanations from the above commits:

index.html:
get rid of the <script> tags for d3, vega, and cedar

main-config.js:
add cedar and its dependents, d3 and vega, to dojoConfig, as specified in the Cedar docs

{
  name: 'd3',
  location: path1 + 'lib-app/cedar',
  main: 'd3.min'
},
{
  name: 'vega',
  location: path1 + 'lib-app/cedar',
  main: 'vega'
},
{
  name: 'cedar',
  location: path1 + 'lib-app/cedar',
  main: 'cedar'
},

custom-scripts.js:
wrap the code that creates a cedar chart in require(['cedar'], function(Cedar) {...

Gruntfile.js:
In the requirejs section (around line 44), options, paths object, add cedar, d3, and vega:

  'cedar': '../lib-app/cedar/cedar',
  'd3': '../lib-app/cedar/d3.min',
  'vega': '../lib-app/cedar/vega'

in the options object, explicitly include cedar in the build (which will automatically include its dependents d3 and vega)

include: [
  'cedar'
],

then in the copy section (around line 159), you'll need to copy over lib-app/cedar/charts to deploy/app/charts. I've just tacked it on to the files array in the resources copy task:

{
  expand: true,
  cwd: 'src/lib-app/cedar/charts/',
  src: ['**'],
  dest: 'deploy/app/charts/'
}

And revert the added copy-over of lib-app/cedar.

Theoretically, if you were to require Cedar from within some already-being-built module, the explicit include: ['cedar'] in the gruntfile shouldn't be necessary, but again, I wasn't able to do that without a multipleDefine error being thrown.

@hhkaos
Copy link
Member Author

hhkaos commented Oct 25, 2017

Thank you very very much @asizer !!

(note: I tried including Cedar in any number of require or define statements that already exist at the tops of files, and kept getting a multipleDefine error. Not sure if that's unique to Cedar, or a problem with how I'm setting up dojoConfig, or some other issue, but I could only get this to work when using require(['cedar']... inside of existing requires/defines)

I still have problems understanding how the dojoConfig actually works... hehe.

I really appreciate you help a lot. By the way I made another customization, I added Google Analytics to track some events as you can see here.

I'm working on a session to encourage our partners to customize the storymaps. This session is called "Demystifying how to customize storymaps" and it will take place inside the developer track during our User Conference tomorrow.

Thank you very much for your help!

@hhkaos hhkaos closed this as completed Oct 25, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants