Code Monkey home page Code Monkey logo

mapguide-maestro's Introduction

MapGuide Maestro

Build status Coverage Status

MapGuide Maestro is an Open Source (LGPL 2.1) map authoring application for MapGuide Open Source and Autodesk Infrastructure Map Server.

MapGuide Maestro is written in 100% managed C#, targeting the .net Framework. It consists of:

  • The Maestro windows application.
    • Provides specialized user interfaces for editing most resource types supported by MapGuide/AIMS
    • Designed for maximum productivity and authoring efficiency
    • Provides validation services with a rich set of validation rules for ensuring integrity of your resources, data sources and configurations.
    • Maestro is built on a flexible extension architecture allowing for custom addins. Some addins bundled with Maestro include:
      • An addin for managing resources in a locally bundled mg-desktop
      • An addin for creating and editing mapguide-rest configuration files.
      • An addin for scripting/automating Maestro via IronPython
  • An API (MaestroAPI) that provides unified access to services provided by MapGuide/aims that consists of:
    • A strongly-typed model library that models all the resources provided by MapGuide/AIMS, allowing you to work with classes, interfaces and objects instead of manipulating XML documents.
    • A unified provider-based API for accessing services provided by MapGuide/AIMS through a common set of interfaces:
      • A HTTP provider for accessing the mapagent
      • A provider that wraps the official MapGuide API
      • A provider that wraps the mg-desktop API

MapGuide Maestro is designed with flexiblity in mind. The application tries very hard not to take any options away, and always allows you to edit the internal XML representation of any resources you are working with. This ensures that features that are missing from the specialized editor user interfaces can still be accessed, and allows Maestro to be future-proofed against any new resource types that MapGuide/AIMS may introduce in the future.

This project is not affiliated with Autodesk or OSGeo.

Unsupported Features

MapGuide Maestro aims to support most of the features avalible in MapGuide Open Source and AIMS, but a few things are not (and will not) be supported:

  • Creating and editing Symbol Library resources
  • Full support for Load Procedures. Current support only covers loading of SDF/SHP/SQLite files without no support for file conversion or transforming coordinates.

Issues/Questions/etc

When using the tool, please bear in mind that the project is a continual work in progress, and may not always perform as expected. Try to keep backups of all important data. If you encounter an error, or have a feature request, please check our issue list, and if it has not already been reported ​please report it (You must have a GitHub account). If you have a question about the usage, you can ask at the mapguide-users mailing list.

mapguide-maestro's People

Contributors

danielknoop avatar jumpinjackie avatar marcuslindh avatar pcardinal avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

mapguide-maestro's Issues

Maestro: Auto generate bounds for WMS/WFS based on the items reported spatial context

Original Link: https://trac.osgeo.org/mapguide/ticket/768

Before layers can be served as WMS they must have the bounds info applied. Since the bounds info should be in EPSG:4326, it is non-trivial for the user to calculate these.

Since MapGuide exposes coordinate transformation functions, Maestro should be able to convert the boundsing coordinates from the layer/featuresource and create the corresponding EPSG:4326 coordinates.

TravisCI config

Now that we've netstandard-ized the MaestroAPI, we should have a TravisCI config to test this under Linux

Restore integration test capabilities

The 6.0m6 SDK package is lighter because in the process of porting our test suites to NUnit 3, we lost the ability to run the integration test parts as we no longer have the ability to make a dedicated NUnit console runner executable.

We either need to find out how to make a dedicated console runner in the NUnit3 world or:

  1. Get the integration tests running again using just the standard NUnit 3 console runner
  2. Find a way to package the required binary assets so that SDK users can once again run integration tests against providers generated with the ProviderTemplate tool.

Cannot connect to WMS service after editing configuration document

Originally reported by: gBecker
Original Link: https://trac.osgeo.org/mapguide/ticket/2541

