{"id":17349826,"url":"https://github.com/stasm/todo","last_synced_at":"2026-03-08T04:31:41.713Z","repository":{"id":138206589,"uuid":"1009894","full_name":"stasm/todo","owner":"stasm","description":"A todo/progress tracking app for Mozilla's localization dashboard (http://hg.mozilla.org/l10n/django-site/).","archived":false,"fork":false,"pushed_at":"2011-03-29T17:32:58.000Z","size":1028,"stargazers_count":5,"open_issues_count":16,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-14T21:12:56.133Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://wiki.mozilla.org/L10n:Dashboard/Apps/Todo","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stasm.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2010-10-20T18:26:46.000Z","updated_at":"2020-05-05T09:17:55.000Z","dependencies_parsed_at":"2023-03-14T17:45:50.782Z","dependency_job_id":null,"html_url":"https://github.com/stasm/todo","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/stasm/todo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stasm%2Ftodo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stasm%2Ftodo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stasm%2Ftodo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stasm%2Ftodo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stasm","download_url":"https://codeload.github.com/stasm/todo/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stasm%2Ftodo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30245219,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-08T00:58:18.660Z","status":"online","status_checked_at":"2026-03-08T02:00:06.215Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-15T16:57:14.286Z","updated_at":"2026-03-08T04:31:41.696Z","avatar_url":"https://github.com/stasm.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"Installation\n============\n\n#. Put the ``todo`` directory in your Python path.\n\n#. Add ``todo`` to your ``INSTALLED_APPS`` setting.\n\n#. Add the following line to your global URL patterns::\n\n    (r'^todo/', include('todo.urls')),\n\n#. Sync the database.\n\n#. Copy ``todo/static`` to wherever you serve your static files from.\n\n\nIntegration\n===========\n\nIn order to enable *todo* for your app, follow the steps below.\n\n\nModels\n------\n\n#. Add a one-to-one relation to your app's project model definition pointing to\n   ``todo.models.Project``::\n\n    from todo.models import Project as TodoProject\n\n    class YourProject(models.Model):\n        ...\n        todo = models.OneToOneField(TodoProject, related_name=\"yourapp\")\n\n#. Modify the database accordingly. For example::\n\n    ALTER TABLE yourapp_yourproject \n    ADD COLUMN `todo_id` integer NOT NULL UNIQUE;\n\n   You can also run `python manage.py sql yourapp` to see what column definiton \n   Django expects from the addition in the previous step.\n\n#. Optionally, add the new ``todo`` field on your project's model to its admin \n   panel::\n\n    from django.contrib import admin\n\n    from yourapp.models import YourProject\n\n    class YourProjectAdmin(admin.ModelAdmin):\n        ...\n        fieldsets = (\n                ...\n                ('Integration', {\n                    'classes': ('collapse',),\n                    'fields': ('todo',),\n                }),\n        )\n\n    admin.site.register(YourProject, YourProjectAdmin)\n\n#. Create ``todo.models.Project`` objects corresponding to your app's projects. \n   You'll need to create one object for each project you have.  This can be \n   easily done via your app's admin panel or using the ``createtodoprojects`` \n   management command supplied by ``todo``.\n\n   To use the ``createtodoprojects`` command pass the name of the model from \n   your app that you use to store your projects.  You can specify more than \n   one model.  Use the app_label.model_label syntax::\n\n    python manage.py createtodoprojects yourapp.YourProject\n\n   One todo.Project object will be created for each of your projects.  The \n   default label for todo.Project is whatever ``unicode(yourproject)`` returns.  \n   You can override this by passing a Python statement in the ``--label`` \n   option. An exception will be raised if the syntax is not valid or if the \n   statement doesn't evaluate to a string.  The statement is evaluated in the \n   current environment of the command, so be careful not to delete your \n   projects accidentally.  Example::\n\n     python manage.py createtodoprojects \\\n       --label '\"%s %s\" % (project.line.name, project.version)' \\\n       yourapp.YourProject\n\n   The label is always truncated to the first 50 characters.\n\n\nTracker and Task Views\n----------------------\n\nThe views display data about trackers and/or tasks.  ``todo`` provides snippets \nthat you can configure in your existing views and include in your templates.\n\n#. Create or modify views in which you want to use the ``todo`` snippets. You \n   must have at least two views:\n   \n   * a single task view,\n   * a single tracker view.\n\n   These two views are *required*. Additionally, you might want to create:\n\n   * a single project view,\n   * a single locale view,\n   * a combined (project+locale) view.\n\n   You might want to modify your app's URL patterns like so::\n\n    urlpatterns += patterns('yourapp.views',\n        (r'^task/(?P\u003ctask_id\u003e\\d+)$', 'single_task'), \n        (r'^tracker/(?P\u003ctracker_id\u003e\\d+)$', 'single_tracker'), \n    )\n\n   (Add more URL patterns if you have more views.)\n\n   Here's an example of how these views can look like::\n\n    from django.shortcuts import get_object_or_404, render_to_response\n\n    from todo.views import snippets\n\n    def single_task(request, task_id):\n        from todo.models import Task\n        task = get_object_or_404(Task, pk=task_id)\n        task_snippet = snippets.task(request, task,\n                                     redirect_view='yourapp.views.single_task')\n        return render_to_response('yourapp/single_task.html',\n                                  {'task_snippet': task_snippet,})\n\n    def single_tracker(request, tracker_id):\n        from todo.models import Tracker\n        tracker = get_object_or_404(Tracker, pk=tracker_id)\n        tree = snippets.tree(request, tracker=tracker,\n                             project=None, locale=None,\n                             task_view='yourapp.views.single_task',\n                             tracker_view='yourapp.views.single_tracker')\n        return render_to_response('yourapp/single_tracker.html',\n                                  {'tree': tree,})\n\n   See ``todo.views.snippets`` and ``todo.views.demo`` for more documentation.\n\n#. Add the ``todo`` snippets' ``divs`` to your templates. Wrap them in\n   a ``div`` with the ``todo`` class. For example::\n\n    \u003cdiv class=\"todo\"\u003e{{task.div}}\u003c/div\u003e\n\n   or::\n\n    \u003cdiv class=\"todo\"\u003e{{tree.div}}\u003c/div\u003e\n\n   For views showing more than a single task, you can use the ``empty`` element \n   of the dictionary returned by the snippet to show a customized message in \n   case there is nothing to display. For instance::\n\n    {% if not tree.empty %}\n      \u003cdiv class=\"todo\"\u003e{{tree.div}}\u003c/div\u003e\n    {% else %}\n      \u003cp\u003eNo trackers or tasks to show.\u003c/p\u003e\n    {% endif %}\n\n#. Include the following code snippet in the ``HEAD`` section of every view\n   that will display ``todo``'s snippets::\n\n    \u003clink rel=\"stylesheet\" type=\"text/css\" href=\"{% url static path='todo/todo.css' %}\" /\u003e\n\n#. Include the following code snippet in the ``HEAD`` section of every view \n   that will display a single task::\n\n    \u003cstyle type=\"text/css\"\u003e\n        .todo #outofdate {\n            background-image: url({% url static path=\"todo/warning.png\" %});\n        }\n        .todo #uptodate {\n            background-image: url({% url static path=\"todo/okay.png\" %});\n        }\n        .todo #checking div {\n            background: url({% url static path=\"loadingAnimation.gif\" %}) no-repeat 0 13px;\n        }\n    \u003c/style\u003e\n\n\nCreate-New Interface\n--------------------\n\nThis is a special view which you can use to configure how new trackers and \ntasks are created.  By default, ``todo`` provides a simple version of this \ninterface at ``/todo/new``.  It is very straightforward:  it shows all the \nprojects (from all the apps using ``todo``) and doesn't let you redirect to the \nnewly created todos after a successul POST request.\n\nIt is possible to customize this interface on a per-app basis, thus allowing to \naddress the limitations mentioned above.  Follow the steps below to create \na custom ersion of the create-new interface for you app.\n\n#. Add a create-new view to your urls.py::\n\n    urlpatterns += patterns('yourapp.views',\n        (r'^\\/new-todo$', 'new_todo'),\n    )\n\n#. Create the view specified in urls.py (``yourapp.view.new_todo`` in the \n   example above)::\n\n    from todo.views import new as create_new_wizard\n\n    def new_todo(request):\n        def locale_filter(appver):\n            \"\"\"Get a QuerySet of Locales related to the project (appver).\n\n            This function will be run after the user selects a project to \n            create new todos for in the create-new interface.  It allows you to \n            narrow the list of available locales to those that actually make \n            sense for the project chosen by the user.  The returned locales \n            will be displayed in a select box in the form wizard.\n\n            \"\"\"\n            return Locale.objects.filter(appvers=appver)\n\n        appvers = YourProject.objects.filter(is_archived=False)\n\n        config = {\n            'projects': appvers,\n            'locale_filter': locale_filter,\n            'get_template': lambda step: 'yourapp/new_%d.html' % step,\n            'task_view': 'yourapp.views.task',\n            'tracker_view': 'yourapp.views.tracker',\n            'thankyou_view': 'yourapp.views.created',\n        }\n        return create_new_wizard(request, **config)\n\n   You can control the most important aspects of the wizard's behavior with the \n   ``config`` dict.  It accepts the following keys and values:\n\n   - `projects`: a QuerySet with the project-like objects in your app.  If \n     `None` (or omitted), all `todo.Project` objects will be shown, possibly \n     showing objects from outside of your app as well (if your app is not the \n     only one using ``todo``).\n\n   - `locale_filter`: a function accepting a single argument, `project`, which \n     is an element from the QuerySet passed in `projects` above.  The function \n     should return a QuerySet of `Locales` related to the passed `project`.  If \n     `None` (or omitted), all locale will be displayed regardless of the \n     projects chosen in the first step.\n\n   - `get_template`: a function accepting a single argument, `step`, which is \n     a zero-based integer index of the step of wizard.  It should return \n     a string which is a name of the template to use for the given step.  If \n     `None` (or omitted), the following default will be used::\n\n      'todo/new_%d.html' % step\n\n   - `task_view`: a string name of the view responsible for showing a single \n     task in your application.  It will be used for redirecting the user to the \n     newly created task.  If `None` (or omitted), the generic 'thank you' view \n     will be used, which will not include any link to the newly created task \n     but can be used to inform the user that the request has been processed \n     successfully.  See `thankyou_view` below.\n\n   - `tracker_view`: a string name of the view responsible for showing a single \n     tracker in your application.  It will be used for redirecting the user to \n     the newly created tracker.  If `None` (or omitted), the generic 'thank \n     you' view will be used, which will not include any link to the newly \n     created tracker but can be used to inform the user that the request has \n     been processed successfully.  See `thankyou_view` below.\n\n   - `thankyou_view`: a string name of the generic 'thank you'/'success' view \n     that will be displayed in absence of the `task_view` or `tracker_view`.  \n     If `None` (or omitted), the default provided by ``todo`` will be used, \n     i.e. `todo.views.created`.\n\n#. Grant the following permissions to users/groups that should be able to \n   create new trackers and tasks::\n\n    todo.create_tracker\n    todo.create_task\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstasm%2Ftodo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstasm%2Ftodo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstasm%2Ftodo/lists"}