├── .gitignore ├── .travis.yml ├── LICENSE ├── MANIFEST.in ├── README.md ├── demo_project ├── demo │ ├── __init__.py │ ├── admin.py │ ├── custom_charts.py │ ├── models.py │ ├── templates │ │ ├── base.html │ │ └── demo │ │ │ ├── c3js.html │ │ │ ├── flot.html │ │ │ ├── flot_line.html │ │ │ ├── flot_line2.html │ │ │ ├── gchart.html │ │ │ ├── gchart_line.html │ │ │ ├── highcharts.html │ │ │ ├── home.html │ │ │ ├── matplotlib.html │ │ │ ├── mongodb_source.html │ │ │ ├── morris.html │ │ │ ├── tutorial.html │ │ │ └── yui.html │ ├── tests.py │ ├── urls.py │ ├── utils.py │ └── views.py ├── demo_project │ ├── __init__.py │ ├── settings │ │ ├── __init__.py │ │ ├── common.py │ │ ├── local.py-dist │ │ └── test.py │ ├── urls.py │ └── wsgi.py ├── graphos ├── manage.py ├── requirements.txt └── static │ ├── admin │ ├── css │ │ ├── base.css │ │ ├── changelists.css │ │ ├── dashboard.css │ │ ├── forms.css │ │ ├── ie.css │ │ ├── login.css │ │ ├── rtl.css │ │ └── widgets.css │ ├── img │ │ ├── admin │ │ │ ├── arrow-down.gif │ │ │ ├── arrow-up.gif │ │ │ ├── changelist-bg.gif │ │ │ ├── changelist-bg_rtl.gif │ │ │ ├── chooser-bg.gif │ │ │ ├── chooser_stacked-bg.gif │ │ │ ├── default-bg-reverse.gif │ │ │ ├── default-bg.gif │ │ │ ├── deleted-overlay.gif │ │ │ ├── icon-no.gif │ │ │ ├── icon-unknown.gif │ │ │ ├── icon-yes.gif │ │ │ ├── icon_addlink.gif │ │ │ ├── icon_alert.gif │ │ │ ├── icon_calendar.gif │ │ │ ├── icon_changelink.gif │ │ │ ├── icon_clock.gif │ │ │ ├── icon_deletelink.gif │ │ │ ├── icon_error.gif │ │ │ ├── icon_searchbox.png │ │ │ ├── icon_success.gif │ │ │ ├── inline-delete-8bit.png │ │ │ ├── inline-delete.png │ │ │ ├── inline-restore-8bit.png │ │ │ ├── inline-restore.png │ │ │ ├── inline-splitter-bg.gif │ │ │ ├── nav-bg-grabber.gif │ │ │ ├── nav-bg-reverse.gif │ │ │ ├── nav-bg.gif │ │ │ ├── selector-add.gif │ │ │ ├── selector-addall.gif │ │ │ ├── selector-remove.gif │ │ │ ├── selector-removeall.gif │ │ │ ├── selector-search.gif │ │ │ ├── selector_stacked-add.gif │ │ │ ├── selector_stacked-remove.gif │ │ │ ├── tool-left.gif │ │ │ ├── tool-left_over.gif │ │ │ ├── tool-right.gif │ │ │ ├── tool-right_over.gif │ │ │ ├── tooltag-add.gif │ │ │ ├── tooltag-add_over.gif │ │ │ ├── tooltag-arrowright.gif │ │ │ └── tooltag-arrowright_over.gif │ │ └── gis │ │ │ ├── move_vertex_off.png │ │ │ └── move_vertex_on.png │ └── js │ │ ├── LICENSE-JQUERY.txt │ │ ├── SelectBox.js │ │ ├── SelectFilter2.js │ │ ├── actions.js │ │ ├── actions.min.js │ │ ├── admin │ │ ├── DateTimeShortcuts.js │ │ ├── RelatedObjectLookups.js │ │ └── ordering.js │ │ ├── calendar.js │ │ ├── collapse.js │ │ ├── collapse.min.js │ │ ├── compress.py │ │ ├── core.js │ │ ├── dateparse.js │ │ ├── getElementsBySelector.js │ │ ├── inlines.js │ │ ├── inlines.min.js │ │ ├── jquery.init.js │ │ ├── jquery.js │ │ ├── jquery.min.js │ │ ├── prepopulate.js │ │ ├── prepopulate.min.js │ │ ├── timeparse.js │ │ └── urlify.js │ ├── css │ ├── bootstrap-responsive.css │ ├── bootstrap-responsive.min.css │ ├── bootstrap.css │ ├── bootstrap.min.css │ ├── c3.min.css │ ├── highmaps.css │ ├── layout.css │ └── main.css │ ├── img │ ├── favicon.gif │ ├── favicon.ico │ ├── glyphicons-halflings-white.png │ └── glyphicons-halflings.png │ └── js │ ├── bootstrap.js │ ├── bootstrap.min.js │ ├── c3.min.js │ ├── excanvas.js │ ├── excanvas.min.js │ ├── jquery.colorhelpers.js │ ├── jquery.colorhelpers.min.js │ ├── jquery.flot.canvas.js │ ├── jquery.flot.canvas.min.js │ ├── jquery.flot.categories.js │ ├── jquery.flot.categories.min.js │ ├── jquery.flot.crosshair.js │ ├── jquery.flot.crosshair.min.js │ ├── jquery.flot.errorbars.js │ ├── jquery.flot.errorbars.min.js │ ├── jquery.flot.fillbetween.js │ ├── jquery.flot.fillbetween.min.js │ ├── jquery.flot.image.js │ ├── jquery.flot.image.min.js │ ├── jquery.flot.js │ ├── jquery.flot.min.js │ ├── jquery.flot.navigate.js │ ├── jquery.flot.navigate.min.js │ ├── jquery.flot.pie.js │ ├── jquery.flot.pie.min.js │ ├── jquery.flot.resize.js │ ├── jquery.flot.resize.min.js │ ├── jquery.flot.selection.js │ ├── jquery.flot.selection.min.js │ ├── jquery.flot.stack.js │ ├── jquery.flot.stack.min.js │ ├── jquery.flot.symbol.js │ ├── jquery.flot.symbol.min.js │ ├── jquery.flot.threshold.js │ ├── jquery.flot.threshold.min.js │ ├── jquery.flot.time.js │ ├── jquery.flot.time.min.js │ ├── jquery.js │ ├── jquery.min.js │ └── statictest.js ├── docs ├── Makefile └── source │ ├── ajax.rst │ ├── conf.py │ ├── custom-charts.rst │ ├── custom-data-source.rst │ ├── flot.rst │ ├── google-charts.rst │ ├── index.rst │ └── intro.rst ├── graphos ├── __init__.py ├── encoders.py ├── exceptions.py ├── models.py ├── renderers │ ├── __init__.py │ ├── base.py │ ├── c3js.py │ ├── flot.py │ ├── gchart.py │ ├── highcharts.py │ ├── matplotlib_renderer.py │ ├── morris.py │ └── yui.py ├── sources │ ├── __init__.py │ ├── base.py │ ├── csv_file.py │ ├── model.py │ ├── mongo.py │ └── simple.py ├── templates │ └── graphos │ │ ├── as_html.html │ │ ├── c3js │ │ ├── html.html │ │ ├── js_base.html │ │ ├── js_column.html │ │ ├── js_donut.html │ │ └── js_pie.html │ │ ├── flot │ │ ├── html.html │ │ ├── js.html │ │ └── pie_chart.html │ │ ├── gchart │ │ ├── area_chart.html │ │ ├── bar_chart.html │ │ ├── base.html │ │ ├── candlestick_chart.html │ │ ├── column_chart.html │ │ ├── gauge_chart.html │ │ ├── html.html │ │ ├── line_chart.html │ │ ├── pie_chart.html │ │ └── treemap_chart.html │ │ ├── highcharts │ │ ├── html.html │ │ ├── js.html │ │ ├── js_dual_axis.html │ │ ├── js_heatmaps.html │ │ ├── js_highmaps.html │ │ ├── js_highmaps_multi_series.html │ │ └── js_treemap.html │ │ ├── matplotlib_renderer │ │ └── line_chart.html │ │ ├── model_template.html │ │ ├── morris │ │ ├── chart.html │ │ ├── donut_chart.html │ │ └── html.html │ │ ├── redis_template.html │ │ └── yui │ │ ├── area_chart.html │ │ ├── area_spline_chart.html │ │ ├── bar_chart.html │ │ ├── base.html │ │ ├── column_chart.html │ │ ├── combo.html │ │ ├── combo_spline.html │ │ ├── html.html │ │ ├── line_chart.html │ │ ├── marker_series.html │ │ ├── pie_chart.html │ │ └── spline_chart.html ├── templatetags │ ├── __init__.py │ └── graph_tags.py ├── test_data │ ├── accounts.csv │ ├── mongodb │ │ ├── mapreduce_daily__sumof__other_time_record__hours.json │ │ ├── mapreduce_daily__sumof__time_record__hours.json │ │ ├── mapreduce_monthly__sumof__other_time_record__hours.json │ │ ├── mapreduce_monthly__sumof__time_record__hours.json │ │ ├── mapreduce_weekly__sumof__other_time_record__hours.json │ │ ├── mapreduce_weekly__sumof__time_record__hours.json │ │ └── test_zips.json │ └── zips.json ├── tests.py ├── utils.py └── views.py ├── requirements.txt └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.db 3 | *.idea/ 4 | *~ 5 | demo_project/demo_project/settings/local.py 6 | build/ 7 | dist/ 8 | .* 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "2.7" 4 | - "3.3" 5 | - "3.4" 6 | before_install: 7 | - "export DISPLAY=:99.0" 8 | - "sh -e /etc/init.d/xvfb start" 9 | - sleep 3 10 | # command to install dependencies 11 | install: 12 | - "pip install -r demo_project/requirements.txt" 13 | - "pip install --upgrade pip" 14 | # command to run tests 15 | script: cd demo_project && python manage.py test graphos demo --settings=demo_project.settings.test 16 | services: 17 | - mongodb 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2013, Agiliq 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.md 2 | recursive-include graphos/templates * -------------------------------------------------------------------------------- /demo_project/demo/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/demo/__init__.py -------------------------------------------------------------------------------- /demo_project/demo/admin.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 *-* 2 | from django.contrib import admin 3 | from .models import TimeSeries 4 | 5 | admin.site.register(TimeSeries) 6 | -------------------------------------------------------------------------------- /demo_project/demo/custom_charts.py: -------------------------------------------------------------------------------- 1 | from graphos.renderers import gchart, flot 2 | 3 | 4 | class CustomGchart(gchart.LineChart): 5 | def get_template(self): 6 | return "demo/gchart_line.html" 7 | 8 | class CustomFlot(flot.LineChart): 9 | def get_template(self): 10 | return "demo/flot_line.html" 11 | 12 | class CustomFlot2(flot.LineChart): 13 | def get_template(self): 14 | return "demo/flot_line2.html" 15 | -------------------------------------------------------------------------------- /demo_project/demo/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | 4 | class TimeSeries(models.Model): 5 | """ 6 | value is used as y axis for the graph 7 | """ 8 | value = models.IntegerField() 9 | 10 | 11 | class Account(models.Model): 12 | year = models.CharField(max_length=4) 13 | sales = models.PositiveIntegerField() 14 | expenses = models.PositiveIntegerField() 15 | ceo = models.CharField(max_length=10) 16 | created_on = models.DateTimeField(auto_now_add=True) 17 | -------------------------------------------------------------------------------- /demo_project/demo/templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Graphos 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 27 | 28 | {% block extra_head %} 29 | {% endblock %} 30 | 31 | 32 | 33 | Fork me on GitHub 34 | 62 | 63 |
64 |
65 |
66 |
67 |
68 | {% block content %} 69 | {% endblock %} 70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | 78 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /demo_project/demo/templates/demo/c3js.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load staticfiles %} 3 | 4 | {% block extra_head %} 5 | 6 | 7 | 8 | {% endblock %} 9 | 10 | {% block menu %} 11 | 23 | {% endblock %} 24 | 25 | {% block content %} 26 |
27 |

28 | graphos.renderer.c3js provides charting via C3JS chart API. 29 |

30 |
31 | 32 |
33 | 34 | {{ line_chart.as_html }} 35 |
36 |             data_source = ModelDataSource(queryset, fields=['year', 'sales',],)
37 |             c3js.LineChart(data_source, options={'title': "Sales Growth"})
38 |         
39 |
40 |
41 | 42 |
43 | {{ spline_chart.as_html }} 44 |
45 | 46 |
47 | 48 |
49 | {{ bar_chart.as_html }} 50 |
51 |
52 | 53 |
54 | {{ column_chart.as_html }} 55 |
56 |
57 | 58 |
59 | {{ pie_chart.as_html }} 60 |
61 |
62 | 63 |
64 | {{ donut_chart.as_html }} 65 |
66 | {% endblock %} 67 | -------------------------------------------------------------------------------- /demo_project/demo/templates/demo/flot.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block menu %} 4 | 16 | {% endblock %} 17 | 18 | {% block content %} 19 |
20 |

21 | graphos.renderer.flot provides charting via Flot Charts API. 22 |

23 |
24 | 25 |

Line Chart

26 | 27 |
28 | 29 | {{ line_chart.as_html }} 30 |
31 |             data_source = ModelDataSource(queryset, fields=['year', 'sales'])
32 |             line_chart = flot.LineChart(data_source, options={'title': "Sales Growth"})
33 |         
34 |
35 |
36 | 37 |
38 |

Bar Chart

39 |
40 | 41 | {{ bar_chart.as_html }} 42 |
43 |             data_source = ModelDataSource(queryset, fields=['year', 'sales'])
44 |             bar_chart = flot.BarChart(data_source, options={'title': "Sales Growth"})
45 |         
46 |
47 |
48 | 49 |
50 |

Point Chart

51 |
52 | 53 | {{ point_chart.as_html }} 54 |
55 |             data_source = ModelDataSource(queryset, fields=['year', 'sales'])
56 |             bar_chart = flot.PointChart(data_source, options={'title': "Sales Growth"})
57 |         
58 |
59 |
60 | 61 |

Column Chart

62 |
63 | {{ column_chart.as_html }} 64 |
65 |             data = [
66 |                    ['Year', 'Sales', 'Expenses', 'Items Sold', 'Net Profit'],
67 |                    ['2004', 1000, 400, 100, 600],
68 |                    ['2005', 1170, 460, 120, 310],
69 |                    ['2006', 660, 1120, 50, -460],
70 |                    ['2007', 1030, 540, 100, 200],
71 |                    ]
72 |             data_source = SimpleDataSource(data)
73 |             chart = gchart.ColumnChart(data_source, options={'title': "Sales/ Expense"})
74 |         
75 |
76 |
77 |

Pie Chart

78 |
79 | {{ pie_chart.as_html }} 80 |
81 |             data = [
82 |                    ['Year', 'Sales'],
83 |                    ['2004', 1000],
84 |                    ['2005', 1170],
85 |                    ['2006', 660],
86 |                    ['2007', 1030],
87 |                    ]
88 |             data_source = SimpleDataSource(data)
89 |             chart = flot.PieChart(data_source, options={'title': "Sales/ Expense"})
90 |         
91 |
92 |
93 | {% endblock %} 94 | -------------------------------------------------------------------------------- /demo_project/demo/templates/demo/flot_line.html: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /demo_project/demo/templates/demo/flot_line2.html: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /demo_project/demo/templates/demo/gchart_line.html: -------------------------------------------------------------------------------- 1 | 2 | 21 | 22 |
23 | 24 | -------------------------------------------------------------------------------- /demo_project/demo/templates/demo/highcharts.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block extra_head %} 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | {% endblock %} 19 | 20 | {% block menu %} 21 | 33 | {% endblock %} 34 | 35 | {% block content %} 36 |
37 |

38 | graphos.renderer.highcharts provides charting via Highcharts chart API. 39 |

40 |
41 | 42 |
43 | 44 | {{ line_chart.as_html }} 45 |
 46 |             data_source = ModelDataSource(queryset, fields=['year', 'sales',],)
 47 |             gchart.LineChart(data_source, options={'title': "Sales Growth"})
 48 |         
49 |
50 |
51 | 52 |
53 | {{ column_chart.as_html }} 54 |
55 | 56 |
57 | 58 |
59 | {{ bar_chart.as_html }} 60 |
61 |
62 | 63 |
64 | {{ candlestick_chart.as_html }} 65 |
66 |
67 | 68 |
69 | {{ pie_chart.as_html }} 70 |
71 | 72 |
73 | {{ area_chart.as_html }} 74 |
75 |
76 | 77 |
78 | {{ scatter_chart.as_html }} 79 |
80 |
81 | 82 |
83 | {{ scatter_multi_series_chart.as_html }} 84 |
85 |
86 | 87 |
88 | {{ donut_chart.as_html }} 89 |
90 |
91 | 92 |
93 | {{ multi_axis_chart.as_html }} 94 |
95 | 96 |
97 | {{ highmap_chart.as_html }} 98 |
99 | 100 |
101 | {{ highmap_chart_point.as_html }} 102 |
103 | 104 |
105 | {{ highmap_chart_bubble.as_html }} 106 |
107 | 108 |
109 | {{ highmap_chart_lat_lon.as_html }} 110 |
111 | 112 |
113 | {{ highmap_chart_multi.as_html }} 114 |
115 | 116 |
117 | {{ highmap_chart_multi_bubble.as_html }} 118 |
119 | 120 |
121 | {{ highmap_chart_multi_lat_lon.as_html }} 122 |
123 | 124 |
125 | {{ heat_map.as_html }} 126 |
127 | 128 |
129 | {{ funnel.as_html }} 130 |
131 | 132 |
133 | {{ treemap.as_html }} 134 |
135 | 136 |
137 | {{ pie_donut.as_html }} 138 |
139 | 140 |
141 | {{ bubble_chart_single.as_html }} 142 |
143 | 144 |
145 | {{ bubble_chart_multi.as_html }} 146 |
147 |
148 | 149 | {% endblock %} 150 | -------------------------------------------------------------------------------- /demo_project/demo/templates/demo/home.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block extra_head %} 4 | 5 | 8 | {% endblock %} 9 | 10 | {% block content %} 11 |
12 |

Graphos Examples

13 |

14 | Graphos is an app for django to plot data into a graph. We currently support 15 | Flot, Google Chart API and YUI Charts. Graphos can read data from CSV, Models, MongoDB and Redis. 16 |

17 |
18 | 19 | 20 | 21 |

Flot Chart

22 | {{ chart.as_html }} 23 | 26 |
27 |

Google charts

28 | 29 | {{ g_chart.as_html }} 30 | 31 | 32 |
33 |

34 | {% endblock %} 35 | -------------------------------------------------------------------------------- /demo_project/demo/templates/demo/matplotlib.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block menu %} 4 | 16 | {% endblock %} 17 | 18 | {% block content %} 19 |
20 |

21 | graphos.renderer.matplotlib_renderer provides charting via matplotlib. 22 |

23 |
24 |
25 | {{ line_chart.as_html }} 26 |
27 |
28 | {{ bar_chart.as_html }} 29 |
30 | {% endblock %} 31 | -------------------------------------------------------------------------------- /demo_project/demo/templates/demo/morris.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block extra_head %} 4 | 5 | 6 | 7 | 8 | 9 | 10 | {% endblock %} 11 | 12 | {% block menu %} 13 | 25 | {% endblock %} 26 | 27 | {% block content %} 28 |
29 |