When editing the configuration document of a WMS FeatureSource? in MGOS 3.0 via the editor, the connection to the WMS server fails. Hitting the "Test Connection"-Button results in an unclassified error.

<2015-02-26T11:44:53> 	15904	MapGuide Maestro v6.0.0.8244	::1	Administrator
 Error: Resource data was not found: MG_USER_CREDENTIALS
 StackTrace:
  - MgResourceServiceHandler.ProcessOperation() line 80 file c:\working\build_area\mapguide\3.0.0\x64\mgdev\server\src\services\resource\ResourceServiceHandler.cpp
  - MgOpDeleteResourceData.Execute() line 101 file c:\working\build_area\mapguide\3.0.0\x64\mgdev\server\src\services\resource\OpDeleteResourceData.cpp
  - MgServerResourceService.DeleteResourceData() line 1917 file c:\working\build_area\mapguide\3.0.0\x64\mgdev\server\src\services\resource\ServerResourceService.cpp
  - MgApplicationRepositoryManager.DeleteResourceData() line 1065 file c:\working\build_area\mapguide\3.0.0\x64\mgdev\server\src\services\resource\ApplicationRepositoryManager.cpp
  - MgTagManager.GetTag() line 372 file c:\working\build_area\mapguide\3.0.0\x64\mgdev\server\src\services\resource\TagManager.cpp	
<2015-02-26T11:44:53> 	18132	MapGuide Maestro v6.0.0.8244	::1	Administrator
 Error: Problem:\nThe application encountered a problem and could not finish the operation you just requested properly.\n\nSolution:\nIf it\'s the first time you met this problem, try again or restart the application / session; otherwise, describe the steps to reproduce this problem to the server administrator for suggestions.
 StackTrace:
  - MgFeatureServiceHandler.ProcessOperation() line 83 file c:\working\build_area\mapguide\3.0.0\x64\mgdev\server\src\services\feature\FeatureServiceHandler.cpp
  - MgOpTestFeatureSourceConnection.Execute() line 100 file c:\working\build_area\mapguide\3.0.0\x64\mgdev\server\src\services\feature\OpTestFeatureSourceConnection.cpp
  - MgServerFeatureService.TestConnection() line 244 file c:\working\build_area\mapguide\3.0.0\x64\mgdev\server\src\services\feature\ServerFeatureService.cpp
  - MgFdoConnectionManager.Open() line 333 file c:\working\build_area\mapguide\3.0.0\x64\mgdev\server\src\common\manager\FdoConnectionManager.cpp

I've also recognized that all entries in the "Select FDO Provider" box exists twice when you have another connection to an older MGOS version aside a MGOS 3.0 server connection in Maestro. For example:

"OSGeo FDO Provider for WMS" and "WMS Provider"

Increase code coverage

Now that we have code coverage set up, let's get this percentage up from its current value of 11%

SDK: Add MVC sample

It's $CURRENT_YEAR, we should have a MaestroAPI in ASP.net MVC in our SDK, not WebForms!

ConnectionProviderRegistry still tries to load ConnectionProviders.xml

Even though the HTTP connection provider is now built-in, the ConnectionProviderRegistry still blows up if ConnectionProviders.xml present.

This is due to code in the static constructor that will still implicitly look for a ConnectionProviders.xml in the same directory as the MaestroAPI assembly and load all registered providers from it.

This code fragment show be offloaded to an explicit init action where applications that need to use these other providers can call as part of application startup.

netstandard-ization

We should look at making at least the MaestroAPI portions netstandard-compatible so it can be used in .net Core, Xamarin, etc.

  • Must be netstandard compatible
    • OSGeo.MapGuide.MaestroAPI
      • Target netstandard2.0
      • Move incompatible classes out of MaestroAPI to either a full-framework bridge assembly or to the project where the type is primarily consumed
    • OSGeo.MapGuide.ObjectModels
      • Target netstandard2.0
      • Address issues reported by ApiPort
      • ApiPort: Do not use System.Drawing primitives (Point/Font/etc)arious UIs, use new BindingList<T>(originalList)
    • OSGeo.MapGuide.MaestroAPI.Http
      • Target netstandard2.0
      • Merge into MaestroAPI itself. This is to simplify the consumption story in .net core.
  • Nice to be netstandard compatbile
    • OSGeo.FDO.Expressions
      • Target netstandard1.6
      • Need a netstandard-compatible version of Irony (found one!)
  • Verify existing SDK story still works

