45 |
45 |
46 #: Each task_type tag is scoped under the program. |
46 #: Each task_type tag is scoped under the program. |
47 scope = db.ReferenceProperty(reference_class=soc.models.linkable.Linkable, |
47 scope = db.ReferenceProperty(reference_class=soc.models.linkable.Linkable, |
48 required=True, |
48 required=True, |
49 collection_name='task_type_tags') |
49 collection_name='task_type_tags') |
50 |
50 |
|
51 order = db.IntegerProperty(required=True, default=0) |
|
52 |
51 @classmethod |
53 @classmethod |
52 def __key_name(cls, scope_path, tag_name): |
54 def __key_name(cls, scope_path, tag_name): |
53 """Create the key_name from program key_name as scope_path and tag_name. |
55 """Create the key_name from program key_name as scope_path and tag_name. |
54 """ |
56 """ |
55 return scope_path + '/' + tag_name |
57 return scope_path + '/' + tag_name |
60 """ |
62 """ |
61 tags = db.Query(cls).filter('tag =', tag_name).fetch(1000) |
63 tags = db.Query(cls).filter('tag =', tag_name).fetch(1000) |
62 return tags |
64 return tags |
63 |
65 |
64 @classmethod |
66 @classmethod |
65 def get_or_create(cls, program, tag_name): |
67 def get_by_scope(cls, scope): |
|
68 """Get the list of tag objects that has the given scope. |
|
69 """ |
|
70 tags = db.Query(cls).filter('scope =', scope).order('order').fetch(1000) |
|
71 return tags |
|
72 |
|
73 @classmethod |
|
74 def get_highest_order(cls, scope): |
|
75 """Get a tag with highest order. |
|
76 """ |
|
77 tags = db.Query(cls).filter('scope =', scope).order('-order').fetch(1) |
|
78 if tags: |
|
79 return tags[0].order |
|
80 else: |
|
81 return -1 |
|
82 |
|
83 @classmethod |
|
84 def get_by_scope_and_name(cls, scope, tag_name): |
|
85 """Get a tag by scope and name. |
|
86 |
|
87 There can be only one such tag. |
|
88 """ |
|
89 |
|
90 tags = db.Query(cls).filter( |
|
91 'scope =', scope).filter('tag =', tag_name).fetch(1) |
|
92 if tags: |
|
93 return tags[0] |
|
94 else: |
|
95 return None |
|
96 |
|
97 @classmethod |
|
98 def update_order(cls, scope, tag_name, order): |
|
99 """Updates the order of the tag. |
|
100 """ |
|
101 |
|
102 tag = cls.get_by_scope_and_name(scope, tag_name) |
|
103 if tag: |
|
104 tag.order = order |
|
105 tag.put() |
|
106 |
|
107 return tag |
|
108 |
|
109 @classmethod |
|
110 def copy_tag(cls, scope, tag_name, new_tag_name): |
|
111 """Copy a tag with a given scope and tag_name to another tag with |
|
112 new tag_name. |
|
113 """ |
|
114 tag = cls.get_by_scope_and_name(scope, tag_name) |
|
115 |
|
116 if tag: |
|
117 tag_key_name = cls.__key_name(scope.key().name(), new_tag_name) |
|
118 existing_tag = cls.get_by_key_name(tag_key_name) |
|
119 |
|
120 if existing_tag is None: |
|
121 new_tag = cls(key_name=tag_key_name, tag=new_tag_name, scope=scope, |
|
122 added=tag.added, tagged=tag.tagged, |
|
123 tagged_count=tag.tagged_count) |
|
124 new_tag.put() |
|
125 tag.delete() |
|
126 |
|
127 return new_tag |
|
128 |
|
129 return existing_tag |
|
130 |
|
131 return None |
|
132 |
|
133 @classmethod |
|
134 def delete_tag(cls, scope, tag_name): |
|
135 """Copy a tag with a given scope and tag_name to another tag with |
|
136 new tag_name. |
|
137 """ |
|
138 tag = cls.get_by_scope_and_name(scope, tag_name) |
|
139 |
|
140 if tag: |
|
141 tag.delete() |
|
142 return True |
|
143 |
|
144 return False |
|
145 |
|
146 @classmethod |
|
147 def get_or_create(cls, scope, tag_name, order=0): |
66 """Get the Tag object that has the tag value given by tag_value. |
148 """Get the Tag object that has the tag value given by tag_value. |
67 """ |
149 """ |
68 tag_key_name = cls.__key_name(program.key().name(), tag_name) |
150 tag_key_name = cls.__key_name(scope.key().name(), tag_name) |
69 existing_tag = cls.get_by_key_name(tag_key_name) |
151 existing_tag = cls.get_by_key_name(tag_key_name) |
70 if existing_tag is None: |
152 if existing_tag is None: |
71 # the tag does not yet exist, so create it. |
153 # the tag does not yet exist, so create it. |
|
154 if not order: |
|
155 order = cls.get_highest_order(scope=scope) + 1 |
72 def create_tag_txn(): |
156 def create_tag_txn(): |
73 new_tag = cls(key_name=tag_key_name, tag=tag_name, scope=program) |
157 new_tag = cls(key_name=tag_key_name, tag=tag_name, |
|
158 scope=scope, order=order) |
74 new_tag.put() |
159 new_tag.put() |
75 return new_tag |
160 return new_tag |
76 existing_tag = db.run_in_transaction(create_tag_txn) |
161 existing_tag = db.run_in_transaction(create_tag_txn) |
77 return existing_tag |
162 return existing_tag |
78 |
163 |
115 difficulty = tag_property('difficulty') |
207 difficulty = tag_property('difficulty') |
116 |
208 |
117 #: Required field which contains the type of the task. These types are |
209 #: Required field which contains the type of the task. These types are |
118 #: configured by a Program Admin. |
210 #: configured by a Program Admin. |
119 task_type = tag_property('task_type') |
211 task_type = tag_property('task_type') |
|
212 |
|
213 #: Field which contains the arbitrary tags for the task. These tags can |
|
214 #: be assigned by Org Admins and mentors. |
|
215 arbit_tag = tag_property('arbit_tag') |
120 |
216 |
121 #: A field which contains time allowed for completing the task (in hours) |
217 #: A field which contains time allowed for completing the task (in hours) |
122 #: from the moment that this task has been assigned to a Student |
218 #: from the moment that this task has been assigned to a Student |
123 time_to_complete = db.IntegerProperty(required=True, |
219 time_to_complete = db.IntegerProperty(required=True, |
124 verbose_name=('Time to Complete')) |
220 verbose_name=('Time to Complete')) |
241 db.Model.__init__(self, parent, key_name, app, **entity_values) |
337 db.Model.__init__(self, parent, key_name, app, **entity_values) |
242 |
338 |
243 # call the Taggable constructor to initialize the tags specified as |
339 # call the Taggable constructor to initialize the tags specified as |
244 # keyword arguments |
340 # keyword arguments |
245 Taggable.__init__(self, task_type=TaskTypeTag, |
341 Taggable.__init__(self, task_type=TaskTypeTag, |
246 difficulty=TaskDifficultyTag) |
342 difficulty=TaskDifficultyTag, |
247 |
343 arbit_tag=TaskArbitraryTag) |