├── .gitignore ├── LICENSE ├── README.rst ├── dashboardmods ├── __init__.py ├── admin.py ├── models.py ├── modules.py └── templates │ └── dashboard │ └── modules │ └── memcache.html ├── doc_src ├── Makefile ├── _static │ ├── breadcrumb_background.png │ ├── default.css │ ├── documentation.png │ ├── header_sm_mid.png │ ├── scrn1.png │ ├── scrn2.png │ ├── searchfield_leftcap.png │ ├── searchfield_repeat.png │ ├── searchfield_rightcap.png │ ├── title_background.png │ ├── toc.js │ ├── triangle_closed.png │ ├── triangle_left.png │ └── triangle_open.png ├── _templates │ └── layout.html ├── conf.py ├── getting_started.rst ├── index.rst ├── installation.rst ├── make.bat └── reference │ ├── index.rst │ └── settings.rst ├── example ├── __init__.py ├── dashboard.py ├── manage.py ├── media │ └── admin_tools │ │ ├── css │ │ ├── dashboard-ie.css │ │ ├── dashboard.css │ │ ├── menu-ie.css │ │ ├── menu.css │ │ └── theming.css │ │ ├── images │ │ ├── admin-tools.png │ │ └── django.png │ │ └── js │ │ ├── jquery │ │ ├── jquery.cookie.min.js │ │ └── jquery.dashboard.js │ │ ├── json.min.js │ │ └── menu.js ├── menu.py ├── settings.py └── urls.py ├── requirements.txt └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | dev.db 3 | local_settings.py 4 | media/ugc 5 | media/ 6 | media2/ 7 | externals 8 | build/ 9 | src/ 10 | pip-log.txt 11 | media/js/*.r*.js 12 | media/css/*.r*.css 13 | *DS_Store 14 | *.egg-info 15 | externals 16 | MANIFEST 17 | dist/ 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/callowayproject/dashboardmods/966e83947ce130d9c3a4d4f3b9796258d508b716/LICENSE -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ============== 2 | Dashboard Mods 3 | ============== 4 | 5 | Dashboard Mods is a set of ``DashboardModule``\ s for 6 | `django-admin-tools `_\ . 7 | 8 | Changes 9 | ======= 10 | 11 | **0.2** Updated to support Django Admin Tools 0.4.0 12 | 13 | Installation 14 | ============ 15 | 16 | Using PIP:: 17 | 18 | pip install dashboardmods 19 | 20 | or download the app `here `_ :: 21 | 22 | python setup.py install 23 | 24 | 25 | Add **dashboardmods** to your settings **INSTALLED_APPS**:: 26 | 27 | INSTALLED_APPS = ( 28 | ... 29 | 'dashboardmods', 30 | ... 31 | ) 32 | 33 | 34 | MemcacheDashboardModule 35 | ======================= 36 | 37 | Displays a bar graph of memory usage, hit/miss ratio and uptime for each memcache server configured in Django's settings. 38 | 39 | To enable, simply add:: 40 | 41 | from dashboardmods import get_memcache_dash_modules 42 | 43 | at the top of the page and in the ``__init__`` method add:: 44 | 45 | self.children.extend(get_memcache_dash_modules()) 46 | 47 | If no memcache servers are configured, nothing happens. 48 | 49 | VarnishDashboardModule 50 | ====================== 51 | 52 | Displays a bar graph of memory usage and hit/miss ratios for each Varnish server configured in ``VARNISH_MANAGEMENT_ADDRS``\ . It uses 53 | `python-varnish `_ for communication. See its docs for more information on setup and installation of ``python-varnish``\ . 54 | 55 | To enable, simply add:: 56 | 57 | from dashboardmods import get_varnish_dash_modules 58 | 59 | at the top of the page and in the ``__init__`` method add:: 60 | 61 | self.children.extend(get_varnish_dash_modules()) 62 | 63 | If no Varnish servers are configured, nothing happens. 64 | 65 | RSSDashboardModule 66 | ================== 67 | 68 | This is a model that allows the dynamic input of RSS feeds to appear as a ``DashboardModule``\ . 69 | 70 | To enable, add ``dashboardmods`` to your ``INSTALLED_APPS`` and ``./manage.py syncdb``\ . 71 | 72 | Then add:: 73 | 74 | from dashboardmods import get_rss_dash_modules 75 | 76 | at the top of the page and in the ``__init__`` method add:: 77 | 78 | self.children.extend(get_rss_dash_modules()) 79 | 80 | If no ``RSSDashboardModule`` records are entered, nothing happens. As soon as one is entered, the ``DashboardModule`` is immediately available. 81 | -------------------------------------------------------------------------------- /dashboardmods/__init__.py: -------------------------------------------------------------------------------- 1 | __version_info__ = { 2 | 'major': 0, 3 | 'minor': 2, 4 | 'micro': 2, 5 | 'releaselevel': 'final', 6 | 'serial': 1 7 | } 8 | 9 | def get_version(): 10 | vers = ["%(major)i.%(minor)i" % __version_info__, ] 11 | 12 | if __version_info__['micro']: 13 | vers.append(".%(micro)i" % __version_info__) 14 | if __version_info__['releaselevel'] != 'final': 15 | vers.append('%(releaselevel)s%(serial)i' % __version_info__) 16 | return ''.join(vers) 17 | 18 | __version__ = get_version() 19 | 20 | try: 21 | from modules import get_memcache_dash_modules, get_rss_dash_modules, get_varnish_dash_modules 22 | except ImportError: 23 | pass 24 | -------------------------------------------------------------------------------- /dashboardmods/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from models import RSSDashboardModule 3 | 4 | admin.site.register(RSSDashboardModule) -------------------------------------------------------------------------------- /dashboardmods/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | class RSSDashboardModule(models.Model): 4 | """ 5 | Each item is an RSS feed that will become an available Dashboard module 6 | """ 7 | 8 | title = models.CharField(max_length=100) 9 | feed = models.URLField(verify_exists=False) 10 | limit = models.IntegerField('Number of items', default=5, help_text="The latest number of articles that should appear in the list") 11 | 12 | class Meta: 13 | pass 14 | 15 | def __unicode__(self): 16 | return self.feed 17 | 18 | -------------------------------------------------------------------------------- /dashboardmods/modules.py: -------------------------------------------------------------------------------- 1 | from admin_tools.dashboard.modules import DashboardModule 2 | from django.conf import settings 3 | 4 | def format_bytes(bytes): 5 | """ 6 | Format a bytes value into something more readable 7 | """ 8 | bytes = float(bytes) 9 | if bytes >= 1073741824: 10 | gigabytes = bytes / 1073741824 11 | size = '%.2fGB' % gigabytes 12 | elif bytes >= 1048576: 13 | megabytes = bytes / 1048576 14 | size = '%.2fMB' % megabytes 15 | elif bytes >= 1024: 16 | kilobytes = bytes / 1024 17 | size = '%.2fKB' % kilobytes 18 | else: 19 | size = '%.2fB' % bytes 20 | return size 21 | 22 | def format_seconds(s): 23 | """ 24 | Format a seconds value into a human-readable form 25 | """ 26 | years, s = divmod(s, 31556952) 27 | min, s = divmod(s, 60) 28 | h, min = divmod(min, 60) 29 | d, h = divmod(h, 24) 30 | return '%sy, %sd, %sh, %sm, %ss' % (years, d, h, min, s) 31 | 32 | 33 | def format_graph(label, count, total, percent): 34 | """ 35 | Creates an
  • element that becomes a percentage bar graph. Meant to be 36 | included within a
      element. 37 | """ 38 | template = """
    • %(label)s%(percent)s%%(%(percent)s%%)
    • """ 39 | 40 | return template % {'label': label, 'count': count, 'total': total, 'percent': percent} 41 | 42 | 43 | class MemcachedDashboardModule(DashboardModule): 44 | """ 45 | Show some basic statistics for a memcache server 46 | """ 47 | def __init__(self, server, stats, *args, **kwargs): 48 | super(MemcachedDashboardModule, self).__init__(*args, **kwargs) 49 | 50 | self.title = "Memcached Stats (%s v%s)" % (server.split(':')[0], stats['version']) 51 | 52 | bytes_used = format_bytes(int(stats['bytes'])) 53 | bytes_available = format_bytes(int(stats['limit_maxbytes'])) 54 | storage_pct = int((float(stats['bytes'])/float(stats['limit_maxbytes']))*100) 55 | 56 | misses = int(stats['get_misses']) 57 | total_requests = int(stats['cmd_get']) 58 | if total_requests: 59 | miss_pct = int((float(misses)/total_requests)*100) 60 | else: 61 | miss_pct = 0 62 | 63 | uptime = format_seconds(int(stats['uptime'])) 64 | 65 | storage = { 66 | 'label': 'Memory Usage', 67 | 'count': bytes_used, 68 | 'total': bytes_available, 69 | 'percent': storage_pct, 70 | } 71 | miss_ratio = { 72 | 'label': 'Cache Misses', 73 | 'count': misses, 74 | 'total': total_requests, 75 | 'percent': miss_pct, 76 | } 77 | code = ['
        '] 78 | code.append(format_graph(**storage)) 79 | code.append(format_graph(**miss_ratio)) 80 | code.append('
      ') 81 | self.children.append("".join(code)) 82 | self.children.append('
    • Uptime: %s
    • ' % uptime) 83 | self.template = "dashboard/modules/memcache.html" 84 | 85 | 86 | class VarnishDashboardModule(DashboardModule): 87 | """ 88 | Shows some basic stats of a varnish server 89 | """ 90 | def __init__(self, server, stats, *args, **kwargs): 91 | super(VarnishDashboardModule, self).__init__(*args, **kwargs) 92 | 93 | self.title = "Varnish Stats (%s)" % server.split(":")[0] 94 | 95 | misses = stats.get('cache_misses', 0) 96 | total_requests = stats.get('cache_hits', 0) + misses 97 | miss_pct = int((float(misses)/total_requests)*100) if total_requests else 0 98 | 99 | if 'bytes_allocated' in stats: 100 | mem_used_key = 'bytes_allocated' 101 | mem_free_key = 'bytes_free' 102 | elif 'sma_bytes_allocated' in stats: 103 | mem_used_key = 'sma_bytes_allocated' 104 | mem_free_key = 'sma_bytes_free' 105 | elif 'sms_bytes_allocated' in stats: 106 | mem_used_key = 'sms_bytes_allocated' 107 | mem_free_key = 'sms_bytes_free' 108 | else: 109 | mem_used_key = None 110 | 111 | if mem_used_key is not None: 112 | bytes_used = format_bytes(stats[mem_used_key]) 113 | bytes_available = format_bytes(stats[mem_free_key]) 114 | storage_pct = int((float(stats[mem_used_key])/stats[mem_free_key])*100) 115 | else: 116 | bytes_used = 0 117 | bytes_available = 0 118 | storage_pct = 0 119 | 120 | storage = { 121 | 'label': 'Memory Usage', 122 | 'count': bytes_used, 123 | 'total': bytes_available, 124 | 'percent': storage_pct, 125 | } 126 | miss_ratio = { 127 | 'label': 'Cache Misses', 128 | 'count': misses, 129 | 'total': total_requests, 130 | 'percent': miss_pct, 131 | } 132 | code = ['
        '] 133 | code.append(format_graph(**storage)) 134 | code.append(format_graph(**miss_ratio)) 135 | code.append('
      ') 136 | self.children.append("".join(code)) 137 | self.template = "dashboard/modules/memcache.html" 138 | 139 | 140 | def get_memcache_dash_modules(): 141 | """ 142 | Based on the settings in Django, attempt to create a MemcacheDashboardModule 143 | for every memcache server. 144 | 145 | Returns a list of modules, or an empty list. 146 | 147 | In the __init__ method of your custom dashboard add: 148 | 149 | self.children.extend(get_memcache_dash_modules()) 150 | 151 | Note it says extend not append. 152 | """ 153 | from django.core.cache import cache 154 | try: 155 | import memcache 156 | if not isinstance(cache._cache, memcache.Client): 157 | return [] 158 | 159 | cache_stats = cache._cache.get_stats() 160 | server_modules = [] 161 | for server, stats in cache_stats: 162 | server_modules.append(MemcachedDashboardModule(server, stats)) 163 | return server_modules 164 | except (ImportError, AttributeError), e: 165 | return [] 166 | 167 | def get_varnish_dash_modules(): 168 | """ 169 | Using python-varnish and the Django settings, attempt to create a 170 | VarnishDashboardModule for every varnish server. 171 | 172 | Returns a list of modules, or an empty list. 173 | 174 | In the __init__ method of your custom dashboard add: 175 | 176 | self.children.extend(get_varnish_dash_modules()) 177 | 178 | Note it says extend not append. 179 | """ 180 | from varnish import VarnishManager 181 | from django.conf import settings 182 | server_modules = [] 183 | 184 | for server in getattr(settings,'VARNISH_MANAGEMENT_ADDRS', ()): 185 | try: 186 | manager = VarnishManager((server,)) 187 | stats = manager.run('stats')[0][0] 188 | server_modules.append(VarnishDashboardModule(server, stats)) 189 | except Exception, e: 190 | if settings.DEBUG: 191 | raise 192 | else: 193 | continue 194 | return server_modules 195 | 196 | def get_rss_dash_modules(): 197 | """ 198 | Convert all RSSDashboarModule objects into FeedDashboardModules. 199 | 200 | Returns a list of modules, or an empty list. 201 | 202 | In the __init__ method of your custom dashboard add: 203 | 204 | self.children.extend(get_rss_dash_modules()) 205 | 206 | Note it says extend not append. 207 | """ 208 | from models import RSSDashboardModule 209 | from admin_tools.dashboard.modules import Feed 210 | modules = [] 211 | for feed in RSSDashboardModule.objects.all(): 212 | modules.append(Feed(title=feed.title, feed_url=feed.feed, limit=feed.limit)) 213 | return modules 214 | -------------------------------------------------------------------------------- /dashboardmods/templates/dashboard/modules/memcache.html: -------------------------------------------------------------------------------- 1 | {% extends "admin_tools/dashboard/module.html" %} 2 | {% block module_content %} 3 | 41 | 42 |
        43 | {% spaceless %} 44 | {% for child in module.children %} 45 | {{child|safe}} 46 | {% endfor %} 47 | {% endspaceless %} 48 |
      49 | {% endblock %} 50 | -------------------------------------------------------------------------------- /doc_src/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | DESTDIR = .. 10 | 11 | # Internal variables. 12 | PAPEROPT_a4 = -D latex_paper_size=a4 13 | PAPEROPT_letter = -D latex_paper_size=letter 14 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 15 | 16 | .PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest 17 | 18 | help: 19 | @echo "Please use \`make ' where is one of" 20 | @echo " html to make standalone HTML files" 21 | @echo " dirhtml to make HTML files named index.html in directories" 22 | @echo " pickle to make pickle files" 23 | @echo " json to make JSON files" 24 | @echo " htmlhelp to make HTML files and a HTML help project" 25 | @echo " qthelp to make HTML files and a qthelp project" 26 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 27 | @echo " changes to make an overview of all changed/added/deprecated items" 28 | @echo " linkcheck to check all external links for integrity" 29 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 30 | 31 | clean: 32 | -rm -rf $(BUILDDIR)/* 33 | 34 | html: 35 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(DESTDIR)/docs 36 | @echo 37 | @echo "Build finished. The HTML pages are in $(DESTDIR)/docs." 38 | 39 | dirhtml: 40 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 41 | @echo 42 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 43 | 44 | pickle: 45 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 46 | @echo 47 | @echo "Build finished; now you can process the pickle files." 48 | 49 | json: 50 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 51 | @echo 52 | @echo "Build finished; now you can process the JSON files." 53 | 54 | htmlhelp: 55 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 56 | @echo 57 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 58 | ".hhp project file in $(BUILDDIR)/htmlhelp." 59 | 60 | qthelp: 61 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 62 | @echo 63 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 64 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 65 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/app.qhcp" 66 | @echo "To view the help file:" 67 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/app.qhc" 68 | 69 | latex: 70 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 71 | @echo 72 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 73 | @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ 74 | "run these through (pdf)latex." 75 | 76 | changes: 77 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 78 | @echo 79 | @echo "The overview file is in $(BUILDDIR)/changes." 80 | 81 | linkcheck: 82 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 83 | @echo 84 | @echo "Link check complete; look for any errors in the above output " \ 85 | "or in $(BUILDDIR)/linkcheck/output.txt." 86 | 87 | doctest: 88 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 89 | @echo "Testing of doctests in the sources finished, look at the " \ 90 | "results in $(BUILDDIR)/doctest/output.txt." 91 | -------------------------------------------------------------------------------- /doc_src/_static/breadcrumb_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/callowayproject/dashboardmods/966e83947ce130d9c3a4d4f3b9796258d508b716/doc_src/_static/breadcrumb_background.png -------------------------------------------------------------------------------- /doc_src/_static/default.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Sphinx stylesheet -- basic theme 3 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4 | */ 5 | h3 { 6 | color:#000000; 7 | font-size: 17px; 8 | margin-bottom:0.5em; 9 | margin-top:2em; 10 | } 11 | /* -- main layout ----------------------------------------------------------- */ 12 | 13 | div.clearer { 14 | clear: both; 15 | } 16 | 17 | /* -- header ---------------------------------------------------------------- */ 18 | 19 | #header #title { 20 | background:#29334F url(title_background.png) repeat-x scroll 0 0; 21 | border-bottom:1px solid #B6B6B6; 22 | height:25px; 23 | overflow:hidden; 24 | } 25 | #headerButtons { 26 | position: absolute; 27 | list-style: none outside; 28 | top: 26px; 29 | left: 0px; 30 | right: 0px; 31 | margin: 0px; 32 | padding: 0px; 33 | border-top: 1px solid #2B334F; 34 | border-bottom: 1px solid #EDEDED; 35 | height: 20px; 36 | font-size: 8pt; 37 | overflow: hidden; 38 | background-color: #D8D8D8; 39 | } 40 | 41 | #headerButtons li { 42 | background-repeat:no-repeat; 43 | display:inline; 44 | margin-top:0; 45 | padding:0; 46 | } 47 | 48 | .headerButton { 49 | display: inline; 50 | height:20px; 51 | } 52 | 53 | .headerButton a { 54 | text-decoration: none; 55 | float: right; 56 | height: 20px; 57 | padding: 4px 15px; 58 | border-left: 1px solid #ACACAC; 59 | font-family:'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; 60 | color: black; 61 | } 62 | .headerButton a:hover { 63 | color: white; 64 | background-color: #787878; 65 | 66 | } 67 | 68 | li#toc_button { 69 | text-align:left; 70 | } 71 | 72 | li#toc_button .headerButton a { 73 | width:198px; 74 | padding-top: 4px; 75 | font-family:'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; 76 | color: black; 77 | float: left; 78 | padding-left:15px; 79 | border-right:1px solid #ACACAC; 80 | background:transparent url(triangle_open.png) no-repeat scroll 4px 6px; 81 | } 82 | 83 | li#toc_button .headerButton a:hover { 84 | background-color: #787878; 85 | color: white; 86 | } 87 | 88 | li#page_buttons { 89 | position:absolute; 90 | right:0; 91 | } 92 | 93 | #breadcrumbs { 94 | color: black; 95 | background-image:url(breadcrumb_background.png); 96 | border-top:1px solid #2B334F; 97 | bottom:0; 98 | font-size:10px; 99 | height:15px; 100 | left:0; 101 | overflow:hidden; 102 | padding:3px 10px 0; 103 | position:absolute; 104 | right:0; 105 | white-space:nowrap; 106 | z-index:901; 107 | } 108 | #breadcrumbs a { 109 | color: black; 110 | text-decoration: none; 111 | } 112 | #breadcrumbs a:hover { 113 | text-decoration: underline; 114 | } 115 | #breadcrumbs img { 116 | padding-left: 3px; 117 | } 118 | /* -- sidebar --------------------------------------------------------------- */ 119 | #sphinxsidebar { 120 | position: absolute; 121 | top: 84px; 122 | bottom: 19px; 123 | left: 0px; 124 | width: 229px; 125 | background-color: #E4EBF7; 126 | border-right: 1px solid #ACACAC; 127 | border-top: 1px solid #2B334F; 128 | overflow-x: hidden; 129 | overflow-y: auto; 130 | padding: 0px 0px 0px 0px; 131 | font-size:11px; 132 | } 133 | 134 | div.sphinxsidebarwrapper { 135 | padding: 10px 5px 0 10px; 136 | } 137 | 138 | #sphinxsidebar li { 139 | margin: 0px; 140 | padding: 0px; 141 | font-weight: normal; 142 | margin: 0px 0px 7px 0px; 143 | overflow: hidden; 144 | text-overflow: ellipsis; 145 | font-size: 11px; 146 | } 147 | 148 | #sphinxsidebar ul { 149 | list-style: none; 150 | margin: 0px 0px 0px 0px; 151 | padding: 0px 5px 0px 5px; 152 | } 153 | 154 | #sphinxsidebar ul ul, 155 | #sphinxsidebar ul.want-points { 156 | list-style: square; 157 | } 158 | 159 | #sphinxsidebar ul ul { 160 | margin-top: 0; 161 | margin-bottom: 0; 162 | } 163 | 164 | #sphinxsidebar form { 165 | margin-top: 10px; 166 | } 167 | 168 | #sphinxsidebar input { 169 | border: 1px solid #787878; 170 | font-family: sans-serif; 171 | font-size: 1em; 172 | } 173 | 174 | img { 175 | border: 0; 176 | } 177 | 178 | #sphinxsidebar li.toctree-l1 a { 179 | font-weight: bold; 180 | color: #000; 181 | text-decoration: none; 182 | } 183 | 184 | #sphinxsidebar li.toctree-l2 a { 185 | font-weight: bold; 186 | color: #4f4f4f; 187 | text-decoration: none; 188 | } 189 | 190 | /* -- search page ----------------------------------------------------------- */ 191 | 192 | ul.search { 193 | margin: 10px 0 0 20px; 194 | padding: 0; 195 | } 196 | 197 | ul.search li { 198 | padding: 5px 0 5px 20px; 199 | background-image: url(file.png); 200 | background-repeat: no-repeat; 201 | background-position: 0 7px; 202 | } 203 | 204 | ul.search li a { 205 | font-weight: bold; 206 | } 207 | 208 | ul.search li div.context { 209 | color: #888; 210 | margin: 2px 0 0 30px; 211 | text-align: left; 212 | } 213 | 214 | ul.keywordmatches li.goodmatch a { 215 | font-weight: bold; 216 | } 217 | #sphinxsidebar input.prettysearch {border:none;} 218 | input.searchbutton { 219 | float: right; 220 | } 221 | .search-wrapper {width: 100%; height: 25px;} 222 | .search-wrapper input.prettysearch { border: none; width:200px; height: 16px; background: url(searchfield_repeat.png) center top repeat-x; border: 0px; margin: 0; padding: 3px 0 0 0; font: 11px "Lucida Grande", "Lucida Sans Unicode", Arial, sans-serif; } 223 | .search-wrapper input.prettysearch { width: 184px; margin-left: 20px; *margin-top:-1px; *margin-right:-2px; *margin-left:10px; } 224 | .search-wrapper .search-left { display: block; position: absolute; width: 20px; height: 19px; background: url(searchfield_leftcap.png) left top no-repeat; } 225 | .search-wrapper .search-right { display: block; position: relative; left: 204px; top: -19px; width: 10px; height: 19px; background: url(searchfield_rightcap.png) right top no-repeat; } 226 | 227 | /* -- index page ------------------------------------------------------------ */ 228 | 229 | table.contentstable { 230 | width: 90%; 231 | } 232 | 233 | table.contentstable p.biglink { 234 | line-height: 150%; 235 | } 236 | 237 | a.biglink { 238 | font-size: 1.3em; 239 | } 240 | 241 | span.linkdescr { 242 | font-style: italic; 243 | padding-top: 5px; 244 | font-size: 90%; 245 | } 246 | 247 | /* -- general index --------------------------------------------------------- */ 248 | 249 | table.indextable td { 250 | text-align: left; 251 | vertical-align: top; 252 | } 253 | 254 | table.indextable dl, table.indextable dd { 255 | margin-top: 0; 256 | margin-bottom: 0; 257 | } 258 | 259 | table.indextable tr.pcap { 260 | height: 10px; 261 | } 262 | 263 | table.indextable tr.cap { 264 | margin-top: 10px; 265 | background-color: #f2f2f2; 266 | } 267 | 268 | img.toggler { 269 | margin-right: 3px; 270 | margin-top: 3px; 271 | cursor: pointer; 272 | } 273 | 274 | /* -- general body styles --------------------------------------------------- */ 275 | .document { 276 | border-top:1px solid #2B334F; 277 | overflow:auto; 278 | padding-left:2em; 279 | padding-right:2em; 280 | position:absolute; 281 | z-index:1; 282 | top:84px; 283 | bottom:19px; 284 | right:0; 285 | left:230px; 286 | } 287 | 288 | a.headerlink { 289 | visibility: hidden; 290 | } 291 | 292 | h1:hover > a.headerlink, 293 | h2:hover > a.headerlink, 294 | h3:hover > a.headerlink, 295 | h4:hover > a.headerlink, 296 | h5:hover > a.headerlink, 297 | h6:hover > a.headerlink, 298 | dt:hover > a.headerlink { 299 | visibility: visible; 300 | } 301 | 302 | div.body p.caption { 303 | text-align: inherit; 304 | } 305 | 306 | div.body td { 307 | text-align: left; 308 | } 309 | 310 | .field-list ul { 311 | padding-left: 1em; 312 | } 313 | 314 | .first { 315 | margin-top: 0 !important; 316 | } 317 | 318 | p.rubric { 319 | margin-top: 30px; 320 | font-weight: bold; 321 | } 322 | 323 | /* -- sidebars -------------------------------------------------------------- */ 324 | 325 | /*div.sidebar { 326 | margin: 0 0 0.5em 1em; 327 | border: 1px solid #ddb; 328 | padding: 7px 7px 0 7px; 329 | background-color: #ffe; 330 | width: 40%; 331 | float: right; 332 | } 333 | 334 | p.sidebar-title { 335 | font-weight: bold; 336 | } 337 | */ 338 | /* -- topics ---------------------------------------------------------------- */ 339 | 340 | div.topic { 341 | border: 1px solid #ccc; 342 | padding: 7px 7px 0 7px; 343 | margin: 10px 0 10px 0; 344 | } 345 | 346 | p.topic-title { 347 | font-size: 1.1em; 348 | font-weight: bold; 349 | margin-top: 10px; 350 | } 351 | 352 | /* -- admonitions ----------------------------------------------------------- */ 353 | .admonition { 354 | border: 1px solid #a1a5a9; 355 | background-color: #f7f7f7; 356 | margin: 20px; 357 | padding: 0px 8px 7px 9px; 358 | text-align: left; 359 | } 360 | .warning { 361 | background-color:#E8E8E8; 362 | border:1px solid #111111; 363 | margin:30px; 364 | } 365 | .admonition p { 366 | font: 12px 'Lucida Grande', Geneva, Helvetica, Arial, sans-serif; 367 | margin-top: 7px; 368 | margin-bottom: 0px; 369 | } 370 | 371 | div.admonition dt { 372 | font-weight: bold; 373 | } 374 | 375 | div.admonition dl { 376 | margin-bottom: 0; 377 | } 378 | 379 | p.admonition-title { 380 | margin: 0px 10px 5px 0px; 381 | font-weight: bold; 382 | padding-top: 3px; 383 | } 384 | 385 | div.body p.centered { 386 | text-align: center; 387 | margin-top: 25px; 388 | } 389 | 390 | /* -- tables ---------------------------------------------------------------- */ 391 | 392 | table.docutils { 393 | border-collapse: collapse; 394 | border-top: 1px solid #919699; 395 | border-left: 1px solid #919699; 396 | border-right: 1px solid #919699; 397 | font-size:12px; 398 | padding:8px; 399 | text-align:left; 400 | vertical-align:top; 401 | } 402 | 403 | table.docutils td, table.docutils th { 404 | padding: 8px; 405 | font-size: 12px; 406 | text-align: left; 407 | vertical-align: top; 408 | border-bottom: 1px solid #919699; 409 | } 410 | 411 | table.docutils th { 412 | font-weight: bold; 413 | } 414 | /* This alternates colors in up to six table rows (light blue for odd, white for even)*/ 415 | .docutils tr { 416 | background: #F0F5F9; 417 | } 418 | 419 | .docutils tr + tr { 420 | background: #FFFFFF; 421 | } 422 | 423 | .docutils tr + tr + tr { 424 | background: #F0F5F9; 425 | } 426 | 427 | .docutils tr + tr + tr + tr { 428 | background: #FFFFFF; 429 | } 430 | 431 | .docutils tr + tr + tr +tr + tr { 432 | background: #F0F5F9; 433 | } 434 | 435 | .docutils tr + tr + tr + tr + tr + tr { 436 | background: #FFFFFF; 437 | } 438 | 439 | .docutils tr + tr + tr + tr + tr + tr + tr { 440 | background: #F0F5F9; 441 | } 442 | 443 | table.footnote td, table.footnote th { 444 | border: 0 !important; 445 | } 446 | 447 | th { 448 | text-align: left; 449 | padding-right: 5px; 450 | } 451 | 452 | /* -- other body styles ----------------------------------------------------- */ 453 | 454 | dl { 455 | margin-bottom: 15px; 456 | } 457 | 458 | dd p { 459 | margin-top: 0px; 460 | font-size: 12px; 461 | } 462 | 463 | dd ul, dd table { 464 | margin-bottom: 10px; 465 | } 466 | 467 | dd { 468 | margin-top: 3px; 469 | margin-bottom: 10px; 470 | margin-left: 30px; 471 | font-size: 12px; 472 | } 473 | 474 | dt:target, .highlight { 475 | background-color: #fbe54e; 476 | } 477 | 478 | dl.glossary dt { 479 | font-weight: bold; 480 | font-size: 0.8em; 481 | } 482 | 483 | dl.glossary dd { 484 | font-size:12px; 485 | } 486 | .field-list ul { 487 | vertical-align: top; 488 | margin: 0; 489 | padding-bottom: 0; 490 | list-style: none inside; 491 | } 492 | 493 | .field-list ul li { 494 | margin-top: 0; 495 | } 496 | 497 | .field-list p { 498 | margin: 0; 499 | } 500 | 501 | .refcount { 502 | color: #060; 503 | } 504 | 505 | .optional { 506 | font-size: 1.3em; 507 | } 508 | 509 | .versionmodified { 510 | font-style: italic; 511 | } 512 | 513 | .system-message { 514 | background-color: #fda; 515 | padding: 5px; 516 | border: 3px solid red; 517 | } 518 | 519 | .footnote:target { 520 | background-color: #ffa 521 | } 522 | 523 | /* -- code displays --------------------------------------------------------- */ 524 | 525 | pre { 526 | overflow: auto; 527 | background-color:#F1F5F9; 528 | border:1px solid #C9D1D7; 529 | border-spacing:0; 530 | font-family:"Bitstream Vera Sans Mono",Monaco,"Lucida Console",Courier,Consolas,monospace; 531 | font-size:11px; 532 | padding: 10px; 533 | } 534 | 535 | td.linenos pre { 536 | padding: 5px 0px; 537 | border: 0; 538 | background-color: transparent; 539 | color: #aaa; 540 | } 541 | 542 | table.highlighttable { 543 | margin-left: 0.5em; 544 | } 545 | 546 | table.highlighttable td { 547 | padding: 0 0.5em 0 0.5em; 548 | } 549 | 550 | tt { 551 | font-family:"Bitstream Vera Sans Mono",Monaco,"Lucida Console",Courier,Consolas,monospace; 552 | 553 | } 554 | 555 | tt.descname { 556 | background-color: transparent; 557 | font-weight: bold; 558 | font-size: 1em; 559 | } 560 | 561 | tt.descclassname { 562 | background-color: transparent; 563 | } 564 | 565 | tt.xref, a tt { 566 | background-color: transparent; 567 | font-weight: bold; 568 | } 569 | 570 | h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { 571 | background-color: transparent; 572 | } 573 | 574 | /* -- math display ---------------------------------------------------------- */ 575 | 576 | img.math { 577 | vertical-align: middle; 578 | } 579 | 580 | div.body div.math p { 581 | text-align: center; 582 | } 583 | 584 | span.eqno { 585 | float: right; 586 | } 587 | 588 | /* -- printout stylesheet --------------------------------------------------- */ 589 | 590 | @media print { 591 | div.document, 592 | div.documentwrapper, 593 | div.bodywrapper { 594 | margin: 0; 595 | width: 100%; 596 | } 597 | 598 | div.sphinxsidebar, 599 | div.related, 600 | div.footer, 601 | #top-link { 602 | display: none; 603 | } 604 | } 605 | 606 | body { 607 | font-family:'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; 608 | } 609 | 610 | dl.class dt { 611 | padding: 3px; 612 | /* border-top: 2px solid #999;*/ 613 | } 614 | 615 | em.property { 616 | font-style: normal; 617 | } 618 | 619 | dl.class dd p { 620 | margin-top: 6px; 621 | } 622 | 623 | dl.class dd dl.exception dt { 624 | padding: 3px; 625 | background-color: #FFD6D6; 626 | border-top: none; 627 | } 628 | 629 | dl.class dd dl.method dt { 630 | padding: 3px; 631 | background-color: #e9e9e9; 632 | border-top: none; 633 | 634 | } 635 | 636 | dl.function dt { 637 | padding: 3px; 638 | border-top: 2px solid #999; 639 | } 640 | 641 | ul { 642 | list-style-image:none; 643 | list-style-position:outside; 644 | list-style-type:square; 645 | margin:0 0 0 30px; 646 | padding:0 0 12px 6px; 647 | } 648 | #docstitle { 649 | height: 36px; 650 | background-image: url(header_sm_mid.png); 651 | left: 0; 652 | top: 0; 653 | position: absolute; 654 | width: 100%; 655 | } 656 | #docstitle p { 657 | padding:7px 0 0 45px; 658 | margin: 0; 659 | color: white; 660 | text-shadow:0 1px 0 #787878; 661 | background: transparent url(documentation.png) no-repeat scroll 10px 3px; 662 | height: 36px; 663 | font-size: 15px; 664 | } 665 | #header { 666 | height:45px; 667 | left:0; 668 | position:absolute; 669 | right:0; 670 | top:36px; 671 | z-index:900; 672 | } 673 | 674 | #header h1 { 675 | font-size:10pt; 676 | margin:0; 677 | padding:5px 0 0 10px; 678 | text-shadow:0 1px 0 #D5D5D5; 679 | white-space:nowrap; 680 | } 681 | 682 | h1 { 683 | -x-system-font:none; 684 | color:#000000; 685 | font-family:'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; 686 | font-size:30px; 687 | font-size-adjust:none; 688 | font-stretch:normal; 689 | font-style:normal; 690 | font-variant:normal; 691 | font-weight:bold; 692 | line-height:normal; 693 | margin-bottom:25px; 694 | margin-top:1em; 695 | } 696 | 697 | .footer { 698 | border-top:1px solid #DDDDDD; 699 | clear:both; 700 | padding-top:9px; 701 | width:100%; 702 | font-size:10px; 703 | } 704 | 705 | p { 706 | -x-system-font:none; 707 | font-family:'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; 708 | font-size:12px; 709 | font-size-adjust:none; 710 | font-stretch:normal; 711 | font-style:normal; 712 | font-variant:normal; 713 | font-weight:normal; 714 | line-height:normal; 715 | margin-bottom:10px; 716 | margin-top:0; 717 | } 718 | 719 | h2 { 720 | border-bottom:1px solid #919699; 721 | color:#000000; 722 | font-size:24px; 723 | margin-top:2.5em; 724 | padding-bottom:2px; 725 | } 726 | 727 | a:link:hover { 728 | color:#093D92; 729 | text-decoration:underline; 730 | } 731 | 732 | a:link { 733 | color:#093D92; 734 | text-decoration:none; 735 | } 736 | 737 | 738 | ol { 739 | list-style-position:outside; 740 | list-style-type:decimal; 741 | margin:0 0 0 30px; 742 | padding:0 0 12px 6px; 743 | } 744 | li { 745 | margin-top:7px; 746 | font-family:'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; 747 | font-size:12px; 748 | font-size-adjust:none; 749 | font-stretch:normal; 750 | font-style:normal; 751 | font-variant:normal; 752 | font-weight:normal; 753 | line-height:normal; 754 | } 755 | li > p { 756 | display:inline; 757 | } 758 | li p { 759 | margin-top:8px; 760 | } -------------------------------------------------------------------------------- /doc_src/_static/documentation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/callowayproject/dashboardmods/966e83947ce130d9c3a4d4f3b9796258d508b716/doc_src/_static/documentation.png -------------------------------------------------------------------------------- /doc_src/_static/header_sm_mid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/callowayproject/dashboardmods/966e83947ce130d9c3a4d4f3b9796258d508b716/doc_src/_static/header_sm_mid.png -------------------------------------------------------------------------------- /doc_src/_static/scrn1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/callowayproject/dashboardmods/966e83947ce130d9c3a4d4f3b9796258d508b716/doc_src/_static/scrn1.png -------------------------------------------------------------------------------- /doc_src/_static/scrn2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/callowayproject/dashboardmods/966e83947ce130d9c3a4d4f3b9796258d508b716/doc_src/_static/scrn2.png -------------------------------------------------------------------------------- /doc_src/_static/searchfield_leftcap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/callowayproject/dashboardmods/966e83947ce130d9c3a4d4f3b9796258d508b716/doc_src/_static/searchfield_leftcap.png -------------------------------------------------------------------------------- /doc_src/_static/searchfield_repeat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/callowayproject/dashboardmods/966e83947ce130d9c3a4d4f3b9796258d508b716/doc_src/_static/searchfield_repeat.png -------------------------------------------------------------------------------- /doc_src/_static/searchfield_rightcap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/callowayproject/dashboardmods/966e83947ce130d9c3a4d4f3b9796258d508b716/doc_src/_static/searchfield_rightcap.png -------------------------------------------------------------------------------- /doc_src/_static/title_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/callowayproject/dashboardmods/966e83947ce130d9c3a4d4f3b9796258d508b716/doc_src/_static/title_background.png -------------------------------------------------------------------------------- /doc_src/_static/toc.js: -------------------------------------------------------------------------------- 1 | var TOC = { 2 | load: function () { 3 | $('#toc_button').click(TOC.toggle); 4 | }, 5 | 6 | toggle: function () { 7 | if ($('#sphinxsidebar').toggle().is(':hidden')) { 8 | $('div.document').css('left', "0px"); 9 | $('toc_button').removeClass("open"); 10 | } else { 11 | $('div.document').css('left', "230px"); 12 | $('#toc_button').addClass("open"); 13 | } 14 | return $('#sphinxsidebar'); 15 | } 16 | }; 17 | 18 | $(document).ready(function () { 19 | TOC.load(); 20 | }); -------------------------------------------------------------------------------- /doc_src/_static/triangle_closed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/callowayproject/dashboardmods/966e83947ce130d9c3a4d4f3b9796258d508b716/doc_src/_static/triangle_closed.png -------------------------------------------------------------------------------- /doc_src/_static/triangle_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/callowayproject/dashboardmods/966e83947ce130d9c3a4d4f3b9796258d508b716/doc_src/_static/triangle_left.png -------------------------------------------------------------------------------- /doc_src/_static/triangle_open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/callowayproject/dashboardmods/966e83947ce130d9c3a4d4f3b9796258d508b716/doc_src/_static/triangle_open.png -------------------------------------------------------------------------------- /doc_src/_templates/layout.html: -------------------------------------------------------------------------------- 1 | {% extends "basic/layout.html" %} 2 | {%- block doctype -%} 3 | 5 | {%- endblock %} 6 | {%- set reldelim1 = reldelim1 is not defined and ' »' or reldelim1 %} 7 | {%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %} 8 | {%- block linktags %} 9 | {%- if hasdoc('about') %} 10 | 11 | {%- endif %} 12 | {%- if hasdoc('genindex') %} 13 | 14 | {%- endif %} 15 | {%- if hasdoc('search') %} 16 | 17 | {%- endif %} 18 | {%- if hasdoc('copyright') %} 19 | 20 | {%- endif %} 21 | 22 | {%- if parents %} 23 | 24 | {%- endif %} 25 | {%- if next %} 26 | 27 | {%- endif %} 28 | {%- if prev %} 29 | 30 | {%- endif %} 31 | {%- endblock %} 32 | {%- block extrahead %} {% endblock %} 33 | {%- block header %}{% endblock %} 34 | {%- block relbar1 %} 35 |
      36 |

      {{docstitle}}

      37 |
      38 | 49 | {% endblock %} 50 | 51 | {%- block sidebar1 %} 52 | {%- if not embedded %}{% if not theme_nosidebar|tobool %} 53 |
      54 |
      55 | {%- block sidebarlogo %} 56 | {%- if logo %} 57 | 60 | {%- endif %} 61 | {%- endblock %} 62 | {%- block sidebartoc %} 63 | 64 | {{ toctree() }} 65 | {%- endblock %} 66 | {%- block sidebarrel %} 67 | {%- endblock %} 68 | {%- block sidebarsourcelink %} 69 | {%- if show_source and has_source and sourcename %} 70 |

      {{ _('This Page') }}

      71 | 75 | {%- endif %} 76 | {%- endblock %} 77 | {%- if customsidebar %} 78 | {% include customsidebar %} 79 | {%- endif %} 80 | {%- block sidebarsearch %} 81 | {%- if pagename != "search" %} 82 | 98 | 99 | {%- endif %} 100 | {%- endblock %} 101 |
      102 |
      103 | {%- endif %}{% endif %} 104 | 105 | {% endblock %} 106 | {%- block document %} 107 |
      108 | {%- if not embedded %}{% if not theme_nosidebar|tobool %} 109 |
      110 | {%- endif %}{% endif %} 111 |
      112 | {% block body %} {% endblock %} 113 |
      114 | {%- if not embedded %}{% if not theme_nosidebar|tobool %} 115 |
      116 | {%- endif %}{% endif %} 117 |
      118 | 132 | {%- endblock %} 133 | {%- block sidebar2 %}{% endblock %} 134 | {%- block relbar2 %}{% endblock %} 135 | {%- block footer %} 136 | 143 | 144 | {%- endblock %} 145 | -------------------------------------------------------------------------------- /doc_src/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # app documentation build configuration file, created by 4 | # sphinx-quickstart on Wed Oct 21 13:18:22 2009. 5 | # 6 | # This file is execfile()d with the current directory set to its containing dir. 7 | # 8 | # Note that not all possible configuration values are present in this 9 | # autogenerated file. 10 | # 11 | # All configuration values have a default; values that are commented out 12 | # serve to show the default. 13 | 14 | import sys, os 15 | 16 | # If extensions (or modules to document with autodoc) are in another directory, 17 | # add these directories to sys.path here. If the directory is relative to the 18 | # documentation root, use os.path.abspath to make it absolute, like shown here. 19 | sys.path.append(os.path.abspath('..')) 20 | os.environ['DJANGO_SETTINGS_MODULE'] = 'example.settings' 21 | 22 | # -- General configuration ----------------------------------------------------- 23 | 24 | # Add any Sphinx extension module names here, as strings. They can be extensions 25 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 26 | extensions = ['sphinx.ext.autodoc'] 27 | 28 | # Add any paths that contain templates here, relative to this directory. 29 | templates_path = ['_templates'] 30 | 31 | # The suffix of source filenames. 32 | source_suffix = '.rst' 33 | 34 | # The encoding of source files. 35 | #source_encoding = 'utf-8' 36 | 37 | # The master toctree document. 38 | master_doc = 'index' 39 | 40 | # General information about the project. 41 | project = u'dashboardmods' 42 | copyright = u'2009, me' 43 | 44 | # The version info for the project you're documenting, acts as replacement for 45 | # |version| and |release|, also used in various other places throughout the 46 | # built documents. 47 | # 48 | # The short X.Y version. 49 | version = '0.1' 50 | # The full version, including alpha/beta/rc tags. 51 | release = '0.1' 52 | 53 | # The language for content autogenerated by Sphinx. Refer to documentation 54 | # for a list of supported languages. 55 | #language = None 56 | 57 | # There are two options for replacing |today|: either, you set today to some 58 | # non-false value, then it is used: 59 | #today = '' 60 | # Else, today_fmt is used as the format for a strftime call. 61 | #today_fmt = '%B %d, %Y' 62 | 63 | # List of documents that shouldn't be included in the build. 64 | #unused_docs = [] 65 | 66 | # List of directories, relative to source directory, that shouldn't be searched 67 | # for source files. 68 | exclude_trees = ['_build'] 69 | 70 | # The reST default role (used for this markup: `text`) to use for all documents. 71 | #default_role = None 72 | 73 | # If true, '()' will be appended to :func: etc. cross-reference text. 74 | #add_function_parentheses = True 75 | 76 | # If true, the current module name will be prepended to all description 77 | # unit titles (such as .. function::). 78 | #add_module_names = True 79 | 80 | # If true, sectionauthor and moduleauthor directives will be shown in the 81 | # output. They are ignored by default. 82 | #show_authors = False 83 | 84 | # The name of the Pygments (syntax highlighting) style to use. 85 | pygments_style = 'sphinx' 86 | 87 | # A list of ignored prefixes for module index sorting. 88 | #modindex_common_prefix = [] 89 | 90 | 91 | # -- Options for HTML output --------------------------------------------------- 92 | 93 | # The theme to use for HTML and HTML Help pages. Major themes that come with 94 | # Sphinx are currently 'default' and 'sphinxdoc'. 95 | html_theme = 'default' 96 | 97 | # Theme options are theme-specific and customize the look and feel of a theme 98 | # further. For a list of options available for each theme, see the 99 | # documentation. 100 | #html_theme_options = {} 101 | 102 | # Add any paths that contain custom themes here, relative to this directory. 103 | #html_theme_path = [] 104 | 105 | # The name for this set of Sphinx documents. If None, it defaults to 106 | # " v documentation". 107 | #html_title = None 108 | 109 | # A shorter title for the navigation bar. Default is the same as html_title. 110 | #html_short_title = None 111 | 112 | # The name of an image file (relative to this directory) to place at the top 113 | # of the sidebar. 114 | #html_logo = None 115 | 116 | # The name of an image file (within the static path) to use as favicon of the 117 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 118 | # pixels large. 119 | #html_favicon = None 120 | 121 | # Add any paths that contain custom static files (such as style sheets) here, 122 | # relative to this directory. They are copied after the builtin static files, 123 | # so a file named "default.css" will overwrite the builtin "default.css". 124 | html_static_path = ['_static'] 125 | 126 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 127 | # using the given strftime format. 128 | #html_last_updated_fmt = '%b %d, %Y' 129 | 130 | # If true, SmartyPants will be used to convert quotes and dashes to 131 | # typographically correct entities. 132 | #html_use_smartypants = True 133 | 134 | # Custom sidebar templates, maps document names to template names. 135 | #html_sidebars = {} 136 | 137 | # Additional templates that should be rendered to pages, maps page names to 138 | # template names. 139 | #html_additional_pages = {} 140 | 141 | # If false, no module index is generated. 142 | #html_use_modindex = True 143 | 144 | # If false, no index is generated. 145 | #html_use_index = True 146 | 147 | # If true, the index is split into individual pages for each letter. 148 | #html_split_index = False 149 | 150 | # If true, links to the reST sources are added to the pages. 151 | html_show_sourcelink = False 152 | 153 | # If true, an OpenSearch description file will be output, and all pages will 154 | # contain a tag referring to it. The value of this option must be the 155 | # base URL from which the finished HTML is served. 156 | #html_use_opensearch = '' 157 | 158 | # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). 159 | #html_file_suffix = '' 160 | 161 | # Output file base name for HTML help builder. 162 | htmlhelp_basename = 'dashboardmodsdoc' 163 | 164 | 165 | # -- Options for LaTeX output -------------------------------------------------- 166 | 167 | # The paper size ('letter' or 'a4'). 168 | #latex_paper_size = 'letter' 169 | 170 | # The font size ('10pt', '11pt' or '12pt'). 171 | #latex_font_size = '10pt' 172 | 173 | # Grouping the document tree into LaTeX files. List of tuples 174 | # (source start file, target name, title, author, documentclass [howto/manual]). 175 | latex_documents = [ 176 | ('index', 'app.tex', u'dashboardmods Documentation', 177 | u'me', 'manual'), 178 | ] 179 | 180 | # The name of an image file (relative to this directory) to place at the top of 181 | # the title page. 182 | #latex_logo = None 183 | 184 | # For "manual" documents, if this is true, then toplevel headings are parts, 185 | # not chapters. 186 | #latex_use_parts = False 187 | 188 | # Additional stuff for the LaTeX preamble. 189 | #latex_preamble = '' 190 | 191 | # Documents to append as an appendix to all manuals. 192 | #latex_appendices = [] 193 | 194 | # If false, no module index is generated. 195 | #latex_use_modindex = True 196 | -------------------------------------------------------------------------------- /doc_src/getting_started.rst: -------------------------------------------------------------------------------- 1 | 2 | Getting Started 3 | =============== 4 | -------------------------------------------------------------------------------- /doc_src/index.rst: -------------------------------------------------------------------------------- 1 | .. app documentation master file, created by 2 | sphinx-quickstart on Wed Oct 21 13:18:22 2009. 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 app's documentation! 7 | =============================== 8 | 9 | Contents: 10 | 11 | .. toctree:: 12 | :maxdepth: 2 13 | :glob: 14 | 15 | 16 | Indices and tables 17 | ================== 18 | 19 | * :ref:`genindex` 20 | * :ref:`modindex` 21 | * :ref:`search` 22 | 23 | -------------------------------------------------------------------------------- /doc_src/installation.rst: -------------------------------------------------------------------------------- 1 | 2 | Installation 3 | ============ 4 | 5 | 6 | 7 | Dependencies 8 | ************ 9 | -------------------------------------------------------------------------------- /doc_src/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM Command file for Sphinx documentation 4 | 5 | set SPHINXBUILD=sphinx-build 6 | set BUILDDIR=_build 7 | set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . 8 | if NOT "%PAPER%" == "" ( 9 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% 10 | ) 11 | 12 | if "%1" == "" goto help 13 | 14 | if "%1" == "help" ( 15 | :help 16 | echo.Please use `make ^` where ^ is one of 17 | echo. html to make standalone HTML files 18 | echo. dirhtml to make HTML files named index.html in directories 19 | echo. pickle to make pickle files 20 | echo. json to make JSON files 21 | echo. htmlhelp to make HTML files and a HTML help project 22 | echo. qthelp to make HTML files and a qthelp project 23 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter 24 | echo. changes to make an overview over all changed/added/deprecated items 25 | echo. linkcheck to check all external links for integrity 26 | echo. doctest to run all doctests embedded in the documentation if enabled 27 | goto end 28 | ) 29 | 30 | if "%1" == "clean" ( 31 | for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i 32 | del /q /s %BUILDDIR%\* 33 | goto end 34 | ) 35 | 36 | if "%1" == "html" ( 37 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html 38 | echo. 39 | echo.Build finished. The HTML pages are in %BUILDDIR%/html. 40 | goto end 41 | ) 42 | 43 | if "%1" == "dirhtml" ( 44 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml 45 | echo. 46 | echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. 47 | goto end 48 | ) 49 | 50 | if "%1" == "pickle" ( 51 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle 52 | echo. 53 | echo.Build finished; now you can process the pickle files. 54 | goto end 55 | ) 56 | 57 | if "%1" == "json" ( 58 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json 59 | echo. 60 | echo.Build finished; now you can process the JSON files. 61 | goto end 62 | ) 63 | 64 | if "%1" == "htmlhelp" ( 65 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp 66 | echo. 67 | echo.Build finished; now you can run HTML Help Workshop with the ^ 68 | .hhp project file in %BUILDDIR%/htmlhelp. 69 | goto end 70 | ) 71 | 72 | if "%1" == "qthelp" ( 73 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp 74 | echo. 75 | echo.Build finished; now you can run "qcollectiongenerator" with the ^ 76 | .qhcp project file in %BUILDDIR%/qthelp, like this: 77 | echo.^> qcollectiongenerator %BUILDDIR%\qthelp\app.qhcp 78 | echo.To view the help file: 79 | echo.^> assistant -collectionFile %BUILDDIR%\qthelp\app.ghc 80 | goto end 81 | ) 82 | 83 | if "%1" == "latex" ( 84 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 85 | echo. 86 | echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. 87 | goto end 88 | ) 89 | 90 | if "%1" == "changes" ( 91 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes 92 | echo. 93 | echo.The overview file is in %BUILDDIR%/changes. 94 | goto end 95 | ) 96 | 97 | if "%1" == "linkcheck" ( 98 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck 99 | echo. 100 | echo.Link check complete; look for any errors in the above output ^ 101 | or in %BUILDDIR%/linkcheck/output.txt. 102 | goto end 103 | ) 104 | 105 | if "%1" == "doctest" ( 106 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest 107 | echo. 108 | echo.Testing of doctests in the sources finished, look at the ^ 109 | results in %BUILDDIR%/doctest/output.txt. 110 | goto end 111 | ) 112 | 113 | :end 114 | -------------------------------------------------------------------------------- /doc_src/reference/index.rst: -------------------------------------------------------------------------------- 1 | .. The reference section is for low-level documentation for programmers. 2 | There should be a file for each class 3 | Include Docstring and parameter expectations for each class 4 | 5 | Reference 6 | ========= 7 | 8 | .. toctree:: 9 | :maxdepth: 2 10 | :glob: 11 | 12 | settings -------------------------------------------------------------------------------- /doc_src/reference/settings.rst: -------------------------------------------------------------------------------- 1 | 2 | Settings 3 | ======== 4 | -------------------------------------------------------------------------------- /example/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/callowayproject/dashboardmods/966e83947ce130d9c3a4d4f3b9796258d508b716/example/__init__.py -------------------------------------------------------------------------------- /example/dashboard.py: -------------------------------------------------------------------------------- 1 | from django.utils.translation import ugettext_lazy as _ 2 | from django.core.urlresolvers import reverse 3 | from admin_tools.dashboard import Dashboard 4 | from admin_tools.dashboard import modules 5 | from dashboardmods import get_memcache_dash_modules, get_rss_dash_modules, get_varnish_dash_modules 6 | 7 | 8 | class CustomIndexDashboard(Dashboard): 9 | """ 10 | Custom index dashboard for twtv3. 11 | """ 12 | def __init__(self, **kwargs): 13 | Dashboard.__init__(self, **kwargs) 14 | 15 | # append a link list module for "quick links" 16 | self.children.append(modules.LinkList( 17 | title=_('Quick links'), 18 | layout='inline', 19 | draggable=False, 20 | deletable=False, 21 | collapsible=False, 22 | children=[ 23 | { 24 | 'title': _('Return to site'), 25 | 'url': '/', 26 | }, 27 | { 28 | 'title': _('Change password'), 29 | 'url': reverse('admin:password_change'), 30 | }, 31 | { 32 | 'title': _('Log out'), 33 | 'url': reverse('admin:logout') 34 | }, 35 | ] 36 | )) 37 | 38 | # append an app list module for "Applications" 39 | self.children.append(modules.AppList( 40 | title=_('Applications'), 41 | exclude_list=('django.contrib',), 42 | )) 43 | 44 | # append an app list module for "Administration" 45 | self.children.append(modules.AppList( 46 | title=_('Administration'), 47 | include_list=('django.contrib',), 48 | )) 49 | 50 | # # append a recent actions module 51 | # self.children.append(RecentActionsDashboardModule( 52 | # title=_('Recent Actions'), 53 | # limit=5 54 | # )) 55 | # 56 | # # append a feed module 57 | # self.children.append(FeedDashboardModule( 58 | # title=_('Latest Web Development Activities'), 59 | # feed_url='http://www.pivotaltracker.com/user_activities/de98454d195bc113ba489ff01ae2673a', 60 | # limit=5 61 | # )) 62 | 63 | self.children.extend(get_memcache_dash_modules()) 64 | self.children.extend(get_varnish_dash_modules()) 65 | self.children.extend(get_rss_dash_modules()) 66 | 67 | def init_with_context(self, context): 68 | """ 69 | Use this method if you need to access the request context. 70 | """ 71 | pass 72 | -------------------------------------------------------------------------------- /example/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from django.core.management import execute_manager 3 | try: 4 | import settings # Assumed to be in the same directory. 5 | except ImportError: 6 | import sys 7 | sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__) 8 | sys.exit(1) 9 | 10 | if __name__ == "__main__": 11 | execute_manager(settings) 12 | -------------------------------------------------------------------------------- /example/media/admin_tools/css/dashboard-ie.css: -------------------------------------------------------------------------------- 1 | /* todo: ie6 doesn't want the dashboard to take full width... */ 2 | 3 | html, body { 4 | _overflow: auto; 5 | _width: 100%; 6 | } 7 | 8 | #content { 9 | *min-width: 98%; 10 | } 11 | 12 | .dashboard-module h2 a.toggle-icon, 13 | .dashboard-module h2 a.close-icon { 14 | margin-top: -16px; 15 | } 16 | 17 | .dashboard-module ul li ul { 18 | margin-top: -25px; 19 | } 20 | 21 | .dashboard-module h3 { 22 | clear: both; 23 | } 24 | 25 | .dashboard-column { 26 | padding: 20px; 27 | } 28 | -------------------------------------------------------------------------------- /example/media/admin_tools/css/dashboard.css: -------------------------------------------------------------------------------- 1 | /* Utilities {{{ */ 2 | 3 | .float-right { 4 | float: right; 5 | } 6 | 7 | /* }}} */ 8 | /* Dashboard general styles {{{ */ 9 | 10 | .warning { 11 | color: red; 12 | background: transparent url(../images/admin-tools.png) 0 -412px no-repeat; 13 | padding-left: 25px; 14 | } 15 | 16 | .dashboard #content { 17 | display: block; 18 | width: auto; !important; 19 | } 20 | 21 | .dashboard-container { 22 | clear: both; 23 | } 24 | 25 | h1.dashboard-title { 26 | float: left; 27 | } 28 | 29 | #dashboard-panel { 30 | margin: 0 10px 0 0; 31 | float: right; 32 | } 33 | 34 | #dashboard-panel h3 a { 35 | padding: 5px; 36 | min-width: 100px; 37 | display: block; 38 | text-align: center; 39 | border: 1px solid #e5e5e5; 40 | -moz-border-radius: 6px; 41 | -webkit-border-radius: 6px; 42 | } 43 | 44 | #dashboard-panel ul { 45 | display: none; 46 | position: absolute; 47 | top: auto; 48 | right: 25px; 49 | margin-top: -1px; 50 | } 51 | 52 | #dashboard-panel ul li { 53 | padding: 5px; 54 | border: 1px solid #e5e5e5; 55 | background-color: white; 56 | } 57 | 58 | #dashboard-panel ul li a { 59 | display: block; 60 | } 61 | 62 | #dashboard-panel:hover ul { 63 | display: block; 64 | } 65 | 66 | .dashboard ul { 67 | margin: 0; 68 | padding: 0; 69 | list-style: none; 70 | } 71 | 72 | .dashboard ul li { 73 | list-style: none; 74 | } 75 | 76 | .dashboard-column { 77 | width: 49.9%; 78 | float: left; 79 | min-height: 200px; 80 | } 81 | 82 | .dashboard-module { 83 | margin: 10px 10px 5px 10px; 84 | padding: 1px; 85 | border: 1px solid #e5e5e5; 86 | -moz-border-radius: 6px; 87 | -webkit-border-radius: 6px; 88 | } 89 | 90 | .dashboard-placeholder { 91 | border: 2px dashed #cbe0ff; 92 | background-color: #fafafa; 93 | margin: 10px 10px 5px 10px; 94 | } 95 | 96 | .dashboard-module h2 { 97 | margin: 0; 98 | padding: 7px 5px 8px 8px; 99 | text-align: left; 100 | font-weight: normal; 101 | background: url(../images/admin-tools.png) repeat-x 0 -245px; 102 | height: 20px; 103 | color: #555; 104 | } 105 | 106 | .dashboard-module.draggable h2 { 107 | cursor: move; 108 | } 109 | 110 | .dashboard-module h2 a.toggle-icon, 111 | .dashboard-module h2 a.close-icon { 112 | text-indent: -9999px; 113 | display: block; 114 | float: right; 115 | height: 20px; 116 | width: 17px; 117 | margin: 0 0 0 5px; 118 | cursor: pointer; 119 | background-image: url(../images/admin-tools.png); 120 | background-repeat: no-repeat; 121 | } 122 | 123 | .dashboard-module h2 a.toggle-icon { 124 | background-position: 0 -45px; 125 | } 126 | 127 | .dashboard-module h2 a.toggle-icon:hover { 128 | background-position: 0 -65px; 129 | } 130 | 131 | .dashboard-module h2 a.toggle-icon.collapsed { 132 | background-position: 0 -85px; 133 | } 134 | 135 | .dashboard-module h2 a.toggle-icon.collapsed:hover { 136 | background-position: 0 -105px; 137 | } 138 | 139 | .dashboard-module h2 a.close-icon { 140 | background-position: 0 -125px; 141 | } 142 | 143 | .dashboard-module h2 a.close-icon:hover { 144 | background-position: 0 -145px; 145 | } 146 | 147 | .fixed h2 span.toggle-icon, 148 | .fixed h2 span.close-icon { 149 | display: none; 150 | } 151 | 152 | .dashboard-module h3 { 153 | padding: 5px 10px; 154 | margin: 0; 155 | background: transparent url(../images/admin-tools.png) repeat-x 0 -325px; 156 | text-indent: 12px; 157 | height: 22px; 158 | } 159 | 160 | .dashboard-module h3 a { 161 | color: #808080; 162 | font-size: 13px; 163 | font-weight: 600; 164 | } 165 | 166 | .dashboard-module-content { 167 | border-top: 1px solid #ececec; 168 | } 169 | 170 | .dashboard-module-content a { 171 | color: #5B80B2; 172 | } 173 | 174 | .dashboard-module-content p { 175 | margin: 10px; 176 | } 177 | 178 | .dashboard-module ul li { 179 | vertical-align: top; 180 | padding: 5px 8px; 181 | line-height: 20px; 182 | } 183 | 184 | .dashboard-module ul li.odd { 185 | background: #f5f5f5; 186 | } 187 | 188 | .dashboard-module ul li.even { 189 | background: #ffffff; 190 | } 191 | 192 | .dashboard-module ul li a.external-link { 193 | background-image: url(../images/admin-tools.png); 194 | background-repeat: no-repeat; 195 | background-position: -5px -168px; 196 | padding-left: 15px; 197 | } 198 | 199 | .dashboard-module ul li ul { 200 | float: right; 201 | } 202 | 203 | .dashboard-module ul li ul li { 204 | display: block; 205 | float: left; 206 | border: 0; 207 | padding: 0 5px; 208 | vertical-align: top; 209 | height: auto; 210 | line-height: auto; 211 | } 212 | 213 | .dashboard-module ul li:hover { 214 | background: #fffff4; 215 | } 216 | 217 | /* }}} */ 218 | /* link list specific styles {{{ */ 219 | 220 | 221 | .dashboard-module ul.inline { 222 | display: block; 223 | height: auto; 224 | padding: 15px; 225 | text-align: center; 226 | } 227 | 228 | .dashboard-module ul.inline li { 229 | display: inline; 230 | margin: 10px auto; 231 | } 232 | 233 | .dashboard-module ul.inline li.odd, 234 | .dashboard-module ul.inline li.even { 235 | background: none; 236 | } 237 | 238 | /* }}} */ 239 | /* Dashboard groups {{{ */ 240 | 241 | .group { 242 | border: 0; 243 | margin: 0; 244 | padding: 0; 245 | } 246 | 247 | .group ul { 248 | background: none; 249 | background-color: #fafafa; 250 | border-width: 0 0 1px 0; 251 | border-color: #d3d3d3; 252 | -moz-border-radius: 0; 253 | -webkit-border-radius: 0; 254 | border-radius: 0; 255 | } 256 | 257 | .group ul li.group-tabs-link { 258 | margin-top: 7px; 259 | } 260 | 261 | .group ul li.group-tabs-link a:focus, 262 | .group ul li.group-tabs-link a:active { 263 | border: none; 264 | outline: none; 265 | } 266 | 267 | .group .dashboard-module { 268 | padding: 5px; 269 | margin: 0; 270 | } 271 | 272 | .group-accordion .group-accordion-header { 273 | display: block; 274 | clear: both; 275 | border: none; 276 | -moz-border-radius: 0; 277 | -webkit-border-radius: 0; 278 | border-radius: 0; 279 | border-bottom: 1px solid #d3d3d3; 280 | margin: 0; 281 | background: none; 282 | background-color: #f6f6f6; 283 | } 284 | 285 | .group-accordion .group-accordion-header.ui-state-default { 286 | background-color: #f0f0f0; 287 | } 288 | 289 | .group-accordion .dashboard-module { 290 | border: 0; 291 | } 292 | 293 | 294 | /* }}} */ 295 | -------------------------------------------------------------------------------- /example/media/admin_tools/css/menu-ie.css: -------------------------------------------------------------------------------- 1 | #header #navigation-menu li { 2 | height: 35px; 3 | margin: 0; 4 | } 5 | 6 | #header #navigation-menu li a { 7 | white-space: nowrap; 8 | } 9 | 10 | #header #navigation-menu li span { 11 | display: none; 12 | } 13 | 14 | #header #navigation-menu li ul li { 15 | _width: 220px; 16 | } 17 | 18 | #header #navigation-menu li ul li a { 19 | height: 20px; 20 | } 21 | -------------------------------------------------------------------------------- /example/media/admin_tools/css/menu.css: -------------------------------------------------------------------------------- 1 | /* menu styles */ 2 | 3 | #header { 4 | overflow: visible; 5 | } 6 | 7 | #header #branding h1 { 8 | margin: 0; 9 | padding: 5px 10px; 10 | height: 31px; 11 | } 12 | 13 | #header ul { 14 | list-style: none; 15 | margin: 0; 16 | padding: 0; 17 | z-index: 9999; 18 | } 19 | 20 | #header ul li { 21 | position: relative; 22 | list-style: none; 23 | } 24 | 25 | #header ul li a { 26 | white-space: nowrap; 27 | } 28 | 29 | #header #navigation-menu { 30 | height: 35px; 31 | z-index: 9999; 32 | background: transparent url(../images/admin-tools.png) repeat-x 0 -205px; 33 | } 34 | 35 | #header #bookmark-button { 36 | cursor: pointer; 37 | position: absolute; 38 | top: auto; 39 | right: 15px; 40 | height: 25px; 41 | width: 24px; 42 | margin-top: 4px; 43 | border: none; 44 | text-indent: -5000px; 45 | overflow: hidden; 46 | background: transparent url(../images/admin-tools.png) no-repeat 0 -425px; 47 | } 48 | 49 | #header #bookmark-button.bookmarked { 50 | background-position: 0 -445px; 51 | } 52 | 53 | #header ul#navigation-menu li { 54 | float: left; 55 | } 56 | 57 | #header ul#navigation-menu li a { 58 | display: block; 59 | text-transform: uppercase; 60 | text-decoration: none; 61 | padding: 9px 15px; 62 | border-right: 1px solid #ededed; 63 | color: #555; 64 | } 65 | 66 | #header ul#navigation-menu li.disabled a { 67 | color: #bbb; 68 | cursor: default; 69 | } 70 | 71 | #header ul#navigation-menu li.first a { 72 | margin: 5px 0 0 12px; 73 | padding-top: 4px; 74 | text-indent: 14px; 75 | background: transparent url(../images/admin-tools.png) no-repeat 0 -385px; 76 | } 77 | 78 | #header ul#navigation-menu li span { 79 | float: right; 80 | height: 10px; 81 | width: 20px; 82 | background: transparent url(../images/admin-tools.png) no-repeat 0 -360px; 83 | } 84 | 85 | #header ul#navigation-menu li:hover, 86 | #header ul#navigation-menu li.over, 87 | #header ul#navigation-menu li.selected { 88 | background: url(../images/admin-tools.png) repeat-x 0 -245px; 89 | } 90 | 91 | #header ul#navigation-menu li ul { 92 | display: none; 93 | position: absolute; 94 | top: auto; 95 | left: auto; 96 | margin-left: -1px; 97 | margin-top: -1px; 98 | } 99 | 100 | #header ul#navigation-menu li ul li { 101 | padding: 0; 102 | float: none; 103 | background: none; 104 | z-index: 9999; 105 | } 106 | 107 | #header ul#navigation-menu li ul li a { 108 | display: block; 109 | border: 1px solid #ededed; 110 | border-width: 0 1px 1px 1px; 111 | text-transform: none; 112 | min-width: 180px; 113 | } 114 | 115 | #header ul#navigation-menu li ul li span { 116 | background-position: 0 -370px; 117 | } 118 | 119 | #header ul#navigation-menu li ul li ul { 120 | left: 100%; 121 | top: 0; 122 | border-top: 1px solid #ededed; 123 | } 124 | 125 | #header ul#navigation-menu li ul li ul li a { 126 | white-space: nowrap; 127 | } 128 | 129 | #header ul#navigation-menu li:hover ul li ul, 130 | #header ul#navigation-menu li.over ul li ul { 131 | display: none; 132 | } 133 | 134 | #header ul#navigation-menu li:hover ul, 135 | #header ul#navigation-menu li.over ul, 136 | #header ul#navigation-menu li ul li:hover ul, 137 | #header ul#navigation-menu li ul li.over ul { 138 | display: block; 139 | } 140 | 141 | #header ul#navigation-menu li:hover ul li, 142 | #header ul#navigation-menu li.over ul li, 143 | #header ul#navigation-menu li ul li:hover ul li, 144 | #header ul#navigation-menu li ul li.over ul li { 145 | background: transparent url(../images/admin-tools.png) repeat-x 0 -285px; 146 | } 147 | 148 | #header ul#navigation-menu li ul li:hover, 149 | #header ul#navigation-menu li ul li.over, 150 | #header ul#navigation-menu li ul li ul li:hover, 151 | #header ul#navigation-menu li ul li ul li.over { 152 | background: transparent url(../images/admin-tools.png) repeat-x 0 -245px; 153 | } 154 | 155 | #header ul#navigation-menu li.disabled:hover, 156 | #header ul#navigation-menu li.disabled .over { 157 | background: none; 158 | } 159 | -------------------------------------------------------------------------------- /example/media/admin_tools/css/theming.css: -------------------------------------------------------------------------------- 1 | /** 2 | * theming styles 3 | * 4 | */ 5 | 6 | #header { 7 | background: url(../images/admin-tools.png) 0 0 repeat-x; 8 | } 9 | 10 | #header #branding h1 { 11 | margin: 0; 12 | padding: 5px 10px; 13 | text-indent: -9999px; 14 | background: transparent url(../images/django.png) 10px 5px no-repeat; 15 | height: 31px; 16 | width: 93px; 17 | } 18 | 19 | div.breadcrumbs { 20 | display: block; 21 | padding: 10px 15px; 22 | border: 0; 23 | background-position: 0 -8px; 24 | border-bottom: 1px solid #ededed; 25 | } 26 | 27 | div.breadcrumbs a { 28 | display: inline; 29 | } 30 | -------------------------------------------------------------------------------- /example/media/admin_tools/images/admin-tools.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/callowayproject/dashboardmods/966e83947ce130d9c3a4d4f3b9796258d508b716/example/media/admin_tools/images/admin-tools.png -------------------------------------------------------------------------------- /example/media/admin_tools/images/django.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/callowayproject/dashboardmods/966e83947ce130d9c3a4d4f3b9796258d508b716/example/media/admin_tools/images/django.png -------------------------------------------------------------------------------- /example/media/admin_tools/js/jquery/jquery.cookie.min.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2006 Klaus Hartl (stilbuero.de) 2 | 3 | jQuery.cookie=function(name,value,options){if(typeof value!='undefined'){options=options||{};if(value===null){value='';options.expires=-1;} 4 | var expires='';if(options.expires&&(typeof options.expires=='number'||options.expires.toUTCString)){var date;if(typeof options.expires=='number'){date=new Date();date.setTime(date.getTime()+(options.expires*24*60*60*1000));}else{date=options.expires;} 5 | expires='; expires='+date.toUTCString();} 6 | var path=options.path?'; path='+(options.path):'';var domain=options.domain?'; domain='+(options.domain):'';var secure=options.secure?'; secure':'';document.cookie=[name,'=',encodeURIComponent(value),expires,path,domain,secure].join('');}else{var cookieValue=null;if(document.cookie&&document.cookie!=''){var cookies=document.cookie.split(';');for(var i=0;i 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining a 10 | * copy of this software and associated documentation files (the "Software"), 11 | * to deal in the Software without restriction, including without limitation 12 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | * and/or sell copies of the Software, and to permit persons to whom the 14 | * Software is furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be included in 17 | * all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | * DEALINGS IN THE SOFTWARE. 26 | */ 27 | 28 | (function($) { 29 | 30 | $.fn.extend({ 31 | //pass the options variable to the function 32 | dashboard: function(options) { 33 | //Set the default values, use comma to separate the settings, example: 34 | var defaults = { 35 | panel_id: 'dashboard-panel', 36 | dashboard_id: this.attr('id'), 37 | dashboard_module_class: 'dashboard-module', 38 | columns: 2, 39 | load_preferences_function: false, 40 | save_preferences_function: false 41 | } 42 | var options = $.extend(defaults, options); 43 | 44 | return this.each(function() { 45 | // set ids for dashboard modules 46 | _initialize($(this), options); 47 | // restore positions, must be done *before* columnize 48 | _restore_positions($(this), options); 49 | // columnize the dashboard modules 50 | _columnize($(this), options); 51 | // add draggable behaviour 52 | _set_draggable($(this), options); 53 | // add collapsible behaviour 54 | _set_collapsible($(this), options); 55 | // add deletable behaviour 56 | _set_deletable($(this), options); 57 | // add addable behaviour to dashboard panel items 58 | _set_addable($(this), options); 59 | // restore user preferences 60 | _restore_preferences($(this), options); 61 | }); 62 | } 63 | }); 64 | 65 | var preferences = false; 66 | 67 | var _initialize = function(elt, options) { 68 | // load preferences 69 | if (preferences === false) { 70 | if (options.load_preferences_function) { 71 | preferences = options.load_preferences_function(options); 72 | } else { 73 | var json_str = $.cookie('admin-tools.' + options.dashboard_id); 74 | preferences = json_str ? JSON.parse(json_str) : {}; 75 | } 76 | } 77 | // set ids if not set 78 | elt.children('div[id!=' + options.panel_id +']').each(function(index) { 79 | if (!$(this).attr('id')) { 80 | $(this).attr('id', 'module_' + index); 81 | } 82 | }); 83 | }; 84 | 85 | var _restore_positions = function(elt, options) { 86 | // restore positions 87 | try { 88 | var saved_positions = _get_preference(options, 'positions'); 89 | } catch (e) { 90 | return; 91 | } 92 | var current_positions = _get_positions(elt, options); 93 | var new_positions = []; 94 | 95 | for(var v = 0; v < current_positions.length; v++) { 96 | new_positions[current_positions[v]] = current_positions[v]; 97 | } 98 | 99 | for(var i = 0; i < saved_positions.length; i++) { 100 | // item id from saved order 101 | var id = saved_positions[i]; 102 | if (id in new_positions) { 103 | var item = new_positions[id]; 104 | var child = elt.children('#'+item); 105 | // select the item according to the saved order 106 | var saved = elt.children('#'+item); 107 | child.remove(); 108 | elt.append(saved); 109 | } 110 | } 111 | }; 112 | 113 | var _columnize = function(elt, options) { 114 | var elts = elt.children('div[id!=' + options.panel_id +']'); 115 | var size = Math.ceil(elts.length / options.columns); 116 | var sizes = _get_preference(options, 'columns'); 117 | var percent = Math.floor(100 / options.columns); 118 | var start = 0; 119 | var stop = 0; 120 | for (var i = 0; i < options.columns; i++) { 121 | if (typeof(sizes[i]) == 'undefined') { 122 | start = i * size; 123 | stop = start + size; 124 | } else if (sizes[i] == 0) { 125 | elt.append( 126 | '
      ' 127 | ); 128 | continue; 129 | } else { 130 | start = (i == 0) ? 0 : start + sizes[i-1]; 131 | stop = start + sizes[i]; 132 | } 133 | elts.slice(start, stop).wrapAll( 134 | '
      ' 135 | ); 136 | } 137 | }; 138 | 139 | var _restore_preferences = function(elt, options) { 140 | elt.children().children('.disabled').each(function() { 141 | _delete_element($(this), options); 142 | }); 143 | if (_get_preference(options, 'disabled')) { 144 | $.each(_get_preference(options, 'disabled'), function(k, v) { 145 | v ? _delete_element($('#'+k), options) : _add_element($('#'+k), options); 146 | }); 147 | } 148 | if (_get_preference(options, 'collapsed')) { 149 | $.each(_get_preference(options, 'collapsed'), function(k, v) { 150 | if (v) { 151 | _toggle_element($('#'+k), options); 152 | } 153 | }); 154 | } 155 | // if there's no element in the panel, hide it 156 | if (!$('#' + options.panel_id).find('li').length) { 157 | $('#' + options.panel_id).hide(); 158 | } 159 | }; 160 | 161 | var _set_draggable = function(elt, options) { 162 | // the dashboard column 163 | elt.children('.dashboard-column').sortable({ 164 | handle: 'h2', 165 | items: '.draggable', 166 | connectWith: '.dashboard-column', 167 | placeholder: 'dashboard-placeholder', 168 | forcePlaceholderSize: true, 169 | cursor: 'crosshair', 170 | opacity: 0.7, 171 | update: function() { 172 | _set_preference(options, 'positions', false, _get_positions(elt, options)); 173 | var columns = []; 174 | elt.children('.dashboard-column').each(function() { 175 | columns.push($(this).children().length); 176 | }); 177 | _set_preference(options, 'columns', false, columns, true); 178 | } 179 | }); 180 | }; 181 | 182 | var _set_collapsible = function(elt, options) { 183 | elt.find('> .dashboard-column > .collapsible > h2').each(function() { 184 | $(this).append('Toggle').find('a.toggle-icon').click(function() { 185 | var prnt = $(this).parent().parent(); 186 | _toggle_element(prnt, options, true); 187 | }); 188 | }); 189 | }; 190 | 191 | var _toggle_element = function(elt, options, save_preference) { 192 | elt.find('h2 a.toggle-icon').toggleClass('collapsed'); 193 | elt.children('div').slideToggle(); 194 | if (save_preference) { 195 | _set_preference(options, 'collapsed', elt.attr('id'), elt.find('h2 a.toggle-icon').hasClass('collapsed'), true); 196 | } 197 | }; 198 | 199 | var _set_deletable = function(elt, options) { 200 | elt.find('> .dashboard-column > .deletable > h2').each(function() { 201 | $(this).append('Close').find('a.close-icon').click(function() { 202 | var prnt = $(this).parent().parent(); 203 | _delete_element(prnt, options, true); 204 | }); 205 | }); 206 | }; 207 | 208 | var _delete_element = function(elt, options, save_preference) { 209 | var existing = $('#'+options.panel_id).find('li a[rel='+elt.attr('id')+']'); 210 | if (!existing.length) { 211 | var panel_ul = $('#' + options.panel_id).find('ul'); 212 | if (!panel_ul.length) { 213 | $('#' + options.panel_id).append('
        '); 214 | panel_ul = $('#' + options.panel_id).find('ul'); 215 | } 216 | panel_ul.append( 217 | '
      • ' 220 | + elt.find('h2').contents().first().text() 221 | + '
      • ' 222 | ); 223 | _set_addable(elt, options, $('#'+options.panel_id).find('li a[rel='+elt.attr('id')+']')); 224 | } else { 225 | existing.parent().show(); 226 | } 227 | elt.fadeOut('fast'); 228 | $('#' + options.panel_id).show(); 229 | if (save_preference) { 230 | _set_preference(options, 'disabled', elt.attr('id'), true, true); 231 | } 232 | }; 233 | 234 | var _set_addable = function(elt, options, elts) { 235 | if (!elts) { 236 | elts = $('#'+options.panel_id).find('li a'); 237 | } 238 | elts.click(function() { 239 | _add_element($('#'+$(this).attr('rel')), options, true); 240 | }); 241 | }; 242 | 243 | var _add_element = function(elt, options, save_preference) { 244 | var panel_elt = $('#'+options.panel_id).find('li a[rel='+elt.attr('id')+']'); 245 | panel_elt.parent().remove(); 246 | elt.removeClass('disabled'); 247 | elt.fadeIn('fast'); 248 | if (save_preference) { 249 | _set_preference(options, 'disabled', elt.attr('id'), false, true); 250 | } 251 | // if there's no element in the panel, hide it 252 | if (!$('#' + options.panel_id).find('li').length) { 253 | $('#' + options.panel_id).hide(); 254 | } 255 | }; 256 | 257 | var load_preferences = function(options) { 258 | if (options.load_preferences_function) { 259 | return options.load_preferences_function(options); 260 | } 261 | if (preferences === false) { 262 | var json_str = $.cookie('admin-tools.' + options.dashboard_id); 263 | preferences = json_str ? JSON.parse(json_str) : {}; 264 | } 265 | return preferences; 266 | } 267 | 268 | var _get_preference = function(options, cat, id, defaultval) { 269 | try { 270 | if (preferences[cat] == undefined) { 271 | preferences[cat] = {}; 272 | } 273 | if (id) { 274 | return preferences[cat][id]; 275 | } 276 | return preferences[cat]; 277 | } catch (e) { 278 | return defaultval ? defaultval : null; 279 | } 280 | }; 281 | 282 | // quick hack to ensure that we do not save preferences if they are 283 | // not modified... 284 | var last_saved_preferences = null; 285 | 286 | var _set_preference = function(options, cat, id, val, save) { 287 | try { 288 | if (preferences[cat] == undefined) { 289 | preferences[cat] = {}; 290 | } 291 | if (id) { 292 | preferences[cat][id] = val; 293 | } else { 294 | preferences[cat] = val; 295 | } 296 | } catch (e) { 297 | } 298 | // save preferences 299 | if (save && JSON.stringify(preferences) != last_saved_preferences) { 300 | if (options.save_preferences_function) { 301 | options.save_preferences_function(options, preferences); 302 | } else { 303 | $.cookie(cookie_name, JSON.stringify(preferences), {expires: 1825}); 304 | } 305 | last_saved_preferences = JSON.stringify(preferences); 306 | } 307 | }; 308 | 309 | var _get_positions = function(elt, options) { 310 | var modules = []; 311 | if (!elt.children('.dashboard-column').length) { 312 | elt.children('div[id!=' + options.panel_id +']').each(function() { 313 | modules.push($(this).attr('id')); 314 | }); 315 | } else { 316 | elt.children('.dashboard-column').each(function() { 317 | $.each($(this).sortable('toArray'), function(index, item) { 318 | modules.push(item); 319 | }); 320 | }); 321 | } 322 | return modules; 323 | } 324 | 325 | })(jQuery); 326 | -------------------------------------------------------------------------------- /example/media/admin_tools/js/json.min.js: -------------------------------------------------------------------------------- 1 | 2 | if(!this.JSON){this.JSON={};} 3 | (function(){function f(n){return n<10?'0'+n:n;} 4 | if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+'-'+ 5 | f(this.getUTCMonth()+1)+'-'+ 6 | f(this.getUTCDate())+'T'+ 7 | f(this.getUTCHours())+':'+ 8 | f(this.getUTCMinutes())+':'+ 9 | f(this.getUTCSeconds())+'Z':null;};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf();};} 10 | var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4);})+'"':'"'+string+'"';} 11 | function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key);} 12 | if(typeof rep==='function'){value=rep.call(holder,key,value);} 13 | switch(typeof value){case'string':return quote(value);case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null';} 14 | gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==='[object Array]'){length=value.length;for(i=0;i'); 35 | $('#navigation-menu li.bookmark').append('
          '); 36 | $('#navigation-menu li.bookmark').removeClass('disabled'); 37 | } 38 | $('#navigation-menu li.bookmark ul').append( 39 | '
        • ' + new_title + '
        • ' 40 | ); 41 | $('#bookmark-form input[name=title]').attr('value', new_title); 42 | // Save bookmark and switch form 43 | $.post(submit_url, $("#bookmark-form").serialize(), function(data) { 44 | $("#bookmark-form").replaceWith(data); 45 | }, 'html'); 46 | } 47 | }); 48 | }; 49 | -------------------------------------------------------------------------------- /example/menu.py: -------------------------------------------------------------------------------- 1 | from django.core.urlresolvers import reverse 2 | from django.utils.translation import ugettext_lazy as _ 3 | from admin_tools.menu import Menu 4 | from admin_tools.menu.items import MenuItem, AppList 5 | 6 | # to activate your custom menu add the following to your settings.py: 7 | # 8 | # ADMIN_TOOLS_MENU = 'example.menu.CustomMenu' 9 | 10 | class CustomMenu(Menu): 11 | """ 12 | Custom Menu for example admin site. 13 | """ 14 | def __init__(self, **kwargs): 15 | Menu.__init__(self, **kwargs) 16 | self.children.append(MenuItem( 17 | title=_('Dashboard'), 18 | url=reverse('admin:index') 19 | )) 20 | self.children.append(AppList( 21 | title=_('Applications'), 22 | exclude_list=('django.contrib',) 23 | )) 24 | self.children.append(AppList( 25 | title=_('Administration'), 26 | include_list=('django.contrib',) 27 | )) 28 | 29 | def init_with_context(self, context): 30 | """ 31 | Use this method if you need to access the request context. 32 | """ 33 | pass 34 | -------------------------------------------------------------------------------- /example/settings.py: -------------------------------------------------------------------------------- 1 | # Django settings for example project. 2 | 3 | DEBUG = True 4 | TEMPLATE_DEBUG = DEBUG 5 | import os, sys 6 | APP = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) 7 | PROJ_ROOT = os.path.abspath(os.path.dirname(__file__)) 8 | sys.path.append(APP) 9 | 10 | ADMINS = ( 11 | # ('Your Name', 'your_email@domain.com'), 12 | ) 13 | 14 | MANAGERS = ADMINS 15 | 16 | DATABASE_ENGINE = 'sqlite3' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. 17 | DATABASE_NAME = 'dev.db' # Or path to database file if using sqlite3. 18 | DATABASE_USER = '' # Not used with sqlite3. 19 | DATABASE_PASSWORD = '' # Not used with sqlite3. 20 | DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3. 21 | DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3. 22 | 23 | # Local time zone for this installation. Choices can be found here: 24 | # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name 25 | # although not all choices may be available on all operating systems. 26 | # If running in a Windows environment this must be set to the same as your 27 | # system time zone. 28 | TIME_ZONE = 'America/Chicago' 29 | 30 | # Language code for this installation. All choices can be found here: 31 | # http://www.i18nguy.com/unicode/language-identifiers.html 32 | LANGUAGE_CODE = 'en-us' 33 | 34 | SITE_ID = 1 35 | 36 | # If you set this to False, Django will make some optimizations so as not 37 | # to load the internationalization machinery. 38 | USE_I18N = True 39 | 40 | # Absolute path to the directory that holds media. 41 | # Example: "/home/media/media.lawrence.com/" 42 | MEDIA_ROOT = os.path.abspath(os.path.join('media')) 43 | 44 | # URL that handles the media served from MEDIA_ROOT. Make sure to use a 45 | # trailing slash if there is a path component (optional in other cases). 46 | # Examples: "http://media.lawrence.com", "http://example.com/media/" 47 | MEDIA_URL = '/static/' 48 | 49 | # URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a 50 | # trailing slash. 51 | # Examples: "http://foo.com/media/", "/media/". 52 | ADMIN_MEDIA_PREFIX = '/media/' 53 | 54 | # Make this unique, and don't share it with anybody. 55 | SECRET_KEY = 'g2_39yupn*6j4p*cg2%w643jiq-1n_annua*%i8+rq0dx9p=$n' 56 | 57 | # List of callables that know how to import templates from various sources. 58 | TEMPLATE_LOADERS = ( 59 | 'django.template.loaders.filesystem.load_template_source', 60 | 'django.template.loaders.app_directories.load_template_source', 61 | # 'django.template.loaders.eggs.load_template_source', 62 | ) 63 | TEMPLATE_CONTEXT_PROCESSORS = ( 64 | 'django.core.context_processors.auth', 65 | 'django.core.context_processors.request', 66 | ) 67 | 68 | MIDDLEWARE_CLASSES = ( 69 | 'django.middleware.common.CommonMiddleware', 70 | 'django.contrib.sessions.middleware.SessionMiddleware', 71 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 72 | ) 73 | 74 | ROOT_URLCONF = 'example.urls' 75 | 76 | TEMPLATE_DIRS = ( 77 | # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". 78 | # Always use forward slashes, even on Windows. 79 | # Don't forget to use absolute paths, not relative paths. 80 | ) 81 | 82 | INSTALLED_APPS = ( 83 | # 'admin_tools', # for the media copying 84 | 'admin_tools.theming', # keep me above admin 85 | 'admin_tools.menu', # keep me above admin 86 | 'admin_tools.dashboard', # keep me above admin 87 | 'django.contrib.admin', 88 | 'django.contrib.auth', 89 | 'django.contrib.contenttypes', 90 | 'django.contrib.sessions', 91 | 'django.contrib.sites', 92 | 'dashboardmods', 93 | ) 94 | ADMIN_TOOLS_INDEX_DASHBOARD = 'example.dashboard.CustomIndexDashboard' 95 | ADMIN_TOOLS_MENU = 'example.menu.CustomMenu' 96 | VARNISH_MANAGEMENT_ADDRS=('localhost:82',) 97 | CACHE_BACKEND = "memcached://localhost:11211/" -------------------------------------------------------------------------------- /example/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls.defaults import * 2 | from django.conf import settings 3 | 4 | # Uncomment the next two lines to enable the admin: 5 | from django.contrib import admin 6 | admin.autodiscover() 7 | 8 | urlpatterns = patterns('', 9 | # Example: 10 | # (r'^example/', include('example.foo.urls')), 11 | 12 | # Uncomment the admin/doc line below and add 'django.contrib.admindocs' 13 | # to INSTALLED_APPS to enable admin documentation: 14 | # (r'^admin/doc/', include('django.contrib.admindocs.urls')), 15 | (r'^admintools/', include('admin_tools.urls')), 16 | # Uncomment the next line to enable the admin: 17 | (r'^admin/', include(admin.site.urls)), 18 | 19 | (r'^static/(?P.*)$', 'django.views.static.serve', 20 | {'document_root': settings.MEDIA_ROOT}), 21 | ) 22 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | django-admin-tools==0.4.0 2 | 3 | # python-varnish is required for the varnish access 4 | # python-memcached is required for the memcache access -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import os, sys 2 | from setuptools import setup, find_packages 3 | 4 | def read_file(filename): 5 | path = os.path.abspath(os.path.dirname(__file__)) 6 | filepath = os.path.join(path, filename) 7 | try: 8 | return open(filepath).read() 9 | except: 10 | return '' 11 | 12 | setup( 13 | name = "dashboardmods", 14 | version = __import__('dashboardmods').get_version().replace(' ', '-'), 15 | url = 'http://opensource.washingtontimes.com/projects/dashboardmods/', 16 | author = 'Corey Oordt', 17 | author_email = 'coordt@washingtontimes.com', 18 | description = 'A collection of dashboard modules for django-admin-tools', 19 | long_description = read_file('README'), 20 | packages = find_packages(), 21 | include_package_data = True, 22 | package_data={'dashboardmods': [ 23 | 'templates/*.html', 24 | 'templates/*/*.html', 25 | 'templates/*/*/*.html', 26 | ]}, 27 | classifiers = [ 28 | 'Development Status :: 4 - Beta', 29 | 'Environment :: Web Environment', 30 | 'Framework :: Django', 31 | 'Intended Audience :: Developers', 32 | 'License :: OSI Approved :: BSD License', 33 | 'Operating System :: OS Independent', 34 | 'Programming Language :: Python', 35 | 'Topic :: Internet :: WWW/HTTP', 36 | 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', 37 | 'Topic :: Internet :: WWW/HTTP :: WSGI', 38 | 'Topic :: Software Development :: Libraries :: Application Frameworks', 39 | 'Topic :: Software Development :: Libraries :: Python Modules', 40 | ], 41 | ) 42 | 43 | 44 | --------------------------------------------------------------------------------