problem moving map group folders

Original Link: https://trac.osgeo.org/mapguide/ticket/2404

This is a problem that's been in Maestro since the beginning. If you make a map and then make some groups, you'll find that you can't properly drag the groups. In fact, you can't even drag the layers to reorder them - despite the graphics which make it look like it will work. For layers you have to use the up/down buttons - which do nothing for groups.

So, if you drag a group folder and want to put it above another group, it will drop it inside the top-most group, and there's no way to get it outside of that group without dragging it to another one. Even if you get the dividers in the right spot, it won't drop a group between other groups - it always puts it inside.

PNG8 validation rules

Original Link: https://trac.osgeo.org/mapguide/ticket/2129

When validating a Map Definition, Maestro should collect the number of unique colors found in all referenced Layer Definitions. If the total is > 256 or a color FDO expression was detected (implying a variable number of different colors), report a warning that the Map Definition may not be suitable for rendering as PNG8 images.

Localization review/cleanup

Original Link: https://trac.osgeo.org/mapguide/ticket/2110

Review the Maestro codebase for localization related issues:

  • Mark lines containing unlocalizable string literals with NOXLATE, making future localizable string hunting easier.
  • Move localizable string literals into their respective resx file
  • Where possible, externalize frequently used string literals into a string constant of a StringConstants? utility class.
  • Refactor out any format strings with locale-specific information. (eg. Coordinate position)
  • Move strings in Resources.resx into a separate Strings.resx resource, to make such items easier to distinguish during the localization process
  • Refactor the file picker filter strings to the form {0}(*.{1})|*.{1} , where {0} is the locale-specific file type and {1} is the extension.

Maestro - Base Map Scale Ranges

Original Link: https://trac.osgeo.org/mapguide/ticket/1924

Hi,

A couple of minor edits to scale ranges to catch unexpected behaviour:

  • 1. When using the "Generate" button and the 'Exponential' method the scale ranges start at the 'Min Scale' but do not end at the 'Max Scale' - if I set a max I expect that to be preserved. I think the "Number of Scales" is generating but missing the top end max scale which is not added in again as it would make numscales +1

  • 2. When manually editing a 'Display Scale' list and saving the list the Map is not invalidated (*) so it is easy to close and loose changes

  • 3. It maybe just me but unless I run full-screen I cannot see the 'Generate' button, the scaling/position of the controls seems not to update if you shrink a window

Non-modal map previews break on transparent background colors

Reported by Reno on the 6.0m6 announcement

Non-modal map previews is not working if the map has transparent background colors.