30 | graphos.renderer.morris provides charting via morris and raphael.js. 31 |

32 |
33 | 34 |

Line Chart

35 |
36 | 37 | {{ line_chart.as_html }} 38 |
39 |             queryset = Account.objects.all()
40 |             data_source = ModelDataSource(queryset, fields=['year', 'sales',],)
41 |             chart = morris.LineChart(data_source)
42 |         
43 |
44 |
45 |

Bar Chart

46 |
47 | 48 | {{ bar_chart.as_html }} 49 |
50 |             data = [
51 |                    ['Year', 'Sales', 'Expenses', 'Items Sold', 'Net Profit'],
52 |                    ['2004', 1000, 400, 100, 600],
53 |                    ['2005', 1170, 460, 120, 310],
54 |                    ['2006', 660, 1120, 50, -460],
55 |                    ['2007', 1030, 540, 100, 200],
56 |                    ]
57 |             simple_data_source = SimpleDataSource(data=data)
58 |             bar_chart = morris.BarChart(simple_data_source)
59 |         
60 |
61 |
62 | 63 |

Donut Chart

64 |
65 | 66 | {{ donut_chart.as_html }} 67 |
68 |             queryset = Account.objects.all()
69 |             data_source = ModelDataSource(queryset, fields=['year', 'sales',],)
70 |             donut_chart = morris.DonutChart(data_source)
71 |         
72 |
73 |
74 | 75 |

Area Chart

76 |
77 | 78 | {{ area_chart.as_html }} 79 |
80 |             queryset = Account.objects.all()
81 |             data_source = ModelDataSource(queryset, fields=['year', 'sales',],)
82 |             area_chart = morris.AreaChart(data_source)
83 |         
84 |
85 |
86 | {% endblock %} 87 | -------------------------------------------------------------------------------- /demo_project/demo/templates/demo/tutorial.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block menu %} 4 | 16 | {% endblock %} 17 | 18 | {% block content %} 19 |
20 | {{ readme|safe }} 21 |
22 | {% endblock %} 23 | -------------------------------------------------------------------------------- /demo_project/demo/templates/demo/yui.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block extra_head %} 4 | 5 | {% endblock %} 6 | 7 | {% block menu %} 8 | 18 | {% endblock %} 19 | 20 | {% block content %} 21 |
22 |

23 | graphos.renderer.yui provides charting via YUI chart API. 24 |

25 |
26 | 27 |

Line Chart

28 |
29 | 30 | {{ line_chart.as_html }} 31 |
 32 |             queryset = Account.objects.all()
 33 |             data_source = ModelDataSource(queryset, fields=['year', 'sales',],)
 34 |             chart = yui.LineChart(data_source, options={'title': "Sales Growth"})
 35 |         
36 |
37 |
38 | 39 |

Spline Chart

40 |
41 | 42 | {{ spline_chart.as_html }} 43 |
 44 |             data = [
 45 |                    ['Year', 'Sales', 'Expenses', 'Items Sold', 'Net Profit'],
 46 |                    ['2004', 1000, 400, 100, 600],
 47 |                    ['2005', 1170, 460, 120, 310],
 48 |                    ['2006', 660, 1120, 50, -460],
 49 |                    ['2007', 1030, 540, 100, 200],
 50 |                    ]
 51 |             data_source = SimpleDataSource(data)
 52 |             chart = yui.SplineChart(data_source, options={'title': "Sales/ Expense"})
 53 |         
54 |
55 |
56 | 57 |

Column Chart

58 |
59 | {{ column_chart.as_html }} 60 |
 61 |             data = [
 62 |                    ['Year', 'Sales', 'Expenses', 'Items Sold', 'Net Profit'],
 63 |                    ['2004', 1000, 400, 100, 600],
 64 |                    ['2005', 1170, 460, 120, 310],
 65 |                    ['2006', 660, 1120, 50, -460],
 66 |                    ['2007', 1030, 540, 100, 200],
 67 |                    ]
 68 |             data_source = SimpleDataSource(data)
 69 |             chart = yui.ColumnChart(data_source, options={'title': "Sales/ Expense"})
 70 |     
71 | 72 |
73 | 74 |

Bar Chart

75 |
76 | {{ bar_chart.as_html }} 77 |
 78 | 			data_source = ModelDataSource(queryset, fields=['year', 'sales'])
 79 | 			chart = yui.BarChart(data_source, options={'title': "Expense Growth"})
 80 |         
81 |
82 |
83 | 84 |

Pie Chart

85 |
86 | {{ pie_chart.as_html }} 87 |
 88 |         data_source = ModelDataSource(queryset, fields=['year', 'sales'])
 89 |         chart = yui.PieChart(data_source)
 90 |         
91 |
92 | 93 |

Area Chart

94 |
95 | {{ area_chart.as_html }} 96 |
 97 |         data_source = ModelDataSource(queryset, fields=['year', 'sales'])
 98 |         chart = yui.AreaChart(data_source)
 99 |         
100 |
101 | 102 |

Areaspline Chart

103 |
104 | {{ area_spline_chart.as_html }} 105 |
106 |         data_source = ModelDataSource(queryset, fields=['year', 'sales'])
107 |         chart = yui.AreaSplineChart(data_source)
108 |         
109 |
110 | 111 |

Combo Chart

112 |
113 | {{ combo_chart.as_html }} 114 |
115 |         data_source = ModelDataSource(queryset, fields=['year', 'sales'])
116 |         chart = yui.ComboChart(data_source)
117 |         
118 |
119 | 120 |

Combo Spline Chart

121 |
122 | {{ combo_spline_chart.as_html }} 123 |
124 |         data_source = ModelDataSource(queryset, fields=['year', 'sales'])
125 |         chart = yui.ComboSplineChart(data_source)
126 |         
127 |
128 | 129 |

Marker Series Chart

