diff options
author | Chris Miller <christopher@ctmiller.net> | 2010-02-20 10:59:07 -0500 |
---|---|---|
committer | Chris Miller <christopher@ctmiller.net> | 2010-02-20 10:59:07 -0500 |
commit | 50083ace2b7ada3a21889b1498399af1c3d8fc2a (patch) | |
tree | 8a515f29bb3d5b8156d3f3a55668503d699616ce /snakeplan | |
download | snakeplan-50083ace2b7ada3a21889b1498399af1c3d8fc2a.tar.bz2 snakeplan-50083ace2b7ada3a21889b1498399af1c3d8fc2a.tar.xz snakeplan-50083ace2b7ada3a21889b1498399af1c3d8fc2a.zip |
Basic list of iterations. Needs much much more work.
Diffstat (limited to 'snakeplan')
-rwxr-xr-x | snakeplan/__init__.py | 0 | ||||
-rwxr-xr-x | snakeplan/manage.py | 11 | ||||
-rwxr-xr-x | snakeplan/projects/__init__.py | 0 | ||||
-rw-r--r-- | snakeplan/projects/admin.py | 8 | ||||
-rwxr-xr-x | snakeplan/projects/models.py | 95 | ||||
-rw-r--r-- | snakeplan/projects/templates/footer.html | 2 | ||||
-rw-r--r-- | snakeplan/projects/templates/header.html | 4 | ||||
-rw-r--r-- | snakeplan/projects/templates/iteration_list.html | 18 | ||||
-rwxr-xr-x | snakeplan/projects/tests.py | 23 | ||||
-rw-r--r-- | snakeplan/projects/urls.py | 6 | ||||
-rw-r--r-- | snakeplan/projects/views/__init__.py | 0 | ||||
-rw-r--r-- | snakeplan/projects/views/iterations.py | 11 | ||||
-rwxr-xr-x | snakeplan/settings.py | 55 | ||||
-rw-r--r-- | snakeplan/snakeplan.db | bin | 0 -> 86016 bytes | |||
-rwxr-xr-x | snakeplan/urls.py | 59 |
15 files changed, 292 insertions, 0 deletions
diff --git a/snakeplan/__init__.py b/snakeplan/__init__.py new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/snakeplan/__init__.py | |||
diff --git a/snakeplan/manage.py b/snakeplan/manage.py new file mode 100755 index 0000000..5e78ea9 --- /dev/null +++ b/snakeplan/manage.py | |||
@@ -0,0 +1,11 @@ | |||
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) | ||
diff --git a/snakeplan/projects/__init__.py b/snakeplan/projects/__init__.py new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/snakeplan/projects/__init__.py | |||
diff --git a/snakeplan/projects/admin.py b/snakeplan/projects/admin.py new file mode 100644 index 0000000..7471356 --- /dev/null +++ b/snakeplan/projects/admin.py | |||
@@ -0,0 +1,8 @@ | |||
1 | from snakeplan.projects import models | ||
2 | from django.contrib import admin | ||
3 | |||
4 | admin.site.register(models.Task) | ||
5 | admin.site.register(models.Story) | ||
6 | admin.site.register(models.Project) | ||
7 | admin.site.register(models.Iteration) | ||
8 | admin.site.register(models.LoggedTime) | ||
diff --git a/snakeplan/projects/models.py b/snakeplan/projects/models.py new file mode 100755 index 0000000..b91ec7c --- /dev/null +++ b/snakeplan/projects/models.py | |||
@@ -0,0 +1,95 @@ | |||
1 | from django.db import models as m | ||
2 | from django.db.models import Model | ||
3 | from django.contrib.auth.models import User | ||
4 | |||
5 | |||
6 | STATUSES = ( | ||
7 | (0, 'Active'), | ||
8 | (1, 'Inactive'), | ||
9 | ) | ||
10 | |||
11 | DISPOSITIONS = ( | ||
12 | (0, 'Planned'), | ||
13 | (1, 'Carried Over'), | ||
14 | (2, 'Added'), | ||
15 | (3, 'Discovered'), | ||
16 | ) | ||
17 | |||
18 | TASK_TYPES = ( | ||
19 | (0, 'Feature'), | ||
20 | (1, 'Debt'), | ||
21 | (2, 'Functional Test'), | ||
22 | (3, 'Acceptance Test'), | ||
23 | (4, 'Overhead'), | ||
24 | ) | ||
25 | |||
26 | |||
27 | class Project(Model): | ||
28 | |||
29 | name = m.CharField(max_length=200) | ||
30 | description = m.TextField(blank=True) | ||
31 | active = m.BooleanField(default=True) | ||
32 | hidden = m.BooleanField(default=False) | ||
33 | wiki_link = m.URLField(blank=True) | ||
34 | |||
35 | def __unicode__(self): | ||
36 | return self.name | ||
37 | |||
38 | |||
39 | class Iteration(Model): | ||
40 | |||
41 | name = m.CharField(max_length=200) | ||
42 | project = m.ForeignKey(Project) | ||
43 | status = m.IntegerField(choices=STATUSES, default=0) | ||
44 | start_date = m.DateField() | ||
45 | end_date = m.DateField() | ||
46 | days_worked = m.DecimalField(default=0, decimal_places=2, max_digits=5) | ||
47 | description = m.TextField(blank=True) | ||
48 | |||
49 | def __unicode__(self): | ||
50 | return self.name | ||
51 | |||
52 | |||
53 | class Story(Model): | ||
54 | |||
55 | name = m.CharField(max_length=200) | ||
56 | project = m.ForeignKey(Project) | ||
57 | iteration = m.ForeignKey(Iteration, blank=True) | ||
58 | disposition = m.IntegerField(choices=DISPOSITIONS) | ||
59 | customer = m.ForeignKey(User, blank=True, related_name='story_customer') | ||
60 | tracker = m.ForeignKey(User, blank=True) | ||
61 | status = m.IntegerField(choices=STATUSES, default=0) | ||
62 | priority = m.IntegerField() | ||
63 | order = m.IntegerField() | ||
64 | description = m.TextField(blank=True) | ||
65 | |||
66 | def __unicode__(self): | ||
67 | return self.name | ||
68 | |||
69 | |||
70 | class Task(Model): | ||
71 | |||
72 | name = m.CharField(max_length=200) | ||
73 | story = m.ForeignKey(Story) | ||
74 | task_type = m.IntegerField(choices=TASK_TYPES) | ||
75 | disposition = m.IntegerField(choices=DISPOSITIONS) | ||
76 | acceptor = m.ForeignKey(User, blank=True) | ||
77 | estimated_hours = m.DecimalField(decimal_places=2, max_digits=5) | ||
78 | description = m.TextField(blank=True) | ||
79 | |||
80 | def __unicode__(self): | ||
81 | return self.name | ||
82 | |||
83 | |||
84 | class LoggedTime(Model): | ||
85 | |||
86 | start_time = m.DateTimeField(blank=True) | ||
87 | end_time = m.DateTimeField(blank=True) | ||
88 | logged_date = m.DateField() | ||
89 | duration = m.DecimalField(decimal_places=2, max_digits=5) | ||
90 | person1 = m.ForeignKey(User, blank=True, related_name="person1") | ||
91 | person2 = m.ForeignKey(User, blank=True, related_name="person2") | ||
92 | description = m.TextField(blank=True) | ||
93 | |||
94 | def __unicode__(self): | ||
95 | return self.description | ||
diff --git a/snakeplan/projects/templates/footer.html b/snakeplan/projects/templates/footer.html new file mode 100644 index 0000000..308b1d0 --- /dev/null +++ b/snakeplan/projects/templates/footer.html | |||
@@ -0,0 +1,2 @@ | |||
1 | </body> | ||
2 | </html> | ||
diff --git a/snakeplan/projects/templates/header.html b/snakeplan/projects/templates/header.html new file mode 100644 index 0000000..75ba4bf --- /dev/null +++ b/snakeplan/projects/templates/header.html | |||
@@ -0,0 +1,4 @@ | |||
1 | <html> | ||
2 | <head><title>{{page_title]]</title></head> | ||
3 | |||
4 | <body> | ||
diff --git a/snakeplan/projects/templates/iteration_list.html b/snakeplan/projects/templates/iteration_list.html new file mode 100644 index 0000000..55bad08 --- /dev/null +++ b/snakeplan/projects/templates/iteration_list.html | |||
@@ -0,0 +1,18 @@ | |||
1 | <h1>{{project_name}}</h1> | ||
2 | |||
3 | |||
4 | {% for item in iteration_list %} | ||
5 | <div id="{{item.id}}"> | ||
6 | <ul> | ||
7 | <li><a href="{{item.id}}">{{ item.name }}</a></li> | ||
8 | <li>{{ item.description }}</li> | ||
9 | <li>{{ item.status }}</li> | ||
10 | <li>{{ item.start_date }}</li> | ||
11 | <li>{{ item.end_date }}</li> | ||
12 | <li>{{ item.days_worked }}</li> | ||
13 | </ul> | ||
14 | </div> | ||
15 | {% endfor %} | ||
16 | </ul> | ||
17 | |||
18 | |||
diff --git a/snakeplan/projects/tests.py b/snakeplan/projects/tests.py new file mode 100755 index 0000000..2247054 --- /dev/null +++ b/snakeplan/projects/tests.py | |||
@@ -0,0 +1,23 @@ | |||
1 | """ | ||
2 | This file demonstrates two different styles of tests (one doctest and one | ||
3 | unittest). These will both pass when you run "manage.py test". | ||
4 | |||
5 | Replace these with more appropriate tests for your application. | ||
6 | """ | ||
7 | |||
8 | from django.test import TestCase | ||
9 | |||
10 | class SimpleTest(TestCase): | ||
11 | def test_basic_addition(self): | ||
12 | """ | ||
13 | Tests that 1 + 1 always equals 2. | ||
14 | """ | ||
15 | self.failUnlessEqual(1 + 1, 2) | ||
16 | |||
17 | __test__ = {"doctest": """ | ||
18 | Another way to test that 1 + 1 is equal to 2. | ||
19 | |||
20 | >>> 1 + 1 == 2 | ||
21 | True | ||
22 | """} | ||
23 | |||
diff --git a/snakeplan/projects/urls.py b/snakeplan/projects/urls.py new file mode 100644 index 0000000..cf1f67d --- /dev/null +++ b/snakeplan/projects/urls.py | |||
@@ -0,0 +1,6 @@ | |||
1 | from django.conf.urls.defaults import * | ||
2 | from projects.views.iterations import * | ||
3 | |||
4 | urlpatterns = patterns('', | ||
5 | ('^(.*?)/iterations/', iteration_list), | ||
6 | ) | ||
diff --git a/snakeplan/projects/views/__init__.py b/snakeplan/projects/views/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/snakeplan/projects/views/__init__.py | |||
diff --git a/snakeplan/projects/views/iterations.py b/snakeplan/projects/views/iterations.py new file mode 100644 index 0000000..327de82 --- /dev/null +++ b/snakeplan/projects/views/iterations.py | |||
@@ -0,0 +1,11 @@ | |||
1 | from django.shortcuts import render_to_response | ||
2 | from projects.models import Project, Iteration | ||
3 | |||
4 | def iteration_list(request, project_id): | ||
5 | project = Project.objects.filter(id = project_id) | ||
6 | iteration_list = Iteration.objects.filter(project = project_id) | ||
7 | |||
8 | return render_to_response("iteration_list.html", | ||
9 | {"project_name" : project[0].name, | ||
10 | "iteration_list" : iteration_list | ||
11 | }) | ||
diff --git a/snakeplan/settings.py b/snakeplan/settings.py new file mode 100755 index 0000000..6da9ec1 --- /dev/null +++ b/snakeplan/settings.py | |||
@@ -0,0 +1,55 @@ | |||
1 | DEBUG = True | ||
2 | TEMPLATE_DEBUG = DEBUG | ||
3 | |||
4 | ADMINS = ( | ||
5 | ('Mike Crute', 'mcrute@gmail.com'), | ||
6 | ) | ||
7 | |||
8 | MANAGERS = ADMINS | ||
9 | |||
10 | DATABASE_ENGINE = 'sqlite3' | ||
11 | DATABASE_NAME = 'snakeplan.db' | ||
12 | |||
13 | TIME_ZONE = 'America/New_York' | ||
14 | LANGUAGE_CODE = 'en-us' | ||
15 | |||
16 | SITE_ID = 1 | ||
17 | |||
18 | USE_I18N = False | ||
19 | |||
20 | # Absolute path to the directory that holds media. | ||
21 | # Example: "/home/media/media.lawrence.com/" | ||
22 | MEDIA_ROOT = '' | ||
23 | |||
24 | # URL that handles the media served from MEDIA_ROOT. Make sure to use a | ||
25 | # trailing slash if there is a path component (optional in other cases). | ||
26 | # Examples: "http://media.lawrence.com", "http://example.com/media/" | ||
27 | MEDIA_URL = '' | ||
28 | ADMIN_MEDIA_PREFIX = '/media/' | ||
29 | |||
30 | SECRET_KEY = 'ow28jyl#0h8+^3$-!*%o-qfj5#zyr@xz+%vn_a3iizhn%l-3_=' | ||
31 | |||
32 | TEMPLATE_LOADERS = ( | ||
33 | 'django.template.loaders.filesystem.load_template_source', | ||
34 | 'django.template.loaders.app_directories.load_template_source', | ||
35 | ) | ||
36 | |||
37 | MIDDLEWARE_CLASSES = ( | ||
38 | 'django.middleware.common.CommonMiddleware', | ||
39 | 'django.contrib.sessions.middleware.SessionMiddleware', | ||
40 | 'django.contrib.auth.middleware.AuthenticationMiddleware', | ||
41 | ) | ||
42 | |||
43 | ROOT_URLCONF = 'snakeplan.urls' | ||
44 | |||
45 | TEMPLATE_DIRS = ( | ||
46 | ) | ||
47 | |||
48 | INSTALLED_APPS = ( | ||
49 | 'django.contrib.auth', | ||
50 | 'django.contrib.contenttypes', | ||
51 | 'django.contrib.sessions', | ||
52 | 'django.contrib.sites', | ||
53 | 'django.contrib.admin', | ||
54 | 'snakeplan.projects', | ||
55 | ) | ||
diff --git a/snakeplan/snakeplan.db b/snakeplan/snakeplan.db new file mode 100644 index 0000000..a572f4b --- /dev/null +++ b/snakeplan/snakeplan.db | |||
Binary files differ | |||
diff --git a/snakeplan/urls.py b/snakeplan/urls.py new file mode 100755 index 0000000..d02a714 --- /dev/null +++ b/snakeplan/urls.py | |||
@@ -0,0 +1,59 @@ | |||
1 | from django.conf.urls.defaults import * | ||
2 | from django.contrib import admin | ||
3 | from snakeplan.projects import admin as snakeplan_admin | ||
4 | |||
5 | admin.autodiscover() | ||
6 | |||
7 | urlpatterns = patterns('', | ||
8 | (r'^snakeplan/projects/', include('snakeplan.projects.urls')), | ||
9 | (r'^admin/', include(admin.site.urls)), | ||
10 | #(r'^foo$', 'snakeplan.projects.views.foo'), | ||
11 | #(r'^projects$', 'snakeplan.projects.views.foo'), | ||
12 | ) | ||
13 | |||
14 | |||
15 | """ | ||
16 | ====== ======================== ======================================== | ||
17 | Method URL What it does | ||
18 | ====== ======================== ======================================== | ||
19 | GET /modelname/ Lists model instances, using filters | ||
20 | like ?key=value1&key=value2 | ||
21 | |||
22 | GET /modelname/search displays a search form | ||
23 | |||
24 | GET /modelname/id displays a readonly instance | ||
25 | |||
26 | GET /modelname/edit/id displays an edit form | ||
27 | |||
28 | POST /modelname/update/id updates an instance and redirects | ||
29 | |||
30 | POST /modelname/upsert Updates or inserts an instance and | ||
31 | redirects | ||
32 | |||
33 | GET /modelname/upsert Draws a form to do an upsert. | ||
34 | |||
35 | GET /modelname/upsertform Draws a form to do an upsert. | ||
36 | |||
37 | GET /modelname/create displays an insert form | ||
38 | |||
39 | GET /modelname/insertform displays an insert form | ||
40 | |||
41 | GET /modelname/remove/id displays a form that posts to | ||
42 | /model/delete/id | ||
43 | |||
44 | POST /modelname/insert inserts a new record and redirects | ||
45 | |||
46 | POST /modelname/delete/id deletes a record and redirects | ||
47 | |||
48 | GET /modelname/bulk/edit display a bulk edit ui | ||
49 | |||
50 | POST /modelname/bulk/update performs a bulk update and redirect | ||
51 | |||
52 | GET /modelname/bulk/create display a bulk insert form | ||
53 | |||
54 | POST /modelname/bulk/insert performs a bulk insert and redirect | ||
55 | |||
56 | POST /modelname/bulk/delete performs a bulk delete and redirect | ||
57 | |||
58 | ====== ======================== ======================================== | ||
59 | """ | ||