Control does not support transparent background colors.
System.ArgumentException: Control does not support transparent background colors. 
   at System.Windows.Forms.Control.set_BackColor(Color value) 
   at Maestro.MapViewer.MapViewer.InitViewerFromMap(Nullable`1 initialScale) in C:\projects\mapguide-maestro\Maestro.MapViewer\MapViewer.cs:line 1155 
   at Maestro.MapViewer.MapViewer.LoadMap(RuntimeMap map) in C:\projects\mapguide-maestro\Maestro.MapViewer\MapViewer.cs:line 1138 
   at Maestro.Editors.Preview.MapPreviewViewContent.OnLoad(EventArgs e) in C:\projects\mapguide-maestro\Maestro.Editors\Preview\MapPreviewViewContent.cs:line 73 
   at System.Windows.Forms.UserControl.OnCreateControl() 
   at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible) 
   at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible) 
   at System.Windows.Forms.Control.CreateControl() 
   at System.Windows.Forms.Control.SetVisibleCore(Boolean value) 
   at System.Windows.Forms.Form.SetVisibleCore(Boolean value) 
   at System.Windows.Forms.Control.set_Visible(Boolean value) 
   at WeifenLuo.WinFormsUI.Docking.DockContentHandler.SetVisible() 
   at WeifenLuo.WinFormsUI.Docking.DockPane.set_ActiveContent(IDockContent value) 
   at WeifenLuo.WinFormsUI.Docking.DockContentHandler.Activate() 
   at WeifenLuo.WinFormsUI.Docking.DockContentHandler.Show(DockPanel dockPanel, DockState dockState) 
   at WeifenLuo.WinFormsUI.Docking.DockContentHandler.Show(DockPanel dockPanel) 
   at WeifenLuo.WinFormsUI.Docking.DockContent.Show(DockPanel dockPanel) 
   at Maestro.Shared.UI.WorkbenchBase.ShowContent(IViewContent vc) in C:\projects\mapguide-maestro\Maestro.Shared.UI\WorkbenchBase.cs:line 410 
   at Maestro.Shared.UI.ViewContentManagerBase.OpenContent[T](String title, String description, ViewRegion region, CreateFunc`1 method) in C:\projects\mapguide-maestro\Maestro.Shared.UI\ViewContentManagerBase.cs:line 229 
   at Maestro.Shared.UI.ViewContentManagerBase.OpenContent[T](ViewRegion region, CreateFunc`1 method) in C:\projects\mapguide-maestro\Maestro.Shared.UI\ViewContentManagerBase.cs:line 164 
   at Maestro.Editors.Preview.LocalMapPreviewer.<>c__DisplayClass10_0.<Preview>b__1(Object obj, Exception ex) in C:\projects\mapguide-maestro\Maestro.Editors\Preview\LocalMapPreviewer.cs:line 172 
   at Maestro.Shared.UI.BusyWaitDialog.Run(String message, BusyWaitDelegate action, Action`2 onComplete, Boolean bPreserveThreadCulture) in C:\projects\mapguide-maestro\Maestro.Shared.UI\BusyWaitDialog.cs:line 103 
   at Maestro.Editors.Preview.LocalMapPreviewer.Preview(IResource res, IEditorService edSvc, String locale) in C:\projects\mapguide-maestro\Maestro.Editors\Preview\LocalMapPreviewer.cs:line 162 
   at Maestro.Base.Editor.EditorContentBase.Preview() in C:\projects\mapguide-maestro\Maestro.Base\Editor\EditorContentBase.cs:line 376 
   at Maestro.Base.Commands.PreviewResourceCommand.Run() in C:\projects\mapguide-maestro\Maestro.Base\Commands\PreviewResourceCommand.cs:line 42 
   at ICSharpCode.Core.WinForms.ToolBarCommand.OnClick(EventArgs e) 
   at System.Windows.Forms.ToolStripItem.HandleClick(EventArgs e) 
   at System.Windows.Forms.ToolStripItem.HandleMouseUp(MouseEventArgs e) 
   at System.Windows.Forms.ToolStripItem.FireEventInteractive(EventArgs e, ToolStripItemEventType met) 
   at System.Windows.Forms.ToolStripItem.FireEvent(EventArgs e, ToolStripItemEventType met) 
   at System.Windows.Forms.ToolStrip.OnMouseUp(MouseEventArgs mea) 
   at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) 
   at System.Windows.Forms.Control.WndProc(Message& m) 
   at System.Windows.Forms.ScrollableControl.WndProc(Message& m) 
   at System.Windows.Forms.ToolStrip.WndProc(Message& m) 
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) 
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) 
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

WFS/WMS service browser

Original Link: https://trac.osgeo.org/mapguide/ticket/2335

Implement a new addin for browsing the WFS/WMS services exposed by the MapGuide Server.