130 |
131 | {{ marker_series_chart.as_html }} 132 |
133 |         data_source = ModelDataSource(queryset, fields=['year', 'sales'])
134 |         chart = yui.MarkerSeriesChart(data_source)
135 |         
136 |
137 | 138 | {% endblock %} 139 | -------------------------------------------------------------------------------- /demo_project/demo/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from django.test import Client 3 | 4 | from django.core.urlresolvers import reverse 5 | 6 | 7 | class SimpleTest(TestCase): 8 | def setUp(self): 9 | self.client = Client() 10 | 11 | def test_homepage(self): 12 | self.client.get(reverse("demo_home")) 13 | 14 | def test_tutorial(self): 15 | self.client.get(reverse("demo_tutorial")) 16 | 17 | def test_gchart_demo(self): 18 | self.client.get(reverse("demo_gchart_demo")) 19 | 20 | def test_demo_yui_demo(self): 21 | self.client.get(reverse("demo_gchart_demo")) 22 | 23 | def test_demo_flot_demo(self): 24 | self.client.get(reverse('demo_flot_demo')) 25 | 26 | def test_demo_morris_demo(self): 27 | self.client.get(reverse('demo_morris_demo')) 28 | 29 | def test_demo_highcharts_demo(self): 30 | self.client.get(reverse('demo_highcharts_demo')) 31 | 32 | 33 | def test_demo_time_series_example(self): 34 | self.client.get(reverse('demo_time_series_example')) 35 | -------------------------------------------------------------------------------- /demo_project/demo/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import patterns, url 2 | 3 | 4 | urlpatterns = patterns('', 5 | url(r'^$', 'demo.views.home', name='demo_home'), 6 | url(r'^tutorial/$', 'demo.views.tutorial', name='demo_tutorial'), 7 | url(r'^gchart/$', 'demo.views.gchart_demo', name='demo_gchart_demo'), 8 | url(r'^yui/$', 'demo.views.yui_demo', name='demo_yui_demo'), 9 | url(r'^flot/$', 'demo.views.flot_demo', name='demo_flot_demo'), 10 | url(r'^highcharts/$', 'demo.views.highcharts_demo', name='demo_highcharts_demo'), 11 | url(r'^c3js/$', 'demo.views.c3js_demo', name='demo_c3js_demo'), 12 | url(r'^morris/$', 'demo.views.morris_demo', name='demo_morris_demo'), 13 | url(r'^matplotlib/$', 'demo.views.matplotlib_demo', name='demo_matplotlib_demo'), 14 | url(r'^time_series/$', 'demo.views.time_series_demo', 15 | name='demo_time_series_example'), 16 | url(r"^gchart-json/$", "demo.views.custom_gchart_renderer", name="demo_custom_gchart"), 17 | url(r"^mongo-json/$", "demo.views.mongo_json", name="demo_mongo_json"), 18 | url(r"^mongo-json2/$", "demo.views.mongo_json2", name="demo_mongo_json2"), 19 | url(r"^mongo-json-multi/$", "demo.views.mongo_json_multi", name="demo_mongo_json_multi"), 20 | url(r"^mongo-json-multi2/$", "demo.views.mongo_json_multi2", name="demo_mongo_json_multi2"), 21 | ) 22 | 23 | -------------------------------------------------------------------------------- /demo_project/demo_project/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/demo_project/__init__.py -------------------------------------------------------------------------------- /demo_project/demo_project/settings/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/demo_project/settings/__init__.py -------------------------------------------------------------------------------- /demo_project/demo_project/settings/local.py-dist: -------------------------------------------------------------------------------- 1 | from .common import * 2 | 3 | DEBUG = True 4 | -------------------------------------------------------------------------------- /demo_project/demo_project/settings/test.py: -------------------------------------------------------------------------------- 1 | from .common import * 2 | -------------------------------------------------------------------------------- /demo_project/demo_project/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import patterns, include, url 2 | from django.conf import settings 3 | 4 | 5 | urlpatterns = patterns('', 6 | url(r'^', include("demo.urls")), 7 | url(r'^static/(?P.*)$', 'django.views.static.serve', 8 | {'document_root': settings.STATIC_ROOT}), 9 | ) 10 | 11 | -------------------------------------------------------------------------------- /demo_project/demo_project/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for demo_project project. 3 | 4 | This module contains the WSGI application used by Django's development server 5 | and any production WSGI deployments. It should expose a module-level variable 6 | named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover 7 | this application via the ``WSGI_APPLICATION`` setting. 8 | 9 | Usually you will have the standard Django WSGI application here, but it also 10 | might make sense to replace the whole Django WSGI application with a custom one 11 | that later delegates to the Django one. For example, you could introduce WSGI 12 | middleware here, or combine a Django application with an application of another 13 | framework. 14 | 15 | """ 16 | import os 17 | 18 | # We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks 19 | # if running multiple sites in the same mod_wsgi process. To fix this, use 20 | # mod_wsgi daemon mode with each site in its own daemon process, or use 21 | # os.environ["DJANGO_SETTINGS_MODULE"] = "demo_project.settings" 22 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "demo_project.settings.local") 23 | 24 | # This application object is used by any WSGI server configured to use this 25 | # file. This includes Django's development server, if the WSGI_APPLICATION 26 | # setting points here. 27 | from django.core.wsgi import get_wsgi_application 28 | application = get_wsgi_application() 29 | 30 | # Apply WSGI middleware here. 31 | # from helloworld.wsgi import HelloWorldApplication 32 | # application = HelloWorldApplication(application) 33 | -------------------------------------------------------------------------------- /demo_project/graphos: -------------------------------------------------------------------------------- 1 | ../graphos -------------------------------------------------------------------------------- /demo_project/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "demo_project.settings.local") 7 | 8 | from django.core.management import execute_from_command_line 9 | 10 | execute_from_command_line(sys.argv) 11 | -------------------------------------------------------------------------------- /demo_project/requirements.txt: -------------------------------------------------------------------------------- 1 | Django==1.8 2 | Markdown==2.3.1 3 | Sphinx==1.2b1 4 | docutils==0.11 5 | numpy==1.10.1 6 | matplotlib==1.4.3 7 | pymongo==2.5.1 8 | pyparsing==2.0.3 9 | python-dateutil==2.4.2 10 | redis==2.7.4 11 | requests==1.2.0 12 | tornado==3.1 13 | -------------------------------------------------------------------------------- /demo_project/static/admin/css/dashboard.css: -------------------------------------------------------------------------------- 1 | /* DASHBOARD */ 2 | 3 | .dashboard .module table th { 4 | width: 100%; 5 | } 6 | 7 | .dashboard .module table td { 8 | white-space: nowrap; 9 | } 10 | 11 | .dashboard .module table td a { 12 | display: block; 13 | padding-right: .6em; 14 | } 15 | 16 | /* RECENT ACTIONS MODULE */ 17 | 18 | .module ul.actionlist { 19 | margin-left: 0; 20 | } 21 | 22 | ul.actionlist li { 23 | list-style-type: none; 24 | } 25 | 26 | ul.actionlist li.changelink { 27 | overflow: hidden; 28 | text-overflow: ellipsis; 29 | -o-text-overflow: ellipsis; 30 | } -------------------------------------------------------------------------------- /demo_project/static/admin/css/ie.css: -------------------------------------------------------------------------------- 1 | /* IE 6 & 7 */ 2 | 3 | /* Proper fixed width for dashboard in IE6 */ 4 | 5 | .dashboard #content { 6 | *width: 768px; 7 | } 8 | 9 | .dashboard #content-main { 10 | *width: 535px; 11 | } 12 | 13 | /* IE 6 ONLY */ 14 | 15 | /* Keep header from flowing off the page */ 16 | 17 | #container { 18 | _position: static; 19 | } 20 | 21 | /* Put the right sidebars back on the page */ 22 | 23 | .colMS #content-related { 24 | _margin-right: 0; 25 | _margin-left: 10px; 26 | _position: static; 27 | } 28 | 29 | /* Put the left sidebars back on the page */ 30 | 31 | .colSM #content-related { 32 | _margin-right: 10px; 33 | _margin-left: -115px; 34 | _position: static; 35 | } 36 | 37 | .form-row { 38 | _height: 1%; 39 | } 40 | 41 | /* Fix right margin for changelist filters in IE6 */ 42 | 43 | #changelist-filter ul { 44 | _margin-right: -10px; 45 | } 46 | 47 | /* IE ignores min-height, but treats height as if it were min-height */ 48 | 49 | .change-list .filtered { 50 | _height: 400px; 51 | } 52 | 53 | /* IE doesn't know alpha transparency in PNGs */ 54 | 55 | .inline-deletelink { 56 | background: transparent url(../img/admin/inline-delete-8bit.png) no-repeat; 57 | } -------------------------------------------------------------------------------- /demo_project/static/admin/css/login.css: -------------------------------------------------------------------------------- 1 | /* LOGIN FORM */ 2 | 3 | body.login { 4 | background: #eee; 5 | } 6 | 7 | .login #container { 8 | background: white; 9 | border: 1px solid #ccc; 10 | width: 28em; 11 | min-width: 300px; 12 | margin-left: auto; 13 | margin-right: auto; 14 | margin-top: 100px; 15 | } 16 | 17 | .login #content-main { 18 | width: 100%; 19 | } 20 | 21 | .login form { 22 | margin-top: 1em; 23 | } 24 | 25 | .login .form-row { 26 | padding: 4px 0; 27 | float: left; 28 | width: 100%; 29 | } 30 | 31 | .login .form-row label { 32 | float: left; 33 | width: 9em; 34 | padding-right: 0.5em; 35 | line-height: 2em; 36 | text-align: right; 37 | font-size: 1em; 38 | color: #333; 39 | } 40 | 41 | .login .form-row #id_username, .login .form-row #id_password { 42 | width: 14em; 43 | } 44 | 45 | .login span.help { 46 | font-size: 10px; 47 | display: block; 48 | } 49 | 50 | .login .submit-row { 51 | clear: both; 52 | padding: 1em 0 0 9.4em; 53 | } 54 | 55 | -------------------------------------------------------------------------------- /demo_project/static/admin/css/rtl.css: -------------------------------------------------------------------------------- 1 | body { 2 | direction: rtl; 3 | } 4 | 5 | /* LOGIN */ 6 | 7 | .login .form-row { 8 | float: right; 9 | } 10 | 11 | .login .form-row label { 12 | float: right; 13 | padding-left: 0.5em; 14 | padding-right: 0; 15 | text-align: left; 16 | } 17 | 18 | .login .submit-row { 19 | clear: both; 20 | padding: 1em 9.4em 0 0; 21 | } 22 | 23 | /* GLOBAL */ 24 | 25 | th { 26 | text-align: right; 27 | } 28 | 29 | .module h2, .module caption { 30 | text-align: right; 31 | } 32 | 33 | .addlink, .changelink { 34 | padding-left: 0px; 35 | padding-right: 12px; 36 | background-position: 100% 0.2em; 37 | } 38 | 39 | .deletelink { 40 | padding-left: 0px; 41 | padding-right: 12px; 42 | background-position: 100% 0.25em; 43 | } 44 | 45 | .object-tools { 46 | float: left; 47 | } 48 | 49 | /* LAYOUT */ 50 | 51 | #user-tools { 52 | right: auto; 53 | left: 0; 54 | text-align: left; 55 | } 56 | 57 | div.breadcrumbs { 58 | text-align: right; 59 | } 60 | 61 | #content-main { 62 | float: right; 63 | } 64 | 65 | #content-related { 66 | float: left; 67 | margin-left: -19em; 68 | margin-right: auto; 69 | } 70 | 71 | .colMS { 72 | margin-left: 20em !important; 73 | margin-right: 10px !important; 74 | } 75 | 76 | /* dashboard styles */ 77 | 78 | .dashboard .module table td a { 79 | padding-left: .6em; 80 | padding-right: 12px; 81 | } 82 | 83 | /* changelists styles */ 84 | 85 | .change-list ul.toplinks li { 86 | float: right; 87 | } 88 | 89 | .change-list .filtered { 90 | background: white url(../img/admin/changelist-bg_rtl.gif) top left repeat-y !important; 91 | } 92 | 93 | .change-list .filtered table { 94 | border-left: 1px solid #ddd; 95 | border-right: 0px none; 96 | } 97 | 98 | #changelist-filter { 99 | right: auto; 100 | left: 0; 101 | border-left: 0px none; 102 | border-right: 1px solid #ddd; 103 | } 104 | 105 | .change-list .filtered table, .change-list .filtered .paginator, .filtered #toolbar, .filtered div.xfull { 106 | margin-right: 0px !important; 107 | margin-left: 160px !important; 108 | } 109 | 110 | #changelist-filter li.selected { 111 | border-left: 0px none; 112 | padding-left: 0px; 113 | margin-left: 0; 114 | border-right: 5px solid #ccc; 115 | padding-right: 5px; 116 | margin-right: -10px; 117 | } 118 | 119 | .filtered .actions { 120 | border-left:1px solid #DDDDDD; 121 | margin-left:160px !important; 122 | border-right: 0 none; 123 | margin-right:0 !important; 124 | } 125 | 126 | /* FORMS */ 127 | 128 | .aligned label { 129 | padding: 0 0 3px 1em; 130 | float: right; 131 | } 132 | 133 | .submit-row { 134 | text-align: left 135 | } 136 | 137 | .submit-row p.deletelink-box { 138 | float: right; 139 | } 140 | 141 | .submit-row .deletelink { 142 | background: url(../img/admin/icon_deletelink.gif) 0 50% no-repeat; 143 | padding-right: 14px; 144 | } 145 | 146 | .vDateField, .vTimeField { 147 | margin-left: 2px; 148 | } 149 | 150 | form ul.inline li { 151 | float: right; 152 | padding-right: 0; 153 | padding-left: 7px; 154 | } 155 | 156 | input[type=submit].default, .submit-row input.default { 157 | float: left; 158 | } 159 | 160 | fieldset .field-box { 161 | float: right; 162 | margin-left: 20px; 163 | } 164 | 165 | .errorlist li { 166 | background-position: 100% .3em; 167 | padding: 4px 25px 4px 5px; 168 | } 169 | 170 | .errornote { 171 | background-position: 100% .3em; 172 | padding: 4px 25px 4px 5px; 173 | } 174 | 175 | /* WIDGETS */ 176 | 177 | .calendarnav-previous { 178 | top: 0; 179 | left: auto; 180 | right: 0; 181 | } 182 | 183 | .calendarnav-next { 184 | top: 0; 185 | right: auto; 186 | left: 0; 187 | } 188 | 189 | .calendar caption, .calendarbox h2 { 190 | text-align: center; 191 | } 192 | 193 | .selector { 194 | float: right; 195 | } 196 | 197 | .selector .selector-filter { 198 | text-align: right; 199 | } 200 | 201 | .inline-deletelink { 202 | float: left; 203 | } 204 | 205 | /* MISC */ 206 | 207 | .inline-related h2, .inline-group h2 { 208 | text-align: right 209 | } 210 | 211 | .inline-related h3 span.delete { 212 | padding-right: 20px; 213 | padding-left: inherit; 214 | left: 10px; 215 | right: inherit; 216 | } 217 | 218 | .inline-related h3 span.delete label { 219 | margin-left: inherit; 220 | margin-right: 2px; 221 | } 222 | -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/arrow-down.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/arrow-down.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/arrow-up.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/arrow-up.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/changelist-bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/changelist-bg.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/changelist-bg_rtl.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/changelist-bg_rtl.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/chooser-bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/chooser-bg.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/chooser_stacked-bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/chooser_stacked-bg.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/default-bg-reverse.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/default-bg-reverse.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/default-bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/default-bg.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/deleted-overlay.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/deleted-overlay.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/icon-no.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/icon-no.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/icon-unknown.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/icon-unknown.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/icon-yes.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/icon-yes.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/icon_addlink.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/icon_addlink.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/icon_alert.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/icon_alert.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/icon_calendar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/icon_calendar.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/icon_changelink.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/icon_changelink.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/icon_clock.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/icon_clock.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/icon_deletelink.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/icon_deletelink.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/icon_error.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/icon_error.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/icon_searchbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/icon_searchbox.png -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/icon_success.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/icon_success.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/inline-delete-8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/inline-delete-8bit.png -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/inline-delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/inline-delete.png -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/inline-restore-8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/inline-restore-8bit.png -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/inline-restore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/inline-restore.png -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/inline-splitter-bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/inline-splitter-bg.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/nav-bg-grabber.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/nav-bg-grabber.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/nav-bg-reverse.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/nav-bg-reverse.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/nav-bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/nav-bg.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/selector-add.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/selector-add.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/selector-addall.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/selector-addall.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/selector-remove.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/selector-remove.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/selector-removeall.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/selector-removeall.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/selector-search.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/selector-search.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/selector_stacked-add.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/selector_stacked-add.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/selector_stacked-remove.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/selector_stacked-remove.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/tool-left.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/tool-left.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/tool-left_over.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/tool-left_over.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/tool-right.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/tool-right.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/tool-right_over.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/tool-right_over.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/tooltag-add.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/tooltag-add.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/tooltag-add_over.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/tooltag-add_over.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/tooltag-arrowright.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/tooltag-arrowright.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/admin/tooltag-arrowright_over.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/admin/tooltag-arrowright_over.gif -------------------------------------------------------------------------------- /demo_project/static/admin/img/gis/move_vertex_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/gis/move_vertex_off.png -------------------------------------------------------------------------------- /demo_project/static/admin/img/gis/move_vertex_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/admin/img/gis/move_vertex_on.png -------------------------------------------------------------------------------- /demo_project/static/admin/js/LICENSE-JQUERY.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 John Resig, http://jquery.com/ 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /demo_project/static/admin/js/SelectBox.js: -------------------------------------------------------------------------------- 1 | var SelectBox = { 2 | cache: new Object(), 3 | init: function(id) { 4 | var box = document.getElementById(id); 5 | var node; 6 | SelectBox.cache[id] = new Array(); 7 | var cache = SelectBox.cache[id]; 8 | for (var i = 0; (node = box.options[i]); i++) { 9 | cache.push({value: node.value, text: node.text, displayed: 1}); 10 | } 11 | }, 12 | redisplay: function(id) { 13 | // Repopulate HTML select box from cache 14 | var box = document.getElementById(id); 15 | box.options.length = 0; // clear all options 16 | for (var i = 0, j = SelectBox.cache[id].length; i < j; i++) { 17 | var node = SelectBox.cache[id][i]; 18 | if (node.displayed) { 19 | box.options[box.options.length] = new Option(node.text, node.value, false, false); 20 | } 21 | } 22 | }, 23 | filter: function(id, text) { 24 | // Redisplay the HTML select box, displaying only the choices containing ALL 25 | // the words in text. (It's an AND search.) 26 | var tokens = text.toLowerCase().split(/\s+/); 27 | var node, token; 28 | for (var i = 0; (node = SelectBox.cache[id][i]); i++) { 29 | node.displayed = 1; 30 | for (var j = 0; (token = tokens[j]); j++) { 31 | if (node.text.toLowerCase().indexOf(token) == -1) { 32 | node.displayed = 0; 33 | } 34 | } 35 | } 36 | SelectBox.redisplay(id); 37 | }, 38 | delete_from_cache: function(id, value) { 39 | var node, delete_index = null; 40 | for (var i = 0; (node = SelectBox.cache[id][i]); i++) { 41 | if (node.value == value) { 42 | delete_index = i; 43 | break; 44 | } 45 | } 46 | var j = SelectBox.cache[id].length - 1; 47 | for (var i = delete_index; i < j; i++) { 48 | SelectBox.cache[id][i] = SelectBox.cache[id][i+1]; 49 | } 50 | SelectBox.cache[id].length--; 51 | }, 52 | add_to_cache: function(id, option) { 53 | SelectBox.cache[id].push({value: option.value, text: option.text, displayed: 1}); 54 | }, 55 | cache_contains: function(id, value) { 56 | // Check if an item is contained in the cache 57 | var node; 58 | for (var i = 0; (node = SelectBox.cache[id][i]); i++) { 59 | if (node.value == value) { 60 | return true; 61 | } 62 | } 63 | return false; 64 | }, 65 | move: function(from, to) { 66 | var from_box = document.getElementById(from); 67 | var to_box = document.getElementById(to); 68 | var option; 69 | for (var i = 0; (option = from_box.options[i]); i++) { 70 | if (option.selected && SelectBox.cache_contains(from, option.value)) { 71 | SelectBox.add_to_cache(to, {value: option.value, text: option.text, displayed: 1}); 72 | SelectBox.delete_from_cache(from, option.value); 73 | } 74 | } 75 | SelectBox.redisplay(from); 76 | SelectBox.redisplay(to); 77 | }, 78 | move_all: function(from, to) { 79 | var from_box = document.getElementById(from); 80 | var to_box = document.getElementById(to); 81 | var option; 82 | for (var i = 0; (option = from_box.options[i]); i++) { 83 | if (SelectBox.cache_contains(from, option.value)) { 84 | SelectBox.add_to_cache(to, {value: option.value, text: option.text, displayed: 1}); 85 | SelectBox.delete_from_cache(from, option.value); 86 | } 87 | } 88 | SelectBox.redisplay(from); 89 | SelectBox.redisplay(to); 90 | }, 91 | sort: function(id) { 92 | SelectBox.cache[id].sort( function(a, b) { 93 | a = a.text.toLowerCase(); 94 | b = b.text.toLowerCase(); 95 | try { 96 | if (a > b) return 1; 97 | if (a < b) return -1; 98 | } 99 | catch (e) { 100 | // silently fail on IE 'unknown' exception 101 | } 102 | return 0; 103 | } ); 104 | }, 105 | select_all: function(id) { 106 | var box = document.getElementById(id); 107 | for (var i = 0; i < box.options.length; i++) { 108 | box.options[i].selected = 'selected'; 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /demo_project/static/admin/js/actions.js: -------------------------------------------------------------------------------- 1 | (function($) { 2 | $.fn.actions = function(opts) { 3 | var options = $.extend({}, $.fn.actions.defaults, opts); 4 | var actionCheckboxes = $(this); 5 | var list_editable_changed = false; 6 | checker = function(checked) { 7 | if (checked) { 8 | showQuestion(); 9 | } else { 10 | reset(); 11 | } 12 | $(actionCheckboxes).attr("checked", checked) 13 | .parent().parent().toggleClass(options.selectedClass, checked); 14 | } 15 | updateCounter = function() { 16 | var sel = $(actionCheckboxes).filter(":checked").length; 17 | $(options.counterContainer).html(interpolate( 18 | ngettext('%(sel)s of %(cnt)s selected', '%(sel)s of %(cnt)s selected', sel), { 19 | sel: sel, 20 | cnt: _actions_icnt 21 | }, true)); 22 | $(options.allToggle).attr("checked", function() { 23 | if (sel == actionCheckboxes.length) { 24 | value = true; 25 | showQuestion(); 26 | } else { 27 | value = false; 28 | clearAcross(); 29 | } 30 | return value; 31 | }); 32 | } 33 | showQuestion = function() { 34 | $(options.acrossClears).hide(); 35 | $(options.acrossQuestions).show(); 36 | $(options.allContainer).hide(); 37 | } 38 | showClear = function() { 39 | $(options.acrossClears).show(); 40 | $(options.acrossQuestions).hide(); 41 | $(options.actionContainer).toggleClass(options.selectedClass); 42 | $(options.allContainer).show(); 43 | $(options.counterContainer).hide(); 44 | } 45 | reset = function() { 46 | $(options.acrossClears).hide(); 47 | $(options.acrossQuestions).hide(); 48 | $(options.allContainer).hide(); 49 | $(options.counterContainer).show(); 50 | } 51 | clearAcross = function() { 52 | reset(); 53 | $(options.acrossInput).val(0); 54 | $(options.actionContainer).removeClass(options.selectedClass); 55 | } 56 | // Show counter by default 57 | $(options.counterContainer).show(); 58 | // Check state of checkboxes and reinit state if needed 59 | $(this).filter(":checked").each(function(i) { 60 | $(this).parent().parent().toggleClass(options.selectedClass); 61 | updateCounter(); 62 | if ($(options.acrossInput).val() == 1) { 63 | showClear(); 64 | } 65 | }); 66 | $(options.allToggle).show().click(function() { 67 | checker($(this).attr("checked")); 68 | updateCounter(); 69 | }); 70 | $("div.actions span.question a").click(function(event) { 71 | event.preventDefault(); 72 | $(options.acrossInput).val(1); 73 | showClear(); 74 | }); 75 | $("div.actions span.clear a").click(function(event) { 76 | event.preventDefault(); 77 | $(options.allToggle).attr("checked", false); 78 | clearAcross(); 79 | checker(0); 80 | updateCounter(); 81 | }); 82 | lastChecked = null; 83 | $(actionCheckboxes).click(function(event) { 84 | if (!event) { var event = window.event; } 85 | var target = event.target ? event.target : event.srcElement; 86 | if (lastChecked && $.data(lastChecked) != $.data(target) && event.shiftKey == true) { 87 | var inrange = false; 88 | $(lastChecked).attr("checked", target.checked) 89 | .parent().parent().toggleClass(options.selectedClass, target.checked); 90 | $(actionCheckboxes).each(function() { 91 | if ($.data(this) == $.data(lastChecked) || $.data(this) == $.data(target)) { 92 | inrange = (inrange) ? false : true; 93 | } 94 | if (inrange) { 95 | $(this).attr("checked", target.checked) 96 | .parent().parent().toggleClass(options.selectedClass, target.checked); 97 | } 98 | }); 99 | } 100 | $(target).parent().parent().toggleClass(options.selectedClass, target.checked); 101 | lastChecked = target; 102 | updateCounter(); 103 | }); 104 | $('form#changelist-form table#result_list tr').find('td:gt(0) :input').change(function() { 105 | list_editable_changed = true; 106 | }); 107 | $('form#changelist-form button[name="index"]').click(function(event) { 108 | if (list_editable_changed) { 109 | return confirm(gettext("You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.")); 110 | } 111 | }); 112 | $('form#changelist-form input[name="_save"]').click(function(event) { 113 | var action_changed = false; 114 | $('div.actions select option:selected').each(function() { 115 | if ($(this).val()) { 116 | action_changed = true; 117 | } 118 | }); 119 | if (action_changed) { 120 | if (list_editable_changed) { 121 | return confirm(gettext("You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.")); 122 | } else { 123 | return confirm(gettext("You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button.")); 124 | } 125 | } 126 | }); 127 | } 128 | /* Setup plugin defaults */ 129 | $.fn.actions.defaults = { 130 | actionContainer: "div.actions", 131 | counterContainer: "span.action-counter", 132 | allContainer: "div.actions span.all", 133 | acrossInput: "div.actions input.select-across", 134 | acrossQuestions: "div.actions span.question", 135 | acrossClears: "div.actions span.clear", 136 | allToggle: "#action-toggle", 137 | selectedClass: "selected" 138 | } 139 | })(django.jQuery); 140 | -------------------------------------------------------------------------------- /demo_project/static/admin/js/actions.min.js: -------------------------------------------------------------------------------- 1 | (function(a){a.fn.actions=function(h){var b=a.extend({},a.fn.actions.defaults,h),e=a(this),f=false;checker=function(c){c?showQuestion():reset();a(e).attr("checked",c).parent().parent().toggleClass(b.selectedClass,c)};updateCounter=function(){var c=a(e).filter(":checked").length;a(b.counterContainer).html(interpolate(ngettext("%(sel)s of %(cnt)s selected","%(sel)s of %(cnt)s selected",c),{sel:c,cnt:_actions_icnt},true));a(b.allToggle).attr("checked",function(){if(c==e.length){value=true;showQuestion()}else{value= 2 | false;clearAcross()}return value})};showQuestion=function(){a(b.acrossClears).hide();a(b.acrossQuestions).show();a(b.allContainer).hide()};showClear=function(){a(b.acrossClears).show();a(b.acrossQuestions).hide();a(b.actionContainer).toggleClass(b.selectedClass);a(b.allContainer).show();a(b.counterContainer).hide()};reset=function(){a(b.acrossClears).hide();a(b.acrossQuestions).hide();a(b.allContainer).hide();a(b.counterContainer).show()};clearAcross=function(){reset();a(b.acrossInput).val(0);a(b.actionContainer).removeClass(b.selectedClass)}; 3 | a(b.counterContainer).show();a(this).filter(":checked").each(function(){a(this).parent().parent().toggleClass(b.selectedClass);updateCounter();a(b.acrossInput).val()==1&&showClear()});a(b.allToggle).show().click(function(){checker(a(this).attr("checked"));updateCounter()});a("div.actions span.question a").click(function(c){c.preventDefault();a(b.acrossInput).val(1);showClear()});a("div.actions span.clear a").click(function(c){c.preventDefault();a(b.allToggle).attr("checked",false);clearAcross();checker(0); 4 | updateCounter()});lastChecked=null;a(e).click(function(c){if(!c)c=window.event;var d=c.target?c.target:c.srcElement;if(lastChecked&&a.data(lastChecked)!=a.data(d)&&c.shiftKey==true){var g=false;a(lastChecked).attr("checked",d.checked).parent().parent().toggleClass(b.selectedClass,d.checked);a(e).each(function(){if(a.data(this)==a.data(lastChecked)||a.data(this)==a.data(d))g=g?false:true;g&&a(this).attr("checked",d.checked).parent().parent().toggleClass(b.selectedClass,d.checked)})}a(d).parent().parent().toggleClass(b.selectedClass, 5 | d.checked);lastChecked=d;updateCounter()});a("form#changelist-form table#result_list tr").find("td:gt(0) :input").change(function(){f=true});a('form#changelist-form button[name="index"]').click(function(){if(f)return confirm(gettext("You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost."))});a('form#changelist-form input[name="_save"]').click(function(){var c=false;a("div.actions select option:selected").each(function(){if(a(this).val())c= 6 | true});if(c)return f?confirm(gettext("You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.")):confirm(gettext("You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button."))})};a.fn.actions.defaults={actionContainer:"div.actions",counterContainer:"span.action-counter",allContainer:"div.actions span.all",acrossInput:"div.actions input.select-across", 7 | acrossQuestions:"div.actions span.question",acrossClears:"div.actions span.clear",allToggle:"#action-toggle",selectedClass:"selected"}})(django.jQuery); 8 | -------------------------------------------------------------------------------- /demo_project/static/admin/js/admin/RelatedObjectLookups.js: -------------------------------------------------------------------------------- 1 | // Handles related-objects functionality: lookup link for raw_id_fields 2 | // and Add Another links. 3 | 4 | function html_unescape(text) { 5 | // Unescape a string that was escaped using django.utils.html.escape. 6 | text = text.replace(/</g, '<'); 7 | text = text.replace(/>/g, '>'); 8 | text = text.replace(/"/g, '"'); 9 | text = text.replace(/'/g, "'"); 10 | text = text.replace(/&/g, '&'); 11 | return text; 12 | } 13 | 14 | // IE doesn't accept periods or dashes in the window name, but the element IDs 15 | // we use to generate popup window names may contain them, therefore we map them 16 | // to allowed characters in a reversible way so that we can locate the correct 17 | // element when the popup window is dismissed. 18 | function id_to_windowname(text) { 19 | text = text.replace(/\./g, '__dot__'); 20 | text = text.replace(/\-/g, '__dash__'); 21 | return text; 22 | } 23 | 24 | function windowname_to_id(text) { 25 | text = text.replace(/__dot__/g, '.'); 26 | text = text.replace(/__dash__/g, '-'); 27 | return text; 28 | } 29 | 30 | function showRelatedObjectLookupPopup(triggeringLink) { 31 | var name = triggeringLink.id.replace(/^lookup_/, ''); 32 | name = id_to_windowname(name); 33 | var href; 34 | if (triggeringLink.href.search(/\?/) >= 0) { 35 | href = triggeringLink.href + '&pop=1'; 36 | } else { 37 | href = triggeringLink.href + '?pop=1'; 38 | } 39 | var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes'); 40 | win.focus(); 41 | return false; 42 | } 43 | 44 | function dismissRelatedLookupPopup(win, chosenId) { 45 | var name = windowname_to_id(win.name); 46 | var elem = document.getElementById(name); 47 | if (elem.className.indexOf('vManyToManyRawIdAdminField') != -1 && elem.value) { 48 | elem.value += ',' + chosenId; 49 | } else { 50 | document.getElementById(name).value = chosenId; 51 | } 52 | win.close(); 53 | } 54 | 55 | function showAddAnotherPopup(triggeringLink) { 56 | var name = triggeringLink.id.replace(/^add_/, ''); 57 | name = id_to_windowname(name); 58 | href = triggeringLink.href 59 | if (href.indexOf('?') == -1) { 60 | href += '?_popup=1'; 61 | } else { 62 | href += '&_popup=1'; 63 | } 64 | var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes'); 65 | win.focus(); 66 | return false; 67 | } 68 | 69 | function dismissAddAnotherPopup(win, newId, newRepr) { 70 | // newId and newRepr are expected to have previously been escaped by 71 | // django.utils.html.escape. 72 | newId = html_unescape(newId); 73 | newRepr = html_unescape(newRepr); 74 | var name = windowname_to_id(win.name); 75 | var elem = document.getElementById(name); 76 | if (elem) { 77 | if (elem.nodeName == 'SELECT') { 78 | var o = new Option(newRepr, newId); 79 | elem.options[elem.options.length] = o; 80 | o.selected = true; 81 | } else if (elem.nodeName == 'INPUT') { 82 | if (elem.className.indexOf('vManyToManyRawIdAdminField') != -1 && elem.value) { 83 | elem.value += ',' + newId; 84 | } else { 85 | elem.value = newId; 86 | } 87 | } 88 | } else { 89 | var toId = name + "_to"; 90 | elem = document.getElementById(toId); 91 | var o = new Option(newRepr, newId); 92 | SelectBox.add_to_cache(toId, o); 93 | SelectBox.redisplay(toId); 94 | } 95 | win.close(); 96 | } 97 | -------------------------------------------------------------------------------- /demo_project/static/admin/js/admin/ordering.js: -------------------------------------------------------------------------------- 1 | addEvent(window, 'load', reorder_init); 2 | 3 | var lis; 4 | var top = 0; 5 | var left = 0; 6 | var height = 30; 7 | 8 | function reorder_init() { 9 | lis = document.getElementsBySelector('ul#orderthese li'); 10 | var input = document.getElementsBySelector('input[name=order_]')[0]; 11 | setOrder(input.value.split(',')); 12 | input.disabled = true; 13 | draw(); 14 | // Now initialise the dragging behaviour 15 | var limit = (lis.length - 1) * height; 16 | for (var i = 0; i < lis.length; i++) { 17 | var li = lis[i]; 18 | var img = document.getElementById('handle'+li.id); 19 | li.style.zIndex = 1; 20 | Drag.init(img, li, left + 10, left + 10, top + 10, top + 10 + limit); 21 | li.onDragStart = startDrag; 22 | li.onDragEnd = endDrag; 23 | img.style.cursor = 'move'; 24 | } 25 | } 26 | 27 | function submitOrderForm() { 28 | var inputOrder = document.getElementsBySelector('input[name=order_]')[0]; 29 | inputOrder.value = getOrder(); 30 | inputOrder.disabled=false; 31 | } 32 | 33 | function startDrag() { 34 | this.style.zIndex = '10'; 35 | this.className = 'dragging'; 36 | } 37 | 38 | function endDrag(x, y) { 39 | this.style.zIndex = '1'; 40 | this.className = ''; 41 | // Work out how far along it has been dropped, using x co-ordinate 42 | var oldIndex = this.index; 43 | var newIndex = Math.round((y - 10 - top) / height); 44 | // 'Snap' to the correct position 45 | this.style.top = (10 + top + newIndex * height) + 'px'; 46 | this.index = newIndex; 47 | moveItem(oldIndex, newIndex); 48 | } 49 | 50 | function moveItem(oldIndex, newIndex) { 51 | // Swaps two items, adjusts the index and left co-ord for all others 52 | if (oldIndex == newIndex) { 53 | return; // Nothing to swap; 54 | } 55 | var direction, lo, hi; 56 | if (newIndex > oldIndex) { 57 | lo = oldIndex; 58 | hi = newIndex; 59 | direction = -1; 60 | } else { 61 | direction = 1; 62 | hi = oldIndex; 63 | lo = newIndex; 64 | } 65 | var lis2 = new Array(); // We will build the new order in this array 66 | for (var i = 0; i < lis.length; i++) { 67 | if (i < lo || i > hi) { 68 | // Position of items not between the indexes is unaffected 69 | lis2[i] = lis[i]; 70 | continue; 71 | } else if (i == newIndex) { 72 | lis2[i] = lis[oldIndex]; 73 | continue; 74 | } else { 75 | // Item is between the two indexes - move it along 1 76 | lis2[i] = lis[i - direction]; 77 | } 78 | } 79 | // Re-index everything 80 | reIndex(lis2); 81 | lis = lis2; 82 | draw(); 83 | // document.getElementById('hiddenOrder').value = getOrder(); 84 | document.getElementsBySelector('input[name=order_]')[0].value = getOrder(); 85 | } 86 | 87 | function reIndex(lis) { 88 | for (var i = 0; i < lis.length; i++) { 89 | lis[i].index = i; 90 | } 91 | } 92 | 93 | function draw() { 94 | for (var i = 0; i < lis.length; i++) { 95 | var li = lis[i]; 96 | li.index = i; 97 | li.style.position = 'absolute'; 98 | li.style.left = (10 + left) + 'px'; 99 | li.style.top = (10 + top + (i * height)) + 'px'; 100 | } 101 | } 102 | 103 | function getOrder() { 104 | var order = new Array(lis.length); 105 | for (var i = 0; i < lis.length; i++) { 106 | order[i] = lis[i].id.substring(1, 100); 107 | } 108 | return order.join(','); 109 | } 110 | 111 | function setOrder(id_list) { 112 | /* Set the current order to match the lsit of IDs */ 113 | var temp_lis = new Array(); 114 | for (var i = 0; i < id_list.length; i++) { 115 | var id = 'p' + id_list[i]; 116 | temp_lis[temp_lis.length] = document.getElementById(id); 117 | } 118 | reIndex(temp_lis); 119 | lis = temp_lis; 120 | draw(); 121 | } 122 | 123 | function addEvent(elm, evType, fn, useCapture) 124 | // addEvent and removeEvent 125 | // cross-browser event handling for IE5+, NS6 and Mozilla 126 | // By Scott Andrew 127 | { 128 | if (elm.addEventListener){ 129 | elm.addEventListener(evType, fn, useCapture); 130 | return true; 131 | } else if (elm.attachEvent){ 132 | var r = elm.attachEvent("on"+evType, fn); 133 | return r; 134 | } else { 135 | elm['on'+evType] = fn; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /demo_project/static/admin/js/collapse.js: -------------------------------------------------------------------------------- 1 | (function($) { 2 | $(document).ready(function() { 3 | // Add anchor tag for Show/Hide link 4 | $("fieldset.collapse").each(function(i, elem) { 5 | // Don't hide if fields in this fieldset have errors 6 | if ( $(elem).find("div.errors").length == 0 ) { 7 | $(elem).addClass("collapsed"); 8 | $(elem).find("h2").first().append(' (' + gettext("Show") + 10 | ')'); 11 | } 12 | }); 13 | // Add toggle to anchor tag 14 | $("fieldset.collapse a.collapse-toggle").toggle( 15 | function() { // Show 16 | $(this).text(gettext("Hide")); 17 | $(this).closest("fieldset").removeClass("collapsed"); 18 | return false; 19 | }, 20 | function() { // Hide 21 | $(this).text(gettext("Show")); 22 | $(this).closest("fieldset").addClass("collapsed"); 23 | return false; 24 | } 25 | ); 26 | }); 27 | })(django.jQuery); 28 | -------------------------------------------------------------------------------- /demo_project/static/admin/js/collapse.min.js: -------------------------------------------------------------------------------- 1 | (function(a){a(document).ready(function(){a("fieldset.collapse").each(function(c,b){if(a(b).find("div.errors").length==0){a(b).addClass("collapsed");a(b).find("h2").first().append(' ('+gettext("Show")+")")}});a("fieldset.collapse a.collapse-toggle").toggle(function(){a(this).text(gettext("Hide"));a(this).closest("fieldset").removeClass("collapsed");return false},function(){a(this).text(gettext("Show"));a(this).closest("fieldset").addClass("collapsed"); 2 | return false})})})(django.jQuery); 3 | -------------------------------------------------------------------------------- /demo_project/static/admin/js/compress.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import optparse 4 | import subprocess 5 | import sys 6 | 7 | here = os.path.dirname(__file__) 8 | 9 | def main(): 10 | usage = "usage: %prog [file1..fileN]" 11 | description = """With no file paths given this script will automatically 12 | compress all jQuery-based files of the admin app. Requires the Google Closure 13 | Compiler library and Java version 6 or later.""" 14 | parser = optparse.OptionParser(usage, description=description) 15 | parser.add_option("-c", dest="compiler", default="~/bin/compiler.jar", 16 | help="path to Closure Compiler jar file") 17 | parser.add_option("-v", "--verbose", 18 | action="store_true", dest="verbose") 19 | parser.add_option("-q", "--quiet", 20 | action="store_false", dest="verbose") 21 | (options, args) = parser.parse_args() 22 | 23 | compiler = os.path.expanduser(options.compiler) 24 | if not os.path.exists(compiler): 25 | sys.exit("Google Closure compiler jar file %s not found. Please use the -c option to specify the path." % compiler) 26 | 27 | if not args: 28 | if options.verbose: 29 | sys.stdout.write("No filenames given; defaulting to admin scripts\n") 30 | args = [os.path.join(here, f) for f in [ 31 | "actions.js", "collapse.js", "inlines.js", "prepopulate.js"]] 32 | 33 | for arg in args: 34 | if not arg.endswith(".js"): 35 | arg = arg + ".js" 36 | to_compress = os.path.expanduser(arg) 37 | if os.path.exists(to_compress): 38 | to_compress_min = "%s.min.js" % "".join(arg.rsplit(".js")) 39 | cmd = "java -jar %s --js %s --js_output_file %s" % (compiler, to_compress, to_compress_min) 40 | if options.verbose: 41 | sys.stdout.write("Running: %s\n" % cmd) 42 | subprocess.call(cmd.split()) 43 | else: 44 | sys.stdout.write("File %s not found. Sure it exists?\n" % to_compress) 45 | 46 | if __name__ == '__main__': 47 | main() 48 | -------------------------------------------------------------------------------- /demo_project/static/admin/js/inlines.min.js: -------------------------------------------------------------------------------- 1 | (function(b){b.fn.formset=function(g){var a=b.extend({},b.fn.formset.defaults,g),k=function(c,f,d){var e=new RegExp("("+f+"-(\\d+|__prefix__))");f=f+"-"+d;b(c).attr("for")&&b(c).attr("for",b(c).attr("for").replace(e,f));if(c.id)c.id=c.id.replace(e,f);if(c.name)c.name=c.name.replace(e,f)};g=b("#id_"+a.prefix+"-TOTAL_FORMS").attr("autocomplete","off");var l=parseInt(g.val()),h=b("#id_"+a.prefix+"-MAX_NUM_FORMS").attr("autocomplete","off");g=h.val()==""||h.val()-g.val()>0;b(this).each(function(){b(this).not("."+ 2 | a.emptyCssClass).addClass(a.formCssClass)});if(b(this).length&&g){var j;if(b(this).attr("tagName")=="TR"){g=this.eq(0).children().length;b(this).parent().append(''+a.addText+"");j=b(this).parent().find("tr:last a")}else{b(this).filter(":last").after('");j=b(this).filter(":last").next().find("a")}j.click(function(){var c=b("#id_"+ 3 | a.prefix+"-TOTAL_FORMS"),f=b("#"+a.prefix+"-empty"),d=f.clone(true);d.removeClass(a.emptyCssClass).addClass(a.formCssClass).attr("id",a.prefix+"-"+l);if(d.is("tr"))d.children(":last").append('
'+a.deleteText+"
");else d.is("ul")||d.is("ol")?d.append('
  • '+a.deleteText+"
  • "):d.children(":first").append(''+ 4 | a.deleteText+"");d.find("*").each(function(){k(this,a.prefix,c.val())});d.insertBefore(b(f));b(c).val(parseInt(c.val())+1);l+=1;h.val()!=""&&h.val()-c.val()<=0&&j.parent().hide();d.find("a."+a.deleteCssClass).click(function(){var e=b(this).parents("."+a.formCssClass);e.remove();l-=1;a.removed&&a.removed(e);e=b("."+a.formCssClass);b("#id_"+a.prefix+"-TOTAL_FORMS").val(e.length);if(h.val()==""||h.val()-e.length>0)j.parent().show();for(var i=0,m=e.length;i 0) { 25 | values.push($(field).val()); 26 | } 27 | }) 28 | field.val(URLify(values.join(' '), maxLength)); 29 | }; 30 | 31 | $(dependencies.join(',')).keyup(populate).change(populate).focus(populate); 32 | }); 33 | }; 34 | })(django.jQuery); 35 | -------------------------------------------------------------------------------- /demo_project/static/admin/js/prepopulate.min.js: -------------------------------------------------------------------------------- 1 | (function(a){a.fn.prepopulate=function(d,g){return this.each(function(){var b=a(this);b.data("_changed",false);b.change(function(){b.data("_changed",true)});var c=function(){if(b.data("_changed")!=true){var e=[];a.each(d,function(h,f){a(f).val().length>0&&e.push(a(f).val())});b.val(URLify(e.join(" "),g))}};a(d.join(",")).keyup(c).change(c).focus(c)})}})(django.jQuery); 2 | -------------------------------------------------------------------------------- /demo_project/static/admin/js/timeparse.js: -------------------------------------------------------------------------------- 1 | var timeParsePatterns = [ 2 | // 9 3 | { re: /^\d{1,2}$/i, 4 | handler: function(bits) { 5 | if (bits[0].length == 1) { 6 | return '0' + bits[0] + ':00'; 7 | } else { 8 | return bits[0] + ':00'; 9 | } 10 | } 11 | }, 12 | // 13:00 13 | { re: /^\d{2}[:.]\d{2}$/i, 14 | handler: function(bits) { 15 | return bits[0].replace('.', ':'); 16 | } 17 | }, 18 | // 9:00 19 | { re: /^\d[:.]\d{2}$/i, 20 | handler: function(bits) { 21 | return '0' + bits[0].replace('.', ':'); 22 | } 23 | }, 24 | // 3 am / 3 a.m. / 3am 25 | { re: /^(\d+)\s*([ap])(?:.?m.?)?$/i, 26 | handler: function(bits) { 27 | var hour = parseInt(bits[1]); 28 | if (hour == 12) { 29 | hour = 0; 30 | } 31 | if (bits[2].toLowerCase() == 'p') { 32 | if (hour == 12) { 33 | hour = 0; 34 | } 35 | return (hour + 12) + ':00'; 36 | } else { 37 | if (hour < 10) { 38 | return '0' + hour + ':00'; 39 | } else { 40 | return hour + ':00'; 41 | } 42 | } 43 | } 44 | }, 45 | // 3.30 am / 3:15 a.m. / 3.00am 46 | { re: /^(\d+)[.:](\d{2})\s*([ap]).?m.?$/i, 47 | handler: function(bits) { 48 | var hour = parseInt(bits[1]); 49 | var mins = parseInt(bits[2]); 50 | if (mins < 10) { 51 | mins = '0' + mins; 52 | } 53 | if (hour == 12) { 54 | hour = 0; 55 | } 56 | if (bits[3].toLowerCase() == 'p') { 57 | if (hour == 12) { 58 | hour = 0; 59 | } 60 | return (hour + 12) + ':' + mins; 61 | } else { 62 | if (hour < 10) { 63 | return '0' + hour + ':' + mins; 64 | } else { 65 | return hour + ':' + mins; 66 | } 67 | } 68 | } 69 | }, 70 | // noon 71 | { re: /^no/i, 72 | handler: function(bits) { 73 | return '12:00'; 74 | } 75 | }, 76 | // midnight 77 | { re: /^mid/i, 78 | handler: function(bits) { 79 | return '00:00'; 80 | } 81 | } 82 | ]; 83 | 84 | function parseTimeString(s) { 85 | for (var i = 0; i < timeParsePatterns.length; i++) { 86 | var re = timeParsePatterns[i].re; 87 | var handler = timeParsePatterns[i].handler; 88 | var bits = re.exec(s); 89 | if (bits) { 90 | return handler(bits); 91 | } 92 | } 93 | return s; 94 | } 95 | -------------------------------------------------------------------------------- /demo_project/static/css/c3.min.css: -------------------------------------------------------------------------------- 1 | .c3 svg{font:10px sans-serif;-webkit-tap-highlight-color:transparent}.c3 line,.c3 path{fill:none;stroke:#000}.c3 text{-webkit-user-select:none;-moz-user-select:none;user-select:none}.c3-bars path,.c3-event-rect,.c3-legend-item-tile,.c3-xgrid-focus,.c3-ygrid{shape-rendering:crispEdges}.c3-chart-arc path{stroke:#fff}.c3-chart-arc text{fill:#fff;font-size:13px}.c3-grid line{stroke:#aaa}.c3-grid text{fill:#aaa}.c3-xgrid,.c3-ygrid{stroke-dasharray:3 3}.c3-text.c3-empty{fill:gray;font-size:2em}.c3-line{stroke-width:1px}.c3-circle._expanded_{stroke-width:1px;stroke:#fff}.c3-selected-circle{fill:#fff;stroke-width:2px}.c3-bar{stroke-width:0}.c3-bar._expanded_{fill-opacity:.75}.c3-target.c3-focused{opacity:1}.c3-target.c3-focused path.c3-line,.c3-target.c3-focused path.c3-step{stroke-width:2px}.c3-target.c3-defocused{opacity:.3!important}.c3-region{fill:#4682b4;fill-opacity:.1}.c3-brush .extent{fill-opacity:.1}.c3-legend-item{font-size:12px}.c3-legend-item-hidden{opacity:.15}.c3-legend-background{opacity:.75;fill:#fff;stroke:#d3d3d3;stroke-width:1}.c3-title{font:14px sans-serif}.c3-tooltip-container{z-index:10}.c3-tooltip{border-collapse:collapse;border-spacing:0;background-color:#fff;empty-cells:show;-webkit-box-shadow:7px 7px 12px -9px #777;-moz-box-shadow:7px 7px 12px -9px #777;box-shadow:7px 7px 12px -9px #777;opacity:.9}.c3-tooltip tr{border:1px solid #CCC}.c3-tooltip th{background-color:#aaa;font-size:14px;padding:2px 5px;text-align:left;color:#FFF}.c3-tooltip td{font-size:13px;padding:3px 6px;background-color:#fff;border-left:1px dotted #999}.c3-tooltip td>span{display:inline-block;width:10px;height:10px;margin-right:6px}.c3-tooltip td.value{text-align:right}.c3-area{stroke-width:0;opacity:.2}.c3-chart-arcs-title{dominant-baseline:middle;font-size:1.3em}.c3-chart-arcs .c3-chart-arcs-background{fill:#e0e0e0;stroke:none}.c3-chart-arcs .c3-chart-arcs-gauge-unit{fill:#000;font-size:16px}.c3-chart-arcs .c3-chart-arcs-gauge-max,.c3-chart-arcs .c3-chart-arcs-gauge-min{fill:#777}.c3-chart-arc .c3-gauge-value{fill:#000} -------------------------------------------------------------------------------- /demo_project/static/css/highmaps.css: -------------------------------------------------------------------------------- 1 | 2 | #demo-wrapper { 3 | max-width: 1000px; 4 | margin: 0 auto; 5 | height: 560px; 6 | } 7 | #mapBox { 8 | width: 80%; 9 | float: left; 10 | } 11 | #container { 12 | height: 500px; 13 | min-width: 310px; 14 | max-width: 800px; 15 | margin: 0 auto; 16 | } 17 | #sideBox { 18 | float: right; 19 | width: 16%; 20 | margin: 100px 1% 0 1%; 21 | padding-left: 1%; 22 | border-left: 1px solid silver; 23 | display: none; 24 | } 25 | #infoBox { 26 | margin-top: 10px; 27 | } 28 | .or-view-as { 29 | margin: 0.5em 0; 30 | } 31 | #up { 32 | height: 20px; 33 | max-width: 400px; 34 | margin: 0 auto; 35 | } 36 | #up a { 37 | cursor: pointer; 38 | padding-left: 40px; 39 | } 40 | .selector { 41 | height: 40px; 42 | max-width: 400px; 43 | margin: 0 auto; 44 | position: relative; 45 | } 46 | .selector .prev-next { 47 | position: absolute; 48 | padding: 0 10px; 49 | font-size: 30px; 50 | line-height: 20px; 51 | background: white; 52 | font-weight: bold; 53 | color: #999; 54 | top: -2px; 55 | display: none; 56 | border: none; 57 | } 58 | .selector .custom-combobox { 59 | display: block; 60 | position: absolute; 61 | left: 40px; 62 | right: 110px; 63 | } 64 | .selector .custom-combobox .custom-combobox-input { 65 | position: absolute; 66 | font-size: 14px; 67 | color: silver; 68 | border-radius: 0; 69 | height: 24px; 70 | display: block; 71 | background: url(https://www.highcharts.com/samples/graphics/search.png) 5px 5px no-repeat white; 72 | padding: 1px 5px 1px 30px; 73 | width: 100%; 74 | } 75 | .selector .custom-combobox .ui-autocomplete-input:focus { 76 | color: black; 77 | } 78 | .selector .custom-combobox .ui-autocomplete-input.valid { 79 | color: black; 80 | } 81 | .selector .custom-combobox-toggle { 82 | position: absolute; 83 | display: block; 84 | right: -78px; 85 | border-radius: 0; 86 | } 87 | 88 | .selector #btn-next-map { 89 | right: -12px; 90 | } 91 | .ui-autocomplete { 92 | max-height: 500px; 93 | overflow: auto; 94 | } 95 | .ui-autocomplete .option-header { 96 | font-style: italic; 97 | font-weight: bold; 98 | margin: 5px 0; 99 | font-size: 1.2em; 100 | color: gray; 101 | } 102 | 103 | .loading { 104 | margin-top: 10em; 105 | text-align: center; 106 | color: gray; 107 | } 108 | .ui-button-icon-only .ui-button-text { 109 | height: 26px; 110 | padding: 0 !important; 111 | background: white; 112 | } 113 | #infoBox .button { 114 | border: none; 115 | border-radius: 3px; 116 | background: #a4edba; 117 | padding: 5px; 118 | color: black; 119 | text-decoration: none; 120 | font-size: 12px; 121 | white-space: nowrap; 122 | cursor: pointer; 123 | margin: 0 3px; 124 | line-height: 30px; 125 | } 126 | 127 | @media (max-width: 768px) { 128 | #demo-wrapper { 129 | width: auto; 130 | height: auto; 131 | } 132 | #mapBox { 133 | width: auto; 134 | float: none; 135 | } 136 | #container { 137 | height: 310px; 138 | } 139 | #sideBox { 140 | float: none; 141 | width: auto; 142 | margin-top: 0; 143 | border-left: none; 144 | border-top: 1px solid silver; 145 | } 146 | /* 147 | .selector { 148 | width: 300px; 149 | } 150 | .selector .custom-combobox .custom-combobox-input { 151 | width: 190px; 152 | } 153 | .selector .custom-combobox-toggle { 154 | left: 226px; 155 | } 156 | .selector #btn-next-map { 157 | left: 310px; 158 | } 159 | */ 160 | 161 | } 162 | 163 | 164 | -------------------------------------------------------------------------------- /demo_project/static/css/layout.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: sans-serif; 3 | font-size: 16px; 4 | margin: 50px; 5 | max-width: 800px; 6 | } 7 | -------------------------------------------------------------------------------- /demo_project/static/css/main.css: -------------------------------------------------------------------------------- 1 | .redlabel { 2 | color : #BF0000; 3 | } 4 | .greenlabel { 5 | color : #46C885; 6 | } 7 | .bluelabel { 8 | color : #49AFCD; 9 | } 10 | 11 | .big { 12 | font-size: 16px; 13 | font-weight: bold; 14 | text-rendering: optimizelegibility; 15 | font-family: Optima; 16 | } 17 | 18 | .optima { 19 | font-family: Optima; 20 | } 21 | 22 | .hero-unit { 23 | padding: 20px; 24 | } 25 | 26 | td { 27 | font-size: 16px; 28 | } 29 | 30 | 31 | .font-set{ 32 | font-family: Ubuntu; 33 | margin-left: 125px; 34 | } 35 | 36 | body, h3, div, p { 37 | font-family: Ubuntu; 38 | } 39 | 40 | #reference { 41 | text-decoration: underline; 42 | } -------------------------------------------------------------------------------- /demo_project/static/img/favicon.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/img/favicon.gif -------------------------------------------------------------------------------- /demo_project/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/img/favicon.ico -------------------------------------------------------------------------------- /demo_project/static/img/glyphicons-halflings-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/img/glyphicons-halflings-white.png -------------------------------------------------------------------------------- /demo_project/static/img/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/demo_project/static/img/glyphicons-halflings.png -------------------------------------------------------------------------------- /demo_project/static/js/jquery.colorhelpers.min.js: -------------------------------------------------------------------------------- 1 | /* Plugin for jQuery for working with colors. 2 | * 3 | * Version 1.1. 4 | * 5 | * Inspiration from jQuery color animation plugin by John Resig. 6 | * 7 | * Released under the MIT license by Ole Laursen, October 2009. 8 | * 9 | * Examples: 10 | * 11 | * $.color.parse("#fff").scale('rgb', 0.25).add('a', -0.5).toString() 12 | * var c = $.color.extract($("#mydiv"), 'background-color'); 13 | * console.log(c.r, c.g, c.b, c.a); 14 | * $.color.make(100, 50, 25, 0.4).toString() // returns "rgba(100,50,25,0.4)" 15 | * 16 | * Note that .scale() and .add() return the same modified object 17 | * instead of making a new one. 18 | * 19 | * V. 1.1: Fix error handling so e.g. parsing an empty string does 20 | * produce a color rather than just crashing. 21 | */(function(e){e.color={},e.color.make=function(t,n,r,i){var s={};return s.r=t||0,s.g=n||0,s.b=r||0,s.a=i!=null?i:1,s.add=function(e,t){for(var n=0;n=1?"rgb("+[s.r,s.g,s.b].join(",")+")":"rgba("+[s.r,s.g,s.b,s.a].join(",")+")"},s.normalize=function(){function e(e,t,n){return tn?n:t}return s.r=e(0,parseInt(s.r),255),s.g=e(0,parseInt(s.g),255),s.b=e(0,parseInt(s.b),255),s.a=e(0,s.a,1),s},s.clone=function(){return e.color.make(s.r,s.b,s.g,s.a)},s.normalize()},e.color.extract=function(t,n){var r;do{r=t.css(n).toLowerCase();if(r!=""&&r!="transparent")break;t=t.parent()}while(!e.nodeName(t.get(0),"body"));return r=="rgba(0, 0, 0, 0)"&&(r="transparent"),e.color.parse(r)},e.color.parse=function(n){var r,i=e.color.make;if(r=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(n))return i(parseInt(r[1],10),parseInt(r[2],10),parseInt(r[3],10));if(r=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(n))return i(parseInt(r[1],10),parseInt(r[2],10),parseInt(r[3],10),parseFloat(r[4]));if(r=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(n))return i(parseFloat(r[1])*2.55,parseFloat(r[2])*2.55,parseFloat(r[3])*2.55);if(r=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(n))return i(parseFloat(r[1])*2.55,parseFloat(r[2])*2.55,parseFloat(r[3])*2.55,parseFloat(r[4]));if(r=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(n))return i(parseInt(r[1],16),parseInt(r[2],16),parseInt(r[3],16));if(r=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(n))return i(parseInt(r[1]+r[1],16),parseInt(r[2]+r[2],16),parseInt(r[3]+r[3],16));var s=e.trim(n).toLowerCase();return s=="transparent"?i(255,255,255,0):(r=t[s]||[0,0,0],i(r[0],r[1],r[2]))};var t={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})(jQuery); -------------------------------------------------------------------------------- /demo_project/static/js/jquery.flot.canvas.min.js: -------------------------------------------------------------------------------- 1 | /* Flot plugin for drawing all elements of a plot on the canvas. 2 | 3 | Copyright (c) 2007-2013 IOLA and Ole Laursen. 4 | Licensed under the MIT license. 5 | 6 | Flot normally produces certain elements, like axis labels and the legend, using 7 | HTML elements. This permits greater interactivity and customization, and often 8 | looks better, due to cross-browser canvas text inconsistencies and limitations. 9 | 10 | It can also be desirable to render the plot entirely in canvas, particularly 11 | if the goal is to save it as an image, or if Flot is being used in a context 12 | where the HTML DOM does not exist, as is the case within Node.js. This plugin 13 | switches out Flot's standard drawing operations for canvas-only replacements. 14 | 15 | Currently the plugin supports only axis labels, but it will eventually allow 16 | every element of the plot to be rendered directly to canvas. 17 | 18 | The plugin supports these options: 19 | 20 | { 21 | canvas: boolean 22 | } 23 | 24 | The "canvas" option controls whether full canvas drawing is enabled, making it 25 | possible to toggle on and off. This is useful when a plot uses HTML text in the 26 | browser, but needs to redraw with canvas text when exporting as an image. 27 | 28 | */(function(e){function o(t,o){var u=o.Canvas;n==null&&(r=u.prototype.getTextInfo,i=u.prototype.addText,n=u.prototype.render),u.prototype.render=function(){if(!t.getOptions().canvas)return n.call(this);var e=this.context,r=this._textCache;e.save(),e.textBaseline="middle";for(var i in r)if(s.call(r,i)){var o=r[i];for(var u in o)if(s.call(o,u)){var a=o[u],f=!0;for(var l in a)if(s.call(a,l)){var c=a[l];if(!c.active){delete a[l];continue}f&&(e.fillStyle=c.font.color,e.font=c.font.definition,f=!1);var h=c.lines;for(var p=0;p ").css("position","absolute").addClass(typeof s=="string"?s:null).appendTo(this.getTextLayer(n));s={lineHeight:h.height(),style:h.css("font-style"),variant:h.css("font-variant"),weight:h.css("font-weight"),family:h.css("font-family"),color:h.css("color")},s.size=h.css("line-height",1).height(),h.remove()}u=s.style+" "+s.variant+" "+s.weight+" "+s.size+"px "+s.family,l=f[i]={width:0,height:0,active:!1,lines:[],font:{definition:u,color:s.color}},c.save(),c.font=u;var p=(i+"").replace(/
    |\r\n|\r/g,"\n").split("\n");for(var d=0;dt&&(t=e[n]);return t+1}function i(e){var t=[];for(var n in e.categories){var r=e.categories[n];r>=e.min&&r<=e.max&&t.push([r,n])}return t.sort(function(e,t){return e[0]-t[0]}),t}function s(t,n,r){if(t[n].options.mode!="categories")return;if(!t[n].categories){var s={},u=t[n].options.categories||{};if(e.isArray(u))for(var a=0;au[1].max||yu[0].max)continue;if(f[v].err=="y")if(g>u[0].max||gu[1].max)continue;var E=!0,S=!0;b>m[1]&&(E=!1,b=m[1]),w0&&T>0){var N=T/2;t.lineWidth=N,t.strokeStyle="rgba(0,0,0,0.1)",s(t,f[v],g,y,b,w,E,S,a,N+N/2,m),t.strokeStyle="rgba(0,0,0,0.2)",s(t,f[v],g,y,b,w,E,S,a,N/2,m)}t.strokeStyle=f[v].color?f[v].color:n.color,t.lineWidth=x,s(t,f[v],g,y,b,w,E,S,a,0,m)}}}}function s(t,n,r,i,s,u,a,f,l,c,h){i+=c,s+=c,u+=c,n.err=="x"?(s>r+l?o(t,[[s,i],[Math.max(r+l,h[0]),i]]):a=!1,ui+l?o(t,[[r,Math.max(i+l,h[1])],[r,u]]):f=!1),l=n.radius!=null?n.radius:l,a&&(n.upperCap=="-"?n.err=="x"?o(t,[[s,i-l],[s,i+l]]):o(t,[[r-l,s],[r+l,s]]):e.isFunction(n.upperCap)&&(n.err=="x"?n.upperCap(t,s,i,l):n.upperCap(t,r,s,l))),f&&(n.lowerCap=="-"?n.err=="x"?o(t,[[u,i-l],[u,i+l]]):o(t,[[r-l,u],[r+l,u]]):e.isFunction(n.lowerCap)&&(n.err=="x"?n.lowerCap(t,u,i,l):n.lowerCap(t,r,u,l)))}function o(e,t){e.beginPath(),e.moveTo(t[0][0],t[0][1]);for(var n=1;n=t.length?null:t[e.fillBetween]:null}function n(e,n,r){if(n.fillBetween==null)return;var i=t(n,e.getData());if(!i)return;var s=r.pointsize,o=r.points,u=i.datapoints.pointsize,a=i.datapoints.points,f=[],l,c,h,p,d,v,m=n.lines.show,g=s>2&&r.format[2].y,y=m&&n.lines.steps,b=!0,w=0,E=0,S,x;for(;;){if(w>=o.length)break;S=f.length;if(o[w]==null){for(x=0;x=a.length){if(!m)for(x=0;xp){if(m&&w>0&&o[w-s]!=null){h=c+(o[w-s+1]-c)*(p-l)/(o[w-s]-l),f.push(p),f.push(h);for(x=2;x0&&a[E-u]!=null&&(v=d+(a[E-u+1]-d)*(l-p)/(a[E-u]-p)),w+=s}b=!1,S!==f.length&&g&&(f[S+2]=v)}if(y&&S!==f.length&&S>0&&f[S]!==null&&f[S]!==f[S-s]&&f[S+1]!==f[S-s+1]){for(x=0;xl&&(d=l,l=a,a=d),f>c&&(d=c,c=f,f=d),n.images.anchor=="center"&&(d=.5*(l-a)/(u.width-1),a-=d,l+=d,d=.5*(c-f)/(u.height-1),f-=d,c+=d);if(a==l||f==c||a>=h.max||l<=h.min||f>=p.max||c<=p.min)continue;var v=0,m=0,g=u.width,y=u.height;ah.max&&(g+=(g-v)*(h.max-l)/(l-a),l=h.max),fp.max&&(m+=(m-y)*(p.max-c)/(c-f),c=p.max),a=h.p2c(a),l=h.p2c(l),f=p.p2c(f),c=p.p2c(c),a>l&&(d=l,l=a,a=d),f>c&&(d=c,c=f,f=d),d=t.globalAlpha,t.globalAlpha*=n.images.alpha,t.drawImage(u,v,m,g-v,y-m,a+r.left,f+r.top,l-a,c-f),t.globalAlpha=d}}function r(e,t,n,r){if(!t.images.show)return;r.format=[{required:!0},{x:!0,number:!0,required:!0},{y:!0,number:!0,required:!0},{x:!0,number:!0,required:!0},{y:!0,number:!0,required:!0}]}function i(e){e.hooks.processRawData.push(r),e.hooks.drawSeries.push(n)}var t={series:{images:{show:!1,alpha:1,anchor:"corner"}}};e.plot.image={},e.plot.image.loadDataImages=function(t,n,r){var i=[],s=[],o=n.series.images.show;e.each(t,function(t,n){if(!o&&!n.images.show)return;n.data&&(n=n.data),e.each(n,function(e,t){typeof t[0]=="string"&&(i.push(t[0]),s.push(t))})}),e.plot.image.load(i,function(t){e.each(s,function(e,n){var r=n[0];t[r]&&(n[0]=t[r])}),r()})},e.plot.image.load=function(t,n){var r=t.length,i={};r==0&&n({}),e.each(t,function(t,s){var o=function(){--r,i[s]=this,r==0&&n(i)};e("").load(o).error(o).attr("src",s)})},e.plot.plugins.push({init:i,options:t,name:"image",version:"1.1"})})(jQuery); -------------------------------------------------------------------------------- /demo_project/static/js/jquery.flot.resize.js: -------------------------------------------------------------------------------- 1 | /* Flot plugin for automatically redrawing plots as the placeholder resizes. 2 | 3 | Copyright (c) 2007-2013 IOLA and Ole Laursen. 4 | Licensed under the MIT license. 5 | 6 | It works by listening for changes on the placeholder div (through the jQuery 7 | resize event plugin) - if the size changes, it will redraw the plot. 8 | 9 | There are no options. If you need to disable the plugin for some plots, you 10 | can just fix the size of their placeholders. 11 | 12 | */ 13 | 14 | /* Inline dependency: 15 | * jQuery resize event - v1.1 - 3/14/2010 16 | * http://benalman.com/projects/jquery-resize-plugin/ 17 | * 18 | * Copyright (c) 2010 "Cowboy" Ben Alman 19 | * Dual licensed under the MIT and GPL licenses. 20 | * http://benalman.com/about/license/ 21 | */ 22 | 23 | (function($,h,c){var a=$([]),e=$.resize=$.extend($.resize,{}),i,k="setTimeout",j="resize",d=j+"-special-event",b="delay",f="throttleWindow";e[b]=250;e[f]=true;$.event.special[j]={setup:function(){if(!e[f]&&this[k]){return false}var l=$(this);a=a.add(l);$.data(this,d,{w:l.width(),h:l.height()});if(a.length===1){g()}},teardown:function(){if(!e[f]&&this[k]){return false}var l=$(this);a=a.not(l);l.removeData(d);if(!a.length){clearTimeout(i)}},add:function(l){if(!e[f]&&this[k]){return false}var n;function m(s,o,p){var q=$(this),r=$.data(this,d);r.w=o!==c?o:q.width();r.h=p!==c?p:q.height();n.apply(this,arguments)}if($.isFunction(l)){n=l;return m}else{n=l.handler;l.handler=m}}};function g(){i=h[k](function(){a.each(function(){var n=$(this),m=n.width(),l=n.height(),o=$.data(this,d);if(m!==o.w||l!==o.h){n.trigger(j,[o.w=m,o.h=l])}});g()},e[b])}})(jQuery,this); 24 | 25 | (function ($) { 26 | var options = { }; // no options 27 | 28 | function init(plot) { 29 | function onResize() { 30 | var placeholder = plot.getPlaceholder(); 31 | 32 | // somebody might have hidden us and we can't plot 33 | // when we don't have the dimensions 34 | if (placeholder.width() == 0 || placeholder.height() == 0) 35 | return; 36 | 37 | plot.resize(); 38 | plot.setupGrid(); 39 | plot.draw(); 40 | } 41 | 42 | function bindEvents(plot, eventHolder) { 43 | plot.getPlaceholder().resize(onResize); 44 | } 45 | 46 | function shutdown(plot, eventHolder) { 47 | plot.getPlaceholder().unbind("resize", onResize); 48 | } 49 | 50 | plot.hooks.bindEvents.push(bindEvents); 51 | plot.hooks.shutdown.push(shutdown); 52 | } 53 | 54 | $.plot.plugins.push({ 55 | init: init, 56 | options: options, 57 | name: 'resize', 58 | version: '1.0' 59 | }); 60 | })(jQuery); 61 | -------------------------------------------------------------------------------- /demo_project/static/js/jquery.flot.resize.min.js: -------------------------------------------------------------------------------- 1 | /* Flot plugin for automatically redrawing plots as the placeholder resizes. 2 | 3 | Copyright (c) 2007-2013 IOLA and Ole Laursen. 4 | Licensed under the MIT license. 5 | 6 | It works by listening for changes on the placeholder div (through the jQuery 7 | resize event plugin) - if the size changes, it will redraw the plot. 8 | 9 | There are no options. If you need to disable the plugin for some plots, you 10 | can just fix the size of their placeholders. 11 | 12 | */ 13 | /* Inline dependency: 14 | * jQuery resize event - v1.1 - 3/14/2010 15 | * http://benalman.com/projects/jquery-resize-plugin/ 16 | * 17 | * Copyright (c) 2010 "Cowboy" Ben Alman 18 | * Dual licensed under the MIT and GPL licenses. 19 | * http://benalman.com/about/license/ 20 | */(function($,h,c){var a=$([]),e=$.resize=$.extend($.resize,{}),i,k="setTimeout",j="resize",d=j+"-special-event",b="delay",f="throttleWindow";e[b]=250;e[f]=true;$.event.special[j]={setup:function(){if(!e[f]&&this[k]){return false}var l=$(this);a=a.add(l);$.data(this,d,{w:l.width(),h:l.height()});if(a.length===1){g()}},teardown:function(){if(!e[f]&&this[k]){return false}var l=$(this);a=a.not(l);l.removeData(d);if(!a.length){clearTimeout(i)}},add:function(l){if(!e[f]&&this[k]){return false}var n;function m(s,o,p){var q=$(this),r=$.data(this,d);r.w=o!==c?o:q.width();r.h=p!==c?p:q.height();n.apply(this,arguments)}if($.isFunction(l)){n=l;return m}else{n=l.handler;l.handler=m}}};function g(){i=h[k](function(){a.each(function(){var n=$(this),m=n.width(),l=n.height(),o=$.data(this,d);if(m!==o.w||l!==o.h){n.trigger(j,[o.w=m,o.h=l])}});g()},e[b])}})(jQuery,this); 21 | (function(e){function n(e){function t(){var t=e.getPlaceholder();if(t.width()==0||t.height()==0)return;e.resize(),e.setupGrid(),e.draw()}function n(e,n){e.getPlaceholder().resize(t)}function r(e,n){e.getPlaceholder().unbind("resize",t)}e.hooks.bindEvents.push(n),e.hooks.shutdown.push(r)}var t={};e.plot.plugins.push({init:n,options:t,name:"resize",version:"1.0"})})(jQuery); -------------------------------------------------------------------------------- /demo_project/static/js/jquery.flot.stack.min.js: -------------------------------------------------------------------------------- 1 | /* Flot plugin for stacking data sets rather than overlyaing them. 2 | 3 | Copyright (c) 2007-2013 IOLA and Ole Laursen. 4 | Licensed under the MIT license. 5 | 6 | The plugin assumes the data is sorted on x (or y if stacking horizontally). 7 | For line charts, it is assumed that if a line has an undefined gap (from a 8 | null point), then the line above it should have the same gap - insert zeros 9 | instead of "null" if you want another behaviour. This also holds for the start 10 | and end of the chart. Note that stacking a mix of positive and negative values 11 | in most instances doesn't make sense (so it looks weird). 12 | 13 | Two or more series are stacked when their "stack" attribute is set to the same 14 | key (which can be any number or string or just "true"). To specify the default 15 | stack, you can set the stack option like this: 16 | 17 | series: { 18 | stack: null/false, true, or a key (number/string) 19 | } 20 | 21 | You can also specify it for a single series, like this: 22 | 23 | $.plot( $("#placeholder"), [{ 24 | data: [ ... ], 25 | stack: true 26 | }]) 27 | 28 | The stacking order is determined by the order of the data series in the array 29 | (later series end up on top of the previous). 30 | 31 | Internally, the plugin modifies the datapoints in each series, adding an 32 | offset to the y value. For line series, extra data points are inserted through 33 | interpolation. If there's a second y value, it's also adjusted (e.g for bar 34 | charts or filled areas). 35 | 36 | */(function(e){function n(e){function t(e,t){var n=null;for(var r=0;r2&&(g?r.format[2].x:r.format[2].y),b=m&&n.lines.steps,w=!0,E=g?1:0,S=g?0:1,x=0,T=0,N,C;for(;;){if(x>=o.length)break;N=f.length;if(o[x]==null){for(C=0;C=a.length){if(!m)for(C=0;Cp){if(m&&x>0&&o[x-s]!=null){h=c+(o[x-s+S]-c)*(p-l)/(o[x-s+E]-l),f.push(p),f.push(h+d);for(C=2;C0&&a[T-u]!=null&&(v=d+(a[T-u+S]-d)*(l-p)/(a[T-u+E]-p)),f[N+S]+=v,x+=s}w=!1,N!=f.length&&y&&(f[N+2]+=v)}if(b&&N!=f.length&&N>0&&f[N]!=null&&f[N]!=f[N-s]&&f[N+1]!=f[N-s+1]){for(C=0;C s = r * sqrt(pi)/2 24 | var size = radius * Math.sqrt(Math.PI) / 2; 25 | ctx.rect(x - size, y - size, size + size, size + size); 26 | }, 27 | diamond: function (ctx, x, y, radius, shadow) { 28 | // pi * r^2 = 2s^2 => s = r * sqrt(pi/2) 29 | var size = radius * Math.sqrt(Math.PI / 2); 30 | ctx.moveTo(x - size, y); 31 | ctx.lineTo(x, y - size); 32 | ctx.lineTo(x + size, y); 33 | ctx.lineTo(x, y + size); 34 | ctx.lineTo(x - size, y); 35 | }, 36 | triangle: function (ctx, x, y, radius, shadow) { 37 | // pi * r^2 = 1/2 * s^2 * sin (pi / 3) => s = r * sqrt(2 * pi / sin(pi / 3)) 38 | var size = radius * Math.sqrt(2 * Math.PI / Math.sin(Math.PI / 3)); 39 | var height = size * Math.sin(Math.PI / 3); 40 | ctx.moveTo(x - size/2, y + height/2); 41 | ctx.lineTo(x + size/2, y + height/2); 42 | if (!shadow) { 43 | ctx.lineTo(x, y - height/2); 44 | ctx.lineTo(x - size/2, y + height/2); 45 | } 46 | }, 47 | cross: function (ctx, x, y, radius, shadow) { 48 | // pi * r^2 = (2s)^2 => s = r * sqrt(pi)/2 49 | var size = radius * Math.sqrt(Math.PI) / 2; 50 | ctx.moveTo(x - size, y - size); 51 | ctx.lineTo(x + size, y + size); 52 | ctx.moveTo(x - size, y + size); 53 | ctx.lineTo(x + size, y - size); 54 | } 55 | }; 56 | 57 | var s = series.points.symbol; 58 | if (handlers[s]) 59 | series.points.symbol = handlers[s]; 60 | } 61 | 62 | function init(plot) { 63 | plot.hooks.processDatapoints.push(processRawData); 64 | } 65 | 66 | $.plot.plugins.push({ 67 | init: init, 68 | name: 'symbols', 69 | version: '1.0' 70 | }); 71 | })(jQuery); 72 | -------------------------------------------------------------------------------- /demo_project/static/js/jquery.flot.symbol.min.js: -------------------------------------------------------------------------------- 1 | /* Flot plugin that adds some extra symbols for plotting points. 2 | 3 | Copyright (c) 2007-2013 IOLA and Ole Laursen. 4 | Licensed under the MIT license. 5 | 6 | The symbols are accessed as strings through the standard symbol options: 7 | 8 | series: { 9 | points: { 10 | symbol: "square" // or "diamond", "triangle", "cross" 11 | } 12 | } 13 | 14 | */(function(e){function t(e,t,n){var r={square:function(e,t,n,r,i){var s=r*Math.sqrt(Math.PI)/2;e.rect(t-s,n-s,s+s,s+s)},diamond:function(e,t,n,r,i){var s=r*Math.sqrt(Math.PI/2);e.moveTo(t-s,n),e.lineTo(t,n-s),e.lineTo(t+s,n),e.lineTo(t,n+s),e.lineTo(t-s,n)},triangle:function(e,t,n,r,i){var s=r*Math.sqrt(2*Math.PI/Math.sin(Math.PI/3)),o=s*Math.sin(Math.PI/3);e.moveTo(t-s/2,n+o/2),e.lineTo(t+s/2,n+o/2),i||(e.lineTo(t,n-o/2),e.lineTo(t-s/2,n+o/2))},cross:function(e,t,n,r,i){var s=r*Math.sqrt(Math.PI)/2;e.moveTo(t-s,n-s),e.lineTo(t+s,n+s),e.moveTo(t-s,n+s),e.lineTo(t+s,n-s)}},i=t.points.symbol;r[i]&&(t.points.symbol=r[i])}function n(e){e.hooks.processDatapoints.push(t)}e.plot.plugins.push({init:n,name:"symbols",version:"1.0"})})(jQuery); -------------------------------------------------------------------------------- /demo_project/static/js/jquery.flot.threshold.js: -------------------------------------------------------------------------------- 1 | /* Flot plugin for thresholding data. 2 | 3 | Copyright (c) 2007-2013 IOLA and Ole Laursen. 4 | Licensed under the MIT license. 5 | 6 | The plugin supports these options: 7 | 8 | series: { 9 | threshold: { 10 | below: number 11 | color: colorspec 12 | } 13 | } 14 | 15 | It can also be applied to a single series, like this: 16 | 17 | $.plot( $("#placeholder"), [{ 18 | data: [ ... ], 19 | threshold: { ... } 20 | }]) 21 | 22 | An array can be passed for multiple thresholding, like this: 23 | 24 | threshold: [{ 25 | below: number1 26 | color: color1 27 | },{ 28 | below: number2 29 | color: color2 30 | }] 31 | 32 | These multiple threshold objects can be passed in any order since they are 33 | sorted by the processing function. 34 | 35 | The data points below "below" are drawn with the specified color. This makes 36 | it easy to mark points below 0, e.g. for budget data. 37 | 38 | Internally, the plugin works by splitting the data into two series, above and 39 | below the threshold. The extra series below the threshold will have its label 40 | cleared and the special "originSeries" attribute set to the original series. 41 | You may need to check for this in hover events. 42 | 43 | */ 44 | 45 | (function ($) { 46 | var options = { 47 | series: { threshold: null } // or { below: number, color: color spec} 48 | }; 49 | 50 | function init(plot) { 51 | function thresholdData(plot, s, datapoints, below, color) { 52 | var ps = datapoints.pointsize, i, x, y, p, prevp, 53 | thresholded = $.extend({}, s); // note: shallow copy 54 | 55 | thresholded.datapoints = { points: [], pointsize: ps, format: datapoints.format }; 56 | thresholded.label = null; 57 | thresholded.color = color; 58 | thresholded.threshold = null; 59 | thresholded.originSeries = s; 60 | thresholded.data = []; 61 | 62 | var origpoints = datapoints.points, 63 | addCrossingPoints = s.lines.show; 64 | 65 | var threspoints = []; 66 | var newpoints = []; 67 | var m; 68 | 69 | for (i = 0; i < origpoints.length; i += ps) { 70 | x = origpoints[i]; 71 | y = origpoints[i + 1]; 72 | 73 | prevp = p; 74 | if (y < below) 75 | p = threspoints; 76 | else 77 | p = newpoints; 78 | 79 | if (addCrossingPoints && prevp != p && x != null 80 | && i > 0 && origpoints[i - ps] != null) { 81 | var interx = x + (below - y) * (x - origpoints[i - ps]) / (y - origpoints[i - ps + 1]); 82 | prevp.push(interx); 83 | prevp.push(below); 84 | for (m = 2; m < ps; ++m) 85 | prevp.push(origpoints[i + m]); 86 | 87 | p.push(null); // start new segment 88 | p.push(null); 89 | for (m = 2; m < ps; ++m) 90 | p.push(origpoints[i + m]); 91 | p.push(interx); 92 | p.push(below); 93 | for (m = 2; m < ps; ++m) 94 | p.push(origpoints[i + m]); 95 | } 96 | 97 | p.push(x); 98 | p.push(y); 99 | for (m = 2; m < ps; ++m) 100 | p.push(origpoints[i + m]); 101 | } 102 | 103 | datapoints.points = newpoints; 104 | thresholded.datapoints.points = threspoints; 105 | 106 | if (thresholded.datapoints.points.length > 0) { 107 | var origIndex = $.inArray(s, plot.getData()); 108 | // Insert newly-generated series right after original one (to prevent it from becoming top-most) 109 | plot.getData().splice(origIndex + 1, 0, thresholded); 110 | } 111 | 112 | // FIXME: there are probably some edge cases left in bars 113 | } 114 | 115 | function processThresholds(plot, s, datapoints) { 116 | if (!s.threshold) 117 | return; 118 | 119 | if (s.threshold instanceof Array) { 120 | s.threshold.sort(function(a, b) { 121 | return a.below - b.below; 122 | }); 123 | 124 | $(s.threshold).each(function(i, th) { 125 | thresholdData(plot, s, datapoints, th.below, th.color); 126 | }); 127 | } 128 | else { 129 | thresholdData(plot, s, datapoints, s.threshold.below, s.threshold.color); 130 | } 131 | } 132 | 133 | plot.hooks.processDatapoints.push(processThresholds); 134 | } 135 | 136 | $.plot.plugins.push({ 137 | init: init, 138 | options: options, 139 | name: 'threshold', 140 | version: '1.2' 141 | }); 142 | })(jQuery); 143 | -------------------------------------------------------------------------------- /demo_project/static/js/jquery.flot.threshold.min.js: -------------------------------------------------------------------------------- 1 | /* Flot plugin for thresholding data. 2 | 3 | Copyright (c) 2007-2013 IOLA and Ole Laursen. 4 | Licensed under the MIT license. 5 | 6 | The plugin supports these options: 7 | 8 | series: { 9 | threshold: { 10 | below: number 11 | color: colorspec 12 | } 13 | } 14 | 15 | It can also be applied to a single series, like this: 16 | 17 | $.plot( $("#placeholder"), [{ 18 | data: [ ... ], 19 | threshold: { ... } 20 | }]) 21 | 22 | An array can be passed for multiple thresholding, like this: 23 | 24 | threshold: [{ 25 | below: number1 26 | color: color1 27 | },{ 28 | below: number2 29 | color: color2 30 | }] 31 | 32 | These multiple threshold objects can be passed in any order since they are 33 | sorted by the processing function. 34 | 35 | The data points below "below" are drawn with the specified color. This makes 36 | it easy to mark points below 0, e.g. for budget data. 37 | 38 | Internally, the plugin works by splitting the data into two series, above and 39 | below the threshold. The extra series below the threshold will have its label 40 | cleared and the special "originSeries" attribute set to the original series. 41 | You may need to check for this in hover events. 42 | 43 | */(function(e){function n(t){function n(t,n,r,i,s){var o=r.pointsize,u,a,f,l,c,h=e.extend({},n);h.datapoints={points:[],pointsize:o,format:r.format},h.label=null,h.color=s,h.threshold=null,h.originSeries=n,h.data=[];var p=r.points,d=n.lines.show,v=[],m=[],g;for(u=0;u0&&p[u-o]!=null){var y=a+(i-f)*(a-p[u-o])/(f-p[u-o+1]);c.push(y),c.push(i);for(g=2;g0){var b=e.inArray(n,t.getData());t.getData().splice(b+1,0,h)}}function r(t,r,i){if(!r.threshold)return;r.threshold instanceof Array?(r.threshold.sort(function(e,t){return e.below-t.below}),e(r.threshold).each(function(e,o){n(t,r,i,o.below,o.color)})):n(t,r,i,r.threshold.below,r.threshold.color)}t.hooks.processDatapoints.push(r)}var t={series:{threshold:null}};e.plot.plugins.push({init:n,options:t,name:"threshold",version:"1.2"})})(jQuery); -------------------------------------------------------------------------------- /demo_project/static/js/jquery.flot.time.min.js: -------------------------------------------------------------------------------- 1 | /* Pretty handling of time axes. 2 | 3 | Copyright (c) 2007-2013 IOLA and Ole Laursen. 4 | Licensed under the MIT license. 5 | 6 | Set axis.mode to "time" to enable. See the section "Time series data" in 7 | API.txt for details. 8 | 9 | */(function(e){function n(e,t){return t*Math.floor(e/t)}function r(e,t,n,r){if(typeof e.strftime=="function")return e.strftime(t);var i=function(e,t){return e=""+e,t=""+(t==null?"0":t),e.length==1?t+e:e},s=[],o=!1,u=e.getHours(),a=u<12;n==null&&(n=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]),r==null&&(r=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"]);var f;u>12?f=u-12:u==0?f=12:f=u;for(var l=0;l=u)break;var h=l[c][0],p=l[c][1];if(p=="year"){if(i.minTickSize!=null&&i.minTickSize[1]=="year")h=Math.floor(i.minTickSize[0]);else{var d=Math.pow(10,Math.floor(Math.log(e.delta/o.year)/Math.LN10)),v=e.delta/o.year/d;v<1.5?h=1:v<3?h=2:v<7.5?h=5:h=10,h*=d}h<1&&(h=1)}e.tickSize=i.tickSize||[h,p];var m=e.tickSize[0];p=e.tickSize[1];var g=m*o[p];p=="second"?r.setSeconds(n(r.getSeconds(),m)):p=="minute"?r.setMinutes(n(r.getMinutes(),m)):p=="hour"?r.setHours(n(r.getHours(),m)):p=="month"?r.setMonth(n(r.getMonth(),m)):p=="quarter"?r.setMonth(3*n(r.getMonth()/3,m)):p=="year"&&r.setFullYear(n(r.getFullYear(),m)),r.setMilliseconds(0),g>=o.minute?r.setSeconds(0):g>=o.hour?r.setMinutes(0):g>=o.day?r.setHours(0):g>=o.day*4?r.setDate(1):g>=o.month*2?r.setMonth(n(r.getMonth(),3)):g>=o.quarter*2?r.setMonth(n(r.getMonth(),6)):g>=o.year&&r.setMonth(0);var y=0,b=Number.NaN,w;do{w=b,b=r.getTime(),t.push(b);if(p=="month"||p=="quarter")if(m<1){r.setDate(1);var E=r.getTime();r.setMonth(r.getMonth()+(p=="quarter"?3:1));var S=r.getTime();r.setTime(b+y*o.hour+(S-E)*m),y=r.getHours(),r.setHours(0)}else r.setMonth(r.getMonth()+m*(p=="quarter"?3:1));else p=="year"?r.setFullYear(r.getFullYear()+m):r.setTime(b+g)}while(b 7 | 8 | Create a data source.:: 9 | 10 | from graphos.sources.model import ModelDataSource 11 | queryset = Account.objects.all() 12 | data_source = ModelDataSource(queryset, 13 | fields=['year', 'sales']) 14 | 15 | 16 | Pass the ``data_source`` to a flot Chart:: 17 | 18 | from graphos.renderers import flot 19 | chart = flot.LineChart(data_source) 20 | 21 | You can render this chart in the template by ``{{ point_chart.as_html }}``. 22 | 23 | Supported chart types 24 | -------------------------- 25 | 26 | * Line 27 | * Bar 28 | * Point 29 | -------------------------------------------------------------------------------- /docs/source/google-charts.rst: -------------------------------------------------------------------------------- 1 | Using Google chart api with graphos 2 | ========================================== 3 | 4 | Include the JS in the template:: 5 | 6 | 7 | 10 | 11 | Create a data source.:: 12 | 13 | from graphos.sources.model import ModelDataSource 14 | queryset = Account.objects.all() 15 | data_source = ModelDataSource(queryset, 16 | fields=['year', 'sales']) 17 | 18 | 19 | Pass the ``data_source`` to a `gchart`:: 20 | 21 | from graphos.renderers import gchart 22 | chart = gchart.LineChart(data_source) 23 | 24 | You can render this chart in the template by ``{{ point_chart.as_html }}``. 25 | 26 | Supported chart types 27 | -------------------------- 28 | 29 | * Area chart 30 | * Bar chart 31 | * Candlestick charts 32 | * Column chart 33 | * Line chart 34 | * Pie chart -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | .. Django Graphos documentation master file, created by 2 | sphinx-quickstart on Thu Jun 20 19:45:15 2013. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to Django Graphos's documentation! 7 | ========================================== 8 | 9 | Contents: 10 | 11 | Django-graphos is a tool to create Graphs. (doh). 12 | There are two things which Graphos gives you over a low level graph manupulation. 13 | 14 | It provides various data sources. 15 | 16 | * SimpleDataSource - Use a Python list 17 | * ModelDataSource 18 | * MongoDataSource 19 | 20 | It provides various renderers. 21 | 22 | * Flot 23 | * Google charts 24 | * YUI 25 | * Morris.js 26 | * (And more) 27 | 28 | Graphos makes it very easy to switch between different data source and renderers. 29 | 30 | Are you building your charts with Flot but would like to later switch to Gchart? In many cases, it might be as easy as switching an import statement. 31 | 32 | 33 | 34 | .. toctree:: 35 | :maxdepth: 2 36 | 37 | intro 38 | flot 39 | google-charts 40 | ajax 41 | custom-data-source 42 | custom-charts 43 | 44 | 45 | 46 | 47 | Indices and tables 48 | ================== 49 | 50 | * :ref:`genindex` 51 | * :ref:`modindex` 52 | * :ref:`search` 53 | 54 | -------------------------------------------------------------------------------- /docs/source/intro.rst: -------------------------------------------------------------------------------- 1 | Intro to Django-graphos 2 | ========================================== -------------------------------------------------------------------------------- /graphos/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/graphos/__init__.py -------------------------------------------------------------------------------- /graphos/encoders.py: -------------------------------------------------------------------------------- 1 | from django.core.serializers.json import DjangoJSONEncoder 2 | 3 | 4 | class GraphosEncoder(DjangoJSONEncoder): 5 | pass 6 | -------------------------------------------------------------------------------- /graphos/exceptions.py: -------------------------------------------------------------------------------- 1 | """ Graphos Exceptions """ 2 | 3 | 4 | class GraphosException(Exception): 5 | pass 6 | -------------------------------------------------------------------------------- /graphos/models.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/graphos/models.py -------------------------------------------------------------------------------- /graphos/renderers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/graphos/renderers/__init__.py -------------------------------------------------------------------------------- /graphos/renderers/base.py: -------------------------------------------------------------------------------- 1 | import json 2 | import sys 3 | 4 | from django.template.loader import render_to_string 5 | from ..exceptions import GraphosException 6 | from ..utils import DEFAULT_HEIGHT, DEFAULT_WIDTH, get_random_string, JSONEncoderForHTML 7 | from ..encoders import GraphosEncoder 8 | 9 | 10 | class BaseChart(object): 11 | 12 | def __init__(self, data_source, html_id=None, 13 | width=None, height=None, 14 | options=None, encoder=GraphosEncoder, 15 | *args, **kwargs): 16 | """ 17 | : param data_source: :type graphos.sources.base.BaseDataSource subclass instance. 18 | : param html_id: :type string: Id of the div where you would like chart to be rendered 19 | : param width: :type integer: Width of the chart div 20 | : param height: :type integer: Height of the chart div 21 | """ 22 | self.data_source = data_source 23 | self.html_id = html_id or get_random_string() 24 | self.height = height or DEFAULT_HEIGHT 25 | self.width = width or DEFAULT_WIDTH 26 | # options could be an object, a list, a dictionary or a nested object or probably anything. 27 | # Different renderers have different structure for options. 28 | # Its responsibility of the renderer to read self.options in correct way and to use it in get_js_template. 29 | self.options = options or {} 30 | self.header = data_source.get_header() 31 | self.encoder = encoder 32 | self.context_data = kwargs 33 | 34 | def get_data(self): 35 | return self.data_source.get_data() 36 | 37 | def get_data_json(self): 38 | return json.dumps(self.get_data(), cls=JSONEncoderForHTML) 39 | 40 | def get_options(self): 41 | options = self.options 42 | if not 'title' in options: 43 | options['title'] = "Chart" 44 | return options 45 | 46 | def get_options_json(self): 47 | return json.dumps(self.get_options(), cls=JSONEncoderForHTML) 48 | 49 | def get_template(self): 50 | return 'graphos/as_html.html' 51 | 52 | def get_html_template(self): 53 | raise GraphosException("Not Implemented") 54 | 55 | def get_js_template(self): 56 | raise GraphosException("Not Implemented") 57 | 58 | def get_html_id(self): 59 | return self.html_id 60 | 61 | def get_context_data(self): 62 | return self.context_data 63 | 64 | def as_html(self): 65 | context = { 66 | 'html': self.render_html(), 67 | 'js': self.render_js(), 68 | } 69 | return render_to_string(self.get_template(), context) 70 | 71 | def render_html(self): 72 | context = {"chart": self} 73 | return render_to_string(self.get_html_template(), context) 74 | 75 | def render_js(self): 76 | context = {"chart": self} 77 | return render_to_string(self.get_js_template(), context) 78 | 79 | def zip_list(self, *args): 80 | rv = zip(*args) 81 | if sys.version_info < (3,0): 82 | return rv 83 | return list(rv) 84 | -------------------------------------------------------------------------------- /graphos/renderers/c3js.py: -------------------------------------------------------------------------------- 1 | import json 2 | from .base import BaseChart 3 | from ..utils import JSONEncoderForHTML 4 | 5 | 6 | class BaseC3JS(BaseChart): 7 | """docstring for BaseC3JS""" 8 | def get_html_template(self): 9 | return "graphos/c3js/html.html" 10 | 11 | def get_js_template(self): 12 | return "graphos/c3js/js_base.html" 13 | 14 | def get_categories(self): 15 | return [x[0] for x in self.get_data()] 16 | 17 | def get_x_axis_title(self): 18 | return self.get_data()[0][0] 19 | 20 | def get_columns_data(self): 21 | return json.dumps(map(list, zip(*self.get_data())), cls=JSONEncoderForHTML) 22 | 23 | 24 | 25 | class LineChart(BaseC3JS): 26 | def get_chart_type(self): 27 | return "line" 28 | 29 | 30 | class BarChart(BaseC3JS): 31 | def get_chart_type(self): 32 | return "bar" 33 | 34 | 35 | class SplineChart(BaseC3JS): 36 | def get_chart_type(self): 37 | return "spline" 38 | 39 | 40 | class PieChart(BaseC3JS): 41 | def get_js_template(self): 42 | return "graphos/c3js/js_pie.html" 43 | 44 | def get_data(self): 45 | _data = super(PieChart, self).get_data() 46 | return json.dumps(_data[1:], cls=JSONEncoderForHTML) 47 | 48 | def get_chart_type(self): 49 | return "pie" 50 | 51 | 52 | class ColumnChart(BaseC3JS): 53 | def get_js_template(self): 54 | return "graphos/c3js/js_column.html" 55 | 56 | """ 57 | C3 doesn't have column type chart, so we have to render the column chart by 58 | rotating the axis in the js 59 | axis: { 60 | rotated: true 61 | } 62 | """ 63 | def get_chart_type(self): 64 | return "column" 65 | 66 | 67 | class DonutChart(BaseC3JS): 68 | def get_js_template(self): 69 | return "graphos/c3js/js_donut.html" 70 | 71 | def get_chart_type(self): 72 | return "donut" 73 | -------------------------------------------------------------------------------- /graphos/renderers/flot.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | from .base import BaseChart 4 | from ..utils import get_default_options, JSONEncoderForHTML 5 | 6 | 7 | class BaseFlotChart(BaseChart): 8 | """ LineChart """ 9 | 10 | def get_serieses(self): 11 | # Assuming self.data_source.data is: 12 | # [['Year', 'Sales', 'Expenses'], [2004, 100, 200], [2005, 300, 250]] 13 | data_only = self.get_data()[1:] 14 | # first_column = [2004, 2005] 15 | first_column = [el[0] for el in data_only] 16 | serieses = [] 17 | for i in range(1, len(self.header)): 18 | current_column = [el[i] for el in data_only] 19 | current_series = self.zip_list(first_column, current_column) 20 | serieses.append(current_series) 21 | # serieses = [[(2004, 100), (2005, 300)], [(2004, 200), (2005, 250)]] 22 | return serieses 23 | 24 | def get_series_objects(self): 25 | series_objects = [] 26 | serieses = self.get_serieses() 27 | for i in range(1, len(self.header)): 28 | series_object = {} 29 | series_object['label'] = self.header[i] 30 | series_object['data'] = serieses[i - 1] 31 | series_objects.append(series_object) 32 | # series_objects = [{'label': 'Sales', 'data': [(2004, 100), (2005, 300)]}, {'label': 'Expenses': 'data': [(2004, 100), (2005, 300)]}] 33 | return series_objects 34 | 35 | def get_series_pie_objects(self): 36 | series_objects = [] 37 | serieses = self.get_data()[1:] 38 | try: 39 | for i in serieses: 40 | series_object = {} 41 | series_object['label'] = i[0] 42 | series_object['data'] = i[1] 43 | series_objects.append(series_object) 44 | except IndexError: 45 | print("Input Data Format is [['Year', 'Sales'], [2004, 100], [2005, 300]]") 46 | # series_objects = [{'label': '2004', 'data': 100}, {'label': '2005': 'data': 300}] 47 | return json.dumps(series_objects, cls=JSONEncoderForHTML) 48 | 49 | def get_series_objects_json(self): 50 | return json.dumps(self.get_series_objects(), cls=JSONEncoderForHTML) 51 | 52 | def get_options(self): 53 | options = get_default_options() 54 | options.update(self.options) 55 | return options 56 | 57 | def get_html_template(self): 58 | return 'graphos/flot/html.html' 59 | 60 | def get_js_template(self): 61 | return 'graphos/flot/js.html' 62 | 63 | 64 | class PointChart(BaseFlotChart): 65 | 66 | def get_options(self): 67 | options = get_default_options("points") 68 | options.update(self.options) 69 | return options 70 | 71 | 72 | class LineChart(BaseFlotChart): 73 | """ LineChart """ 74 | 75 | def get_options(self): 76 | options = get_default_options("lines") 77 | options.update(self.options) 78 | return options 79 | 80 | 81 | class BarChart(BaseFlotChart): 82 | 83 | def get_options(self): 84 | options = get_default_options("bars") 85 | options.update(self.options) 86 | return options 87 | 88 | 89 | class ColumnChart(BaseFlotChart): 90 | 91 | def get_options(self): 92 | options = get_default_options("bars") 93 | options.update(self.options) 94 | options["horizontal"] = True 95 | return options 96 | 97 | 98 | class PieChart(BaseFlotChart): 99 | 100 | def get_options(self): 101 | options = get_default_options("pie") 102 | options.update(self.options) 103 | return options 104 | 105 | def get_js_template(self): 106 | return 'graphos/flot/pie_chart.html' 107 | -------------------------------------------------------------------------------- /graphos/renderers/gchart.py: -------------------------------------------------------------------------------- 1 | from .base import BaseChart 2 | 3 | 4 | class BaseGChart(BaseChart): 5 | def get_html_template(self): 6 | return "graphos/gchart/html.html" 7 | 8 | 9 | class LineChart(BaseGChart): 10 | def get_js_template(self): 11 | return "graphos/gchart/line_chart.html" 12 | 13 | 14 | class GaugeChart(BaseGChart): 15 | def get_js_template(self): 16 | return "graphos/gchart/gauge_chart.html" 17 | 18 | 19 | class ColumnChart(BaseGChart): 20 | def get_js_template(self): 21 | return "graphos/gchart/column_chart.html" 22 | 23 | 24 | class BarChart(BaseGChart): 25 | def get_js_template(self): 26 | return "graphos/gchart/bar_chart.html" 27 | 28 | def get_options(self): 29 | options = super(BarChart, self).get_options() 30 | if not 'vAxis' in options: 31 | vaxis = self.data_source.get_header()[0] 32 | options['vAxis'] = {'title': vaxis} 33 | return options 34 | 35 | 36 | class CandlestickChart(BaseGChart): 37 | def get_js_template(self): 38 | return "graphos/gchart/candlestick_chart.html" 39 | 40 | 41 | class PieChart(BaseGChart): 42 | def get_js_template(self): 43 | return "graphos/gchart/pie_chart.html" 44 | 45 | 46 | class TreeMapChart(BaseGChart): 47 | def get_js_template(self): 48 | return "graphos/gchart/treemap_chart.html" 49 | 50 | 51 | class AreaChart(BaseGChart): 52 | def get_js_template(self): 53 | return "graphos/gchart/area_chart.html" 54 | -------------------------------------------------------------------------------- /graphos/renderers/matplotlib_renderer.py: -------------------------------------------------------------------------------- 1 | #Named such to not clash with matplotlib 2 | from .base import BaseChart 3 | 4 | import matplotlib 5 | matplotlib.use('Agg') # http://stackoverflow.com/a/4706614/202168 6 | import matplotlib.pyplot as plt 7 | from matplotlib.ticker import FormatStrFormatter 8 | 9 | try: 10 | # python 2 11 | from StringIO import StringIO 12 | except ImportError: 13 | # python 3 14 | from io import BytesIO as StringIO 15 | 16 | import base64 17 | 18 | 19 | class BaseMatplotlibChart(BaseChart): 20 | 21 | def get_html_template(self): 22 | return "graphos/matplotlib_renderer/line_chart.html" 23 | 24 | def get_serieses(self): 25 | data_only = self.get_data()[1:] 26 | serieses = [] 27 | for i in range(0, len(self.header)): 28 | current_column = [float(el[i]) for el in data_only] 29 | serieses.append(current_column) 30 | return serieses 31 | 32 | def render_js(self): 33 | return "" 34 | 35 | 36 | class LineChart(BaseMatplotlibChart): 37 | 38 | def get_image(self): 39 | fig = plt.figure() 40 | ax = fig.add_subplot(111) 41 | serieses = self.get_serieses() 42 | for i in range(1, len(serieses)): 43 | ax.plot(serieses[0], serieses[i]) 44 | ax.xaxis.set_major_formatter(FormatStrFormatter('%d')) 45 | out = StringIO() 46 | plt.savefig(out) 47 | out.seek(0) 48 | return "data:image/png;base64,%s" % base64.encodestring(out.read()) 49 | 50 | 51 | class BarChart(BaseMatplotlibChart): 52 | 53 | def get_image(self): 54 | fig = plt.figure() 55 | ax = fig.add_subplot(111) 56 | serieses = self.get_serieses() 57 | for i in range(1, len(serieses)): 58 | ax.bar(serieses[0], serieses[1], 0.35) 59 | ax.xaxis.set_major_formatter(FormatStrFormatter('%d')) 60 | out = StringIO() 61 | plt.savefig(out) 62 | out.seek(0) 63 | return "data:image/png;base64,%s" % base64.encodestring(out.read()) 64 | -------------------------------------------------------------------------------- /graphos/renderers/morris.py: -------------------------------------------------------------------------------- 1 | from .base import BaseChart 2 | import json 3 | 4 | from ..utils import JSONEncoderForHTML 5 | 6 | class BaseMorrisChart(BaseChart): 7 | 8 | def get_data(self): 9 | header = self.header 10 | data = super(BaseMorrisChart, self).get_data() 11 | data_only = data[1:] 12 | rows = [] 13 | for row in data_only: 14 | rows.append(dict(zip(header, row))) 15 | return rows 16 | 17 | def get_category_key(self): 18 | return self.header[0] 19 | 20 | def get_y_keys(self): 21 | try: 22 | return json.dumps(self.options['ykeys'], cls=JSONEncoderForHTML) 23 | except KeyError: 24 | return json.dumps(self.header[1:], cls=JSONEncoderForHTML) 25 | 26 | def get_html_template(self): 27 | return "graphos/morris/html.html" 28 | 29 | def get_js_template(self): 30 | return "graphos/morris/chart.html" 31 | 32 | 33 | class LineChart(BaseMorrisChart): 34 | def chart_type(self): 35 | return "Line" 36 | 37 | 38 | class BarChart(BaseMorrisChart): 39 | def chart_type(self): 40 | return "Bar" 41 | 42 | 43 | class DonutChart(BaseMorrisChart): 44 | def get_data(self): 45 | data = super(BaseMorrisChart, self).get_data() 46 | data_only = data[1:] 47 | return [{"label": el[0], "value": el[1]} for el in data_only] 48 | 49 | def chart_type(self): 50 | return "Donut" 51 | 52 | def get_js_template(self): 53 | return "graphos/morris/donut_chart.html" 54 | 55 | 56 | class AreaChart(BaseMorrisChart): 57 | def chart_type(self): 58 | return "Area" 59 | -------------------------------------------------------------------------------- /graphos/renderers/yui.py: -------------------------------------------------------------------------------- 1 | from .base import BaseChart 2 | 3 | 4 | class BaseYuiChart(BaseChart): 5 | def get_data(self): 6 | data = super(BaseYuiChart, self).get_data() 7 | header = self.header 8 | data_only = data[1:] 9 | rows = [] 10 | for row in data_only: 11 | rows.append(dict(zip(header, row))) 12 | return rows 13 | 14 | def get_category_key(self): 15 | return self.data_source.get_header()[0] 16 | 17 | def get_html_template(self): 18 | return "graphos/yui/html.html" 19 | 20 | 21 | class LineChart(BaseYuiChart): 22 | def get_js_template(self): 23 | return "graphos/yui/line_chart.html" 24 | 25 | def get_chart_type(self): 26 | return "line" 27 | 28 | 29 | class SplineChart(BaseYuiChart): 30 | def get_js_template(self): 31 | return "graphos/yui/spline_chart.html" 32 | 33 | def get_chart_type(self): 34 | return "spline" 35 | 36 | 37 | class BarChart(BaseYuiChart): 38 | def get_js_template(self): 39 | return "graphos/yui/bar_chart.html" 40 | 41 | def get_chart_type(self): 42 | return "bar" 43 | 44 | 45 | class ColumnChart(BaseYuiChart): 46 | def get_js_template(self): 47 | return "graphos/yui/column_chart.html" 48 | 49 | def get_chart_type(self): 50 | return "column" 51 | 52 | 53 | class PieChart(BaseYuiChart): 54 | def get_js_template(self): 55 | return "graphos/yui/pie_chart.html" 56 | 57 | def get_chart_type(self): 58 | return "pie" 59 | 60 | def get_data(self): 61 | # FIXME 62 | data = self.data_source.get_data() 63 | header = self.header 64 | header_first_two_columns = header[:2] 65 | data_only = data[1:] 66 | data_only_with_first_two_columns = [each[:2] for each in data_only] 67 | rows = [] 68 | for row in data_only_with_first_two_columns: 69 | rows.append(dict(zip(header_first_two_columns, row))) 70 | return rows 71 | 72 | 73 | class AreaChart(BaseYuiChart): 74 | def get_js_template(self): 75 | return "graphos/yui/area_chart.html" 76 | 77 | def get_chart_type(self): 78 | return "area" 79 | 80 | 81 | class AreaSplineChart(BaseYuiChart): 82 | def get_js_template(self): 83 | return "graphos/yui/area_spline_chart.html" 84 | 85 | def get_chart_type(self): 86 | return "areaspline" 87 | 88 | 89 | class ComboChart(BaseYuiChart): 90 | def get_js_template(self): 91 | return "graphos/yui/combo.html" 92 | 93 | def get_chart_type(self): 94 | return "combo" 95 | 96 | 97 | class ComboSplineChart(BaseYuiChart): 98 | def get_js_template(self): 99 | return "graphos/yui/combo_spline.html" 100 | 101 | def get_chart_type(self): 102 | return "combospline" 103 | 104 | 105 | class MarkerSeriesChart(BaseYuiChart): 106 | def get_js_template(self): 107 | return "graphos/yui/marker_series.html" 108 | 109 | def get_chart_type(self): 110 | return "markerseries" -------------------------------------------------------------------------------- /graphos/sources/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/graphos/sources/__init__.py -------------------------------------------------------------------------------- /graphos/sources/base.py: -------------------------------------------------------------------------------- 1 | """Base Plot Data Handler""" 2 | 3 | from ..exceptions import GraphosException 4 | 5 | 6 | class BaseDataSource(object): 7 | def __init__(*args, **kwargs): 8 | pass 9 | 10 | def get_data(self): 11 | "Get all the data. Subclasses should override this" 12 | raise GraphosException("Not Implemented") 13 | 14 | def get_header(self): 15 | "Get the header - First row. Subclasses should override this" 16 | raise GraphosException("Not Implemented") 17 | 18 | def get_first_column(self): 19 | """ 20 | Get the first column. Generally would be the x axis. 21 | Subclasses should override this 22 | """ 23 | raise GraphosException("Not Implemented") 24 | -------------------------------------------------------------------------------- /graphos/sources/csv_file.py: -------------------------------------------------------------------------------- 1 | from .simple import SimpleDataSource 2 | 3 | import csv 4 | 5 | class CSVDataSource(SimpleDataSource): 6 | "A data source for CSV files" 7 | def __init__(self, csv_file, fields=None): 8 | """csv_file: A file like object which should be charted 9 | """ 10 | reader = csv.reader(csv_file) 11 | data =[row for row in reader] 12 | self.data = data 13 | self.fields = fields 14 | -------------------------------------------------------------------------------- /graphos/sources/model.py: -------------------------------------------------------------------------------- 1 | """ Model Plot Data Handler""" 2 | from .simple import SimpleDataSource 3 | 4 | 5 | def get_field_values(row, fields): 6 | data = [] 7 | for field in fields: 8 | value = getattr(row, field) 9 | data.append(value if not callable(value) else value()) 10 | return data 11 | 12 | 13 | class ModelDataSource(SimpleDataSource): 14 | """ 15 | Normalizes data contained in a queryset to format usable by renderers 16 | """ 17 | def __init__(self, queryset, fields=None): 18 | """ 19 | : param queryset: :type Django ORM queryset 20 | : param fields: :type list of strings 21 | Example usage: 22 | queryset = Account.objects.all() 23 | mds = ModelDataSource(queryset, fields=['year', 'sales', 'expenses']) 24 | # This assumes the following model Account: 25 | class Account(models.Model): 26 | year = models.IntegerField() 27 | sales = models.DecimalField() 28 | expenses = models.DecimalField() 29 | profit = models.DecimalField() 30 | """ 31 | self.queryset = queryset 32 | if fields: 33 | self.fields = fields 34 | else: 35 | self.fields = [el.name for el in self.queryset.model._meta.fields] 36 | self.data = self.create_data() 37 | 38 | def create_data(self): 39 | data = [self.fields] 40 | for row in self.queryset: 41 | data.append(get_field_values(row, self.fields)) 42 | return data 43 | -------------------------------------------------------------------------------- /graphos/sources/mongo.py: -------------------------------------------------------------------------------- 1 | """ Mongodb Plot Data Source """ 2 | 3 | from .simple import SimpleDataSource 4 | 5 | 6 | def get_row(doc, fields): 7 | current_row = [] 8 | for i in range(len(fields)): 9 | try: 10 | field = doc[fields[i]] 11 | except KeyError: 12 | field = "" 13 | current_row.append(field) 14 | return current_row 15 | 16 | 17 | class MongoDBDataSource(SimpleDataSource): 18 | """ MongoDBDataSource """ 19 | 20 | def __init__(self, 21 | cursor, 22 | fields, 23 | *args, 24 | **kwargs): 25 | 26 | self.cursor = cursor 27 | self.fields = fields 28 | self._doc_list = [] 29 | 30 | def get_data(self): 31 | if self._doc_list: 32 | return self._doc_list 33 | doc_list = [] 34 | doc_list.append(self.fields) 35 | for doc in self.cursor: 36 | current_row = get_row(doc, self.fields) 37 | doc_list.append(current_row) 38 | self._doc_list = doc_list 39 | return doc_list 40 | 41 | @property 42 | def data(self): 43 | return self.get_data() 44 | -------------------------------------------------------------------------------- /graphos/sources/simple.py: -------------------------------------------------------------------------------- 1 | from .base import BaseDataSource 2 | 3 | 4 | class SimpleDataSource(BaseDataSource): 5 | def __init__(self, data): 6 | """ 7 | : param data: :type list of lists 8 | Example usage: 9 | data = [ 10 | ['Year', 'Sales', 'Expenses', 'Items Sold', 'Net Profit'], 11 | ['2004', 1000, 400, 100, 600], 12 | ['2005', 1170, 460, 120, 310], 13 | ['2006', 660, 1120, 50, -460], 14 | ['2007', 1030, 540, 100, 200], 15 | ] 16 | sd = SimpleDataSource(data) 17 | """ 18 | self.data = data 19 | 20 | def get_data(self): 21 | return self.data 22 | 23 | def get_header(self): 24 | return self.data[0] 25 | 26 | def get_first_column(self): 27 | """ 28 | Get the first column. Generally would be the x axis. 29 | : return: :type list of strings 30 | Example: 31 | For the example shown in __init__, it would return the following: 32 | ['2004', '2005', '2006', '2007'] 33 | """ 34 | data_not_header = self.data[1:] 35 | return [el[0] for el in data_not_header] 36 | -------------------------------------------------------------------------------- /graphos/templates/graphos/as_html.html: -------------------------------------------------------------------------------- 1 | {{ html }} 2 | {{ js }} -------------------------------------------------------------------------------- /graphos/templates/graphos/c3js/html.html: -------------------------------------------------------------------------------- 1 |
    2 | -------------------------------------------------------------------------------- /graphos/templates/graphos/c3js/js_base.html: -------------------------------------------------------------------------------- 1 | 18 | -------------------------------------------------------------------------------- /graphos/templates/graphos/c3js/js_column.html: -------------------------------------------------------------------------------- 1 | 19 | -------------------------------------------------------------------------------- /graphos/templates/graphos/c3js/js_donut.html: -------------------------------------------------------------------------------- 1 | 15 | -------------------------------------------------------------------------------- /graphos/templates/graphos/c3js/js_pie.html: -------------------------------------------------------------------------------- 1 | 12 | -------------------------------------------------------------------------------- /graphos/templates/graphos/flot/html.html: -------------------------------------------------------------------------------- 1 |
    -------------------------------------------------------------------------------- /graphos/templates/graphos/flot/js.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /graphos/templates/graphos/flot/pie_chart.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /graphos/templates/graphos/gchart/area_chart.html: -------------------------------------------------------------------------------- 1 | {% extends "graphos/gchart/base.html" %} 2 | 3 | {% block create_chart %} 4 | var chart = new google.visualization.AreaChart(document.getElementById('{{ chart.get_html_id }}')); 5 | {% endblock %} 6 | -------------------------------------------------------------------------------- /graphos/templates/graphos/gchart/bar_chart.html: -------------------------------------------------------------------------------- 1 | {% extends "graphos/gchart/base.html" %} 2 | 3 | {% block create_chart %} 4 | var chart = new google.visualization.BarChart(document.getElementById('{{ chart.get_html_id }}')); 5 | {% endblock %} 6 | -------------------------------------------------------------------------------- /graphos/templates/graphos/gchart/base.html: -------------------------------------------------------------------------------- 1 | 2 | 21 | -------------------------------------------------------------------------------- /graphos/templates/graphos/gchart/candlestick_chart.html: -------------------------------------------------------------------------------- 1 | {% extends "graphos/gchart/base.html" %} 2 | 3 | {% block chart_specific_arraytodatatable %} 4 | var data = google.visualization.arrayToDataTable({{ chart.get_data_json|safe }}, true); 5 | {% endblock %} 6 | 7 | {% block create_chart %} 8 | var chart = new google.visualization.CandlestickChart(document.getElementById('{{ chart.get_html_id }}', true)); 9 | {% endblock %} -------------------------------------------------------------------------------- /graphos/templates/graphos/gchart/column_chart.html: -------------------------------------------------------------------------------- 1 | {% extends "graphos/gchart/base.html" %} 2 | 3 | {% block create_chart %} 4 | var chart = new google.visualization.ColumnChart(document.getElementById('{{ chart.get_html_id }}')); 5 | {% endblock %} -------------------------------------------------------------------------------- /graphos/templates/graphos/gchart/gauge_chart.html: -------------------------------------------------------------------------------- 1 | {% extends "graphos/gchart/base.html" %} 2 | 3 | {% block create_chart %} 4 | var chart = new google.visualization.Gauge(document.getElementById('{{ chart.get_html_id }}')); 5 | {% endblock %} 6 | -------------------------------------------------------------------------------- /graphos/templates/graphos/gchart/html.html: -------------------------------------------------------------------------------- 1 |
    -------------------------------------------------------------------------------- /graphos/templates/graphos/gchart/line_chart.html: -------------------------------------------------------------------------------- 1 | {% extends "graphos/gchart/base.html" %} 2 | 3 | {% block create_chart %} 4 | var chart = new google.visualization.LineChart(document.getElementById('{{ chart.get_html_id }}')); 5 | {% endblock %} -------------------------------------------------------------------------------- /graphos/templates/graphos/gchart/pie_chart.html: -------------------------------------------------------------------------------- 1 | {% extends "graphos/gchart/base.html" %} 2 | 3 | {% block create_chart %} 4 | var chart = new google.visualization.PieChart(document.getElementById('{{ chart.get_html_id }}')); 5 | {% endblock %} 6 | -------------------------------------------------------------------------------- /graphos/templates/graphos/gchart/treemap_chart.html: -------------------------------------------------------------------------------- 1 | {% extends "graphos/gchart/base.html" %} 2 | 3 | {% block create_chart %} 4 | var chart = new google.visualization.TreeMap(document.getElementById('{{ chart.get_html_id }}')); 5 | {% endblock %} 6 | -------------------------------------------------------------------------------- /graphos/templates/graphos/highcharts/html.html: -------------------------------------------------------------------------------- 1 |
    -------------------------------------------------------------------------------- /graphos/templates/graphos/highcharts/js.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /graphos/templates/graphos/highcharts/js_dual_axis.html: -------------------------------------------------------------------------------- 1 | {% load graph_tags %} 2 | 3 | 17 | -------------------------------------------------------------------------------- /graphos/templates/graphos/highcharts/js_heatmaps.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /graphos/templates/graphos/highcharts/js_highmaps.html: -------------------------------------------------------------------------------- 1 | 29 | -------------------------------------------------------------------------------- /graphos/templates/graphos/highcharts/js_highmaps_multi_series.html: -------------------------------------------------------------------------------- 1 | 20 | -------------------------------------------------------------------------------- /graphos/templates/graphos/highcharts/js_treemap.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /graphos/templates/graphos/matplotlib_renderer/line_chart.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /graphos/templates/graphos/model_template.html: -------------------------------------------------------------------------------- 1 |
    2 | 113 | -------------------------------------------------------------------------------- /graphos/templates/graphos/morris/chart.html: -------------------------------------------------------------------------------- 1 | 26 | -------------------------------------------------------------------------------- /graphos/templates/graphos/morris/donut_chart.html: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /graphos/templates/graphos/morris/html.html: -------------------------------------------------------------------------------- 1 |
    -------------------------------------------------------------------------------- /graphos/templates/graphos/redis_template.html: -------------------------------------------------------------------------------- 1 |
    2 | 113 | -------------------------------------------------------------------------------- /graphos/templates/graphos/yui/area_chart.html: -------------------------------------------------------------------------------- 1 | {% extends "graphos/yui/base.html" %} 2 | -------------------------------------------------------------------------------- /graphos/templates/graphos/yui/area_spline_chart.html: -------------------------------------------------------------------------------- 1 | {% extends "graphos/yui/base.html" %} 2 | -------------------------------------------------------------------------------- /graphos/templates/graphos/yui/bar_chart.html: -------------------------------------------------------------------------------- 1 | {% extends "graphos/yui/base.html" %} -------------------------------------------------------------------------------- /graphos/templates/graphos/yui/base.html: -------------------------------------------------------------------------------- 1 | 18 | -------------------------------------------------------------------------------- /graphos/templates/graphos/yui/column_chart.html: -------------------------------------------------------------------------------- 1 | {% extends "graphos/yui/base.html" %} -------------------------------------------------------------------------------- /graphos/templates/graphos/yui/combo.html: -------------------------------------------------------------------------------- 1 | {% extends "graphos/yui/base.html" %} 2 | -------------------------------------------------------------------------------- /graphos/templates/graphos/yui/combo_spline.html: -------------------------------------------------------------------------------- 1 | {% extends "graphos/yui/base.html" %} 2 | -------------------------------------------------------------------------------- /graphos/templates/graphos/yui/html.html: -------------------------------------------------------------------------------- 1 |
    -------------------------------------------------------------------------------- /graphos/templates/graphos/yui/line_chart.html: -------------------------------------------------------------------------------- 1 | {% extends "graphos/yui/base.html" %} -------------------------------------------------------------------------------- /graphos/templates/graphos/yui/marker_series.html: -------------------------------------------------------------------------------- 1 | {% extends "graphos/yui/base.html" %} 2 | -------------------------------------------------------------------------------- /graphos/templates/graphos/yui/pie_chart.html: -------------------------------------------------------------------------------- 1 | {% extends "graphos/yui/base.html" %} -------------------------------------------------------------------------------- /graphos/templates/graphos/yui/spline_chart.html: -------------------------------------------------------------------------------- 1 | {% extends "graphos/yui/base.html" %} 2 | -------------------------------------------------------------------------------- /graphos/templatetags/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agiliq/django-graphos/2f11e98de8a51f808e536099e830b2fc3a508a6a/graphos/templatetags/__init__.py -------------------------------------------------------------------------------- /graphos/templatetags/graph_tags.py: -------------------------------------------------------------------------------- 1 | import random 2 | from django import template 3 | 4 | register = template.Library() 5 | 6 | 7 | @register.simple_tag 8 | def random_chart_type(): 9 | chart_type = ['line', 'column', 'spline', 'scatter'] 10 | return random.choice(chart_type) 11 | -------------------------------------------------------------------------------- /graphos/test_data/accounts.csv: -------------------------------------------------------------------------------- 1 | Year,Sales,Expense 2 | 2006,1000,400 3 | 2007,1170,460 4 | 2008,660,1120 5 | 2009,1030,540 -------------------------------------------------------------------------------- /graphos/test_data/mongodb/test_zips.json: -------------------------------------------------------------------------------- 1 | {"city": "ACMAR", "loc": [-86.51557, 33.584132], "pop": 6055, "state": "AL", "_id": "35004"} 2 | {"city": "ADAMSVILLE", "loc": [-86.959727, 33.588437], "pop": 10616, "state": "AL", "_id": "35005"} 3 | {"city": "ADGER", "loc": [-87.167455, 33.434277], "pop": 3205, "state": "AL", "_id": "35006"} 4 | {"city": "KEYSTONE", "loc": [-86.812861, 33.236868], "pop": 14218, "state": "AL", "_id": "35007"} 5 | {"city": "NEW SITE", "loc": [-85.951086, 32.941445], "pop": 19942, "state": "AL", "_id": "35010"} 6 | {"city": "ALPINE", "loc": [-86.208934, 33.331165], "pop": 3062, "state": "AL", "_id": "35014"} 7 | {"city": "ARAB", "loc": [-86.489638, 34.328339], "pop": 13650, "state": "AL", "_id": "35016"} 8 | {"city": "BAILEYTON", "loc": [-86.621299, 34.268298], "pop": 1781, "state": "AL", "_id": "35019"} 9 | {"city": "BESSEMER", "loc": [-86.947547, 33.409002], "pop": 40549, "state": "AL", "_id": "35020"} 10 | {"city": "HUEYTOWN", "loc": [-86.999607, 33.414625], "pop": 39677, "state": "AL", "_id": "35023"} 11 | {"city": "BLOUNTSVILLE", "loc": [-86.568628, 34.092937], "pop": 9058, "state": "AL", "_id": "35031"} 12 | {"city": "BREMEN", "loc": [-87.004281, 33.973664], "pop": 3448, "state": "AL", "_id": "35033"} 13 | {"city": "BRENT", "loc": [-87.211387, 32.93567], "pop": 3791, "state": "AL", "_id": "35034"} 14 | {"city": "BRIERFIELD", "loc": [-86.951672, 33.042747], "pop": 1282, "state": "AL", "_id": "35035"} 15 | {"city": "CALERA", "loc": [-86.755987, 33.1098], "pop": 4675, "state": "AL", "_id": "35040"} 16 | {"city": "CENTREVILLE", "loc": [-87.11924, 32.950324], "pop": 4902, "state": "AL", "_id": "35042"} 17 | {"city": "CHELSEA", "loc": [-86.614132, 33.371582], "pop": 4781, "state": "AL", "_id": "35043"} 18 | {"city": "COOSA PINES", "loc": [-86.337622, 33.266928], "pop": 7985, "state": "AL", "_id": "35044"} 19 | {"city": "CLANTON", "loc": [-86.642472, 32.835532], "pop": 13990, "state": "AL", "_id": "35045"} 20 | {"city": "CLEVELAND", "loc": [-86.559355, 33.992106], "state": "AL", "_id": "35049"} -------------------------------------------------------------------------------- /graphos/utils.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import decimal 3 | import json 4 | import uuid 5 | import random 6 | import string 7 | 8 | from django.utils import six, timezone 9 | from django.utils.encoding import force_text 10 | from django.utils.functional import Promise 11 | from django.db.models.query import QuerySet 12 | 13 | DEFAULT_HEIGHT = 400 14 | DEFAULT_WIDTH = 800 15 | 16 | DB_HOST = ["localhost"] 17 | DB_PORT = 27017 18 | 19 | 20 | def get_random_string(): 21 | random_letter = lambda: random.choice(string.ascii_letters) 22 | random_string = "".join([random_letter() 23 | for el in range(10)]) 24 | return random_string 25 | 26 | 27 | def get_default_options(graph_type="lines"): 28 | """ default options """ 29 | options = {"series": {"%s" % graph_type: {"show": "true"}}, 30 | "legend": {"position": 'ne'}, 31 | "title": "Chart"} 32 | return options 33 | 34 | 35 | def get_db(db_name=None): 36 | """ GetDB - simple function to wrap getting a database 37 | connection from the connection pool. 38 | """ 39 | import pymongo 40 | return pymongo.Connection(host=DB_HOST, 41 | port=DB_PORT)[db_name] 42 | 43 | 44 | class JSONEncoderForHTML(json.JSONEncoder): 45 | """An encoder that produces JSON safe to embed in HTML. 46 | To embed JSON content in, say, a script tag on a web page, the 47 | characters &, < and > should be escaped. They cannot be escaped 48 | with the usual entities (e.g. &) because they are not expanded 49 | within