Current idea is simply for a tree-style explorer interface based on the respective WFS/WMS GetCapabilities? responses to see what layers have been published for WFS/WMS.

This feature doubles as a nice way to verify if publishing a resource for WFS/WMS consumption has succeeded.

Insulate GeoAPI

Currently, we are leaking out GeoAPI from MaestroAPI to downstream consumers because we are leaking out IGeometry and ICoordinateSystem in our various public APIs.

To simplify usage of Maestro API (and to make the netstandard porting effort simpler), we should provide wrapper classes around these 2 interfaces

Make zip artifact

We used to make a zip release of Maestro (along with installer and SDK) that was just Maestro without the local connection mode and IronPython scripting engine. This was for running on Linux via Mono (at your own risk).

Our current AppVeyor setup doesn't produce this particular artifact.

Specified method is not supported

I am running mapguide maestro on a Windows 2008 Server and whenever I try to preview a map or a layer, is does not show and returns a error message 'Specified method is not supported'.... Please help me solve this issue.

Update Fusion Editor to replace Bing (VirtualEarth) with Bing Maps

Bing v7 controls (VirtualEarth) will shutdown on Jun 30th 2017

https://blogs.bing.com/maps/June-2016/Bing-Maps-V8-Web-Control-Released

Work is already being done to make sure Fusion switches over to the apikey-based service.

http://trac.osgeo.org/fusion/changeset/2971/sandbox/adsk/3.2o

To make sure Maestro can create/edit Fusion layouts with this change in place, we need to:

  • Remove existing Bing (VirtualEarth) layer types.
  • Add Bing Maps equivalent layer types to the UI. NOTE: When saving, the Fusion base layer type is still VirtualEarth
    • Aerial
    • Road
  • Provide a field to enter the Bing Maps API key. When saving, put this value into a top-level BingMapKey extension element of the Application Definition. When loading, load the API key into the field from this location if it exists.
  • Optionally/Ideally:
    • If we load an appdef and it has references to the old Bing (VirtualEarth) layers, raise some kind of warning about this.
    • Detect this case in the Maestro resource validator.

Url properties lost when upgrading Layer Definition resource to 2.4.0

Reported here: http://osgeo-org.1560.x6.nabble.com/Maestro-Feature-Upgrade-problem-td5305534.html

We're using Maestro (5.1 and 6.0b4) to upgrade some feature schema from 2.3.0 to 2.4.0.

After schema upgrade the HYPERLINK info are completely lost.

The block <Url> <Url>if('"ID" = ''707'' OR "ID" = ''648''', Concat('gdt_redirectNpages.php?&amp;npages=2'))</Url>

is not migrated to

 <UrlData> 
   <Content>................... </Content> 
 </UrlData> 

so hyperlinks have to be restored manually.

Here is an example of the schema before and after upgrade :

<?xml version="1.0"?> 
<LayerDefinition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" version="2.3.0" xsi:noNamespaceSchemaLocation="LayerDefinition-2.3.0.xsd"> 
   <VectorLayerDefinition> 
<ResourceId>Library://MYDATA/MyFolder/Data/shp.FeatureSource</ResourceId> 
     <Watermarks /> 
     <FeatureName>Default:piezometri</FeatureName> 
     <FeatureNameType>FeatureClass</FeatureNameType> 
     <Filter /> 
     <PropertyMapping> 
       <Name>TXT_CODE</Name> 
       <Value>Codice</Value> 
     </PropertyMapping> 
     <PropertyMapping> 
       <Name>ID</Name> 
       <Value>ID</Value> 
     </PropertyMapping> 
     <Geometry>Geometry</Geometry> 
     <Url>if('"ID" = ''707'' OR "ID" = ''648''', Concat('gdt_redirectNpages.php?&amp;npages=2'))</Url> 
     <ToolTip>Concat('&lt;img src="/logo.jpg" /&gt;','&lt;br /&gt;',TXT_DESCR )</ToolTip> 
     <VectorScaleRange> 
``


After : 
Library://GDMS/1805_ISP_Piezometri/Data/shp.FeatureSource Default:piezometri FeatureClass TXT_CODE Codice ID ID Geometry ........... missing Concat('<img src="http://monitoring.gdtest.it/sititest/logo_gdtest_small.jpg" />','<br />',TXT_DESCR ) ```

Add CONTRIBUTING.md

Although I'd love nothing more than receiving pull requests, there should still be a minimum bar of acceptability that such pull requests should meet.

And such standards should be documented in a CONTRIBUTING.md document.

Oracle Provider for Mapguide on Linux

Hi Jackie,

My Server Configuration is as below:

  1. MapGuide Server 3.1.0, Oracle Instant Client 11g installed on Centos 6.8 Server
  2. Oracle 11g & Maestro 5.1 are on Windows Server 2012

I have successfully performed the following steps:

  1. Connection established to Oracle database from Linux Server and retrieving the data using SQL
  2. Connection established to Map Guide Server 3.1.0 on Linux with Map Guide Maestro v 5.1

Issue: I am getting the following error when connecting to data source with OSGeo.KingOracle 4.1.0 provider in Maestro

The remote server returned an error: (559) MgFdoException.:
An exception occurred in FDO component.
Error occurred in Feature Source (Session:45a446e8-6665-11e7-8000-00016c5a03b2_en_MTI3LjAuMC4x0AFC0AFB0AFA//b4ccab67-4b8f-4e64-bc2b-55bc4a3d8485.FeatureSource): An exception occurred in FDO component.
Failed to retrieve the third party exception mesage. This message may not be unicode compliant.

  • MgFdoConnectionManager.Open() line 333 file FdoConnectionManager.cpp

  • MgFdoConnectionManager.CacheFdoConnection() line 1097 file FdoConnectionManager.cpp

  • MgFdoConnectionManager.Open() line 1089 file FdoConnectionManager.cpp
    (Cause: , Root Cause: )

  • MgFeatureServiceHandler.ProcessOperation() line 83 file FeatureServiceHandler.cpp

  • MgOpTestFeatureSourceConnection.Execute() line 100 file OpTestFeatureSourceConnection.cpp

  • MgServerFeatureService.TestConnection() line 244 file ServerFeatureService.cpp

  • MgFdoConnectionManager.Open() line 366 file FdoConnectionManager.cpp
    The remote server returned an error: (559) MgFdoException.

Q1. Is sl-king fdo provider for oracle supported on Linux?

If yes, Please share documents, urls, help manual to create layers in Maestro using SL-King FDO Provider for Oracle and display the layers using Mapguide Server.

If No, please suggest alternative to create layers in Maestro any other FDO Provider for Oracle and display the layers using Mapguide Server.

Thanks
Satish Bonala

Problem with integration of Google Maps API with Maestro 6.0 Mapguide 3.0

Original Link: https://trac.osgeo.org/mapguide/ticket/2581

Hi folks,

when integrating all 4 different google maps types, only G_SATELLITE_MAP will be displayed in the browser, after site is loaded... all other 3 map types are not shown, when they are the first childmap behind MapGuide. But we want G_NORMAL_MAP shown at start!

In the <ApplicationDefinition?><GoogleScript?> the parameters "key" and "client" for ​http://maps.google.com/maps/api/js are correct, no "callback" defined... All parameters are tested in a small html5/OpenLayers-website...

AppVeyor setup

Now that Maestro is on GitHub, let's set up AppVeyor for CI

  • Get it working!
  • Slap an AppVeyor badge on README.md
  • Get it to build user documentation (via sphinx) and API documentation (via SHFB)
  • If possible, get it to auto-publish artifacts for GitHub releases
    • Need to use release tag name as the version label for installer
  • Setup code coverage with OpenCover
    • Publish results to coveralls

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.