Bläddra i källkod

massive commit with new design

Damien ACCORSI 9 år sedan
förälder
incheckning
1bb7ca1f42
100 ändrade filer med 7610 tillägg och 649 borttagningar
  1. 34 11
      tracim/tracim/controllers/__init__.py
  2. 25 24
      tracim/tracim/controllers/admin/user.py
  3. 4 5
      tracim/tracim/controllers/admin/workspace.py
  4. 81 50
      tracim/tracim/controllers/content.py
  5. 36 6
      tracim/tracim/controllers/root.py
  6. 17 9
      tracim/tracim/controllers/user.py
  7. 30 18
      tracim/tracim/controllers/workspace.py
  8. Binär
      tracim/tracim/i18n/fr/LC_MESSAGES/tracim.mo
  9. 16 271
      tracim/tracim/i18n/fr/LC_MESSAGES/tracim.po
  10. 62 5
      tracim/tracim/lib/content.py
  11. 19 4
      tracim/tracim/lib/helpers.py
  12. 12 2
      tracim/tracim/lib/workspace.py
  13. 8 0
      tracim/tracim/model/auth.py
  14. 150 37
      tracim/tracim/model/data.py
  15. 147 37
      tracim/tracim/model/serializers.py
  16. 158 9
      tracim/tracim/public/assets/css/dashboard.css
  17. 4 0
      tracim/tracim/public/assets/js/jquery.tablesorter.min.js
  18. Binär
      tracim/tracim/public/assets/jstree/themes/default/32px.png
  19. 37 0
      tracim/tracim/public/assets/jstree/themes/tracim/style.css
  20. 21 0
      tracim/tracim/public/assets/tablesorter/LICENSE
  21. 90 0
      tracim/tracim/public/assets/tablesorter/README.md
  22. 25 0
      tracim/tracim/public/assets/tablesorter/addons/pager/jquery.tablesorter.pager.css
  23. 184 0
      tracim/tracim/public/assets/tablesorter/addons/pager/jquery.tablesorter.pager.js
  24. 26 0
      tracim/tracim/public/assets/tablesorter/bower.json
  25. 26 0
      tracim/tracim/public/assets/tablesorter/build.xml
  26. 41 0
      tracim/tracim/public/assets/tablesorter/changelog
  27. 43 0
      tracim/tracim/public/assets/tablesorter/docs/assets/ajax-content.html
  28. 29 0
      tracim/tracim/public/assets/tablesorter/docs/css/jq.css
  29. 119 0
      tracim/tracim/public/assets/tablesorter/docs/example-ajax.html
  30. 70 0
      tracim/tracim/public/assets/tablesorter/docs/example-attribute-sort.html
  31. 75 0
      tracim/tracim/public/assets/tablesorter/docs/example-empty-table.html
  32. 109 0
      tracim/tracim/public/assets/tablesorter/docs/example-extending-defaults.html
  33. 108 0
      tracim/tracim/public/assets/tablesorter/docs/example-meta-headers.html
  34. 107 0
      tracim/tracim/public/assets/tablesorter/docs/example-meta-parsers.html
  35. 107 0
      tracim/tracim/public/assets/tablesorter/docs/example-meta-sort-list.html
  36. 116 0
      tracim/tracim/public/assets/tablesorter/docs/example-option-debug.html
  37. 106 0
      tracim/tracim/public/assets/tablesorter/docs/example-option-digits.html
  38. 107 0
      tracim/tracim/public/assets/tablesorter/docs/example-option-sort-force.html
  39. 108 0
      tracim/tracim/public/assets/tablesorter/docs/example-option-sort-key.html
  40. 108 0
      tracim/tracim/public/assets/tablesorter/docs/example-option-sort-list.html
  41. 108 0
      tracim/tracim/public/assets/tablesorter/docs/example-option-sort-order.html
  42. 85 0
      tracim/tracim/public/assets/tablesorter/docs/example-option-text-extraction.html
  43. 118 0
      tracim/tracim/public/assets/tablesorter/docs/example-options-headers.html
  44. 329 0
      tracim/tracim/public/assets/tablesorter/docs/example-pager.html
  45. 112 0
      tracim/tracim/public/assets/tablesorter/docs/example-parsers.html
  46. 113 0
      tracim/tracim/public/assets/tablesorter/docs/example-trigger-sort.html
  47. 336 0
      tracim/tracim/public/assets/tablesorter/docs/example-triggers.html
  48. 118 0
      tracim/tracim/public/assets/tablesorter/docs/example-update-cell.html
  49. 383 0
      tracim/tracim/public/assets/tablesorter/docs/example-widgets.html
  50. Binär
      tracim/tracim/public/assets/tablesorter/docs/img/external.png
  51. 577 0
      tracim/tracim/public/assets/tablesorter/docs/index.html
  52. 23 0
      tracim/tracim/public/assets/tablesorter/docs/js/docs.js
  53. 29 0
      tracim/tracim/public/assets/tablesorter/docs/js/examples.js
  54. 154 0
      tracim/tracim/public/assets/tablesorter/jquery-latest.js
  55. 122 0
      tracim/tracim/public/assets/tablesorter/jquery.metadata.js
  56. 1038 0
      tracim/tracim/public/assets/tablesorter/jquery.tablesorter.js
  57. 4 0
      tracim/tracim/public/assets/tablesorter/jquery.tablesorter.min.js
  58. 27 0
      tracim/tracim/public/assets/tablesorter/package.json
  59. Binär
      tracim/tracim/public/assets/tablesorter/themes/blue/asc.gif
  60. Binär
      tracim/tracim/public/assets/tablesorter/themes/blue/bg.gif
  61. Binär
      tracim/tracim/public/assets/tablesorter/themes/blue/blue.zip
  62. Binär
      tracim/tracim/public/assets/tablesorter/themes/blue/desc.gif
  63. 39 0
      tracim/tracim/public/assets/tablesorter/themes/blue/style.css
  64. Binär
      tracim/tracim/public/assets/tablesorter/themes/green/asc.png
  65. Binär
      tracim/tracim/public/assets/tablesorter/themes/green/bg.png
  66. Binär
      tracim/tracim/public/assets/tablesorter/themes/green/desc.png
  67. Binär
      tracim/tracim/public/assets/tablesorter/themes/green/green.zip
  68. 39 0
      tracim/tracim/public/assets/tablesorter/themes/green/style.css
  69. Binär
      tracim/tracim/public/assets/tablesorter/themes/tracim/asc.gif
  70. Binär
      tracim/tracim/public/assets/tablesorter/themes/tracim/bg.gif
  71. Binär
      tracim/tracim/public/assets/tablesorter/themes/tracim/desc.gif
  72. 21 0
      tracim/tracim/public/assets/tablesorter/themes/tracim/style.css
  73. 63 0
      tracim/tracim/public/mail.html
  74. 0 0
      tracim/tracim/templates/admin/__init__.py
  75. 7 0
      tracim/tracim/templates/admin/user_edit.mak
  76. 43 30
      tracim/tracim/templates/admin/user_getall.mak
  77. 110 0
      tracim/tracim/templates/admin/user_getone.mak
  78. 6 0
      tracim/tracim/templates/admin/user_password_edit.mak
  79. 26 16
      tracim/tracim/templates/admin/workspace_getall.mak
  80. 133 0
      tracim/tracim/templates/admin/workspace_getone.mak
  81. 0 45
      tracim/tracim/templates/dashboard.mak
  82. 0 0
      tracim/tracim/templates/file/__init__.py
  83. 0 0
      tracim/tracim/templates/file/edit.mak
  84. 56 0
      tracim/tracim/templates/file/forms.mak
  85. 184 0
      tracim/tracim/templates/file/getone.mak
  86. 5 0
      tracim/tracim/templates/file/new.mak
  87. 7 4
      tracim/tracim/templates/file/toolbar.mak
  88. 0 0
      tracim/tracim/templates/folder/__init__.py
  89. 0 1
      tracim/tracim/templates/folder/edit.mak
  90. 82 0
      tracim/tracim/templates/folder/forms.mak
  91. 177 0
      tracim/tracim/templates/folder/getone.mak
  92. 2 2
      tracim/tracim/templates/folder/move.mak
  93. 6 0
      tracim/tracim/templates/folder/new.mak
  94. 24 4
      tracim/tracim/templates/folder/toolbar.mak
  95. 173 0
      tracim/tracim/templates/home.mak
  96. 0 1
      tracim/tracim/templates/master_anonymous.mak
  97. 53 44
      tracim/tracim/templates/master_authenticated.mak
  98. 98 0
      tracim/tracim/templates/master_authenticated_left_treeview.mak
  99. 15 14
      tracim/tracim/templates/master_authenticated_left_treeview_right_toolbar.mak
  100. 0 0
      tracim/tracim/templates/page/__init__.py

+ 34 - 11
tracim/tracim/controllers/__init__.py Visa fil

115
         so that the object is available in any controller method
115
         so that the object is available in any controller method
116
     """
116
     """
117
 
117
 
118
+    TEMPLATE_NEW = 'unknown "template new"'
119
+    TEMPLATE_EDIT = 'unknown "template edit"'
120
+
118
     def _before(self, *args, **kw):
121
     def _before(self, *args, **kw):
119
         """
122
         """
120
         Instantiate the current workspace in tg.tmpl_context
123
         Instantiate the current workspace in tg.tmpl_context
135
         """
138
         """
136
         return ContentApi(tmpl_context.current_user).build_breadcrumb(tmpl_context.workspace, item_id)
139
         return ContentApi(tmpl_context.current_user).build_breadcrumb(tmpl_context.workspace, item_id)
137
 
140
 
141
+    def _struct_new_serialized(self, workspace_id, parent_id):
142
+        print('values are: ', workspace_id, parent_id)
143
+        result = DictLikeClass(
144
+            item=DictLikeClass(parent=DictLikeClass(id=parent_id),
145
+                               workspace=DictLikeClass(id=workspace_id)))
146
+
147
+        return result
148
+
149
+    @tg.require(current_user_is_contributor())
150
+    @tg.expose()
151
+    def new(self, parent_id=None, workspace_id=None):
152
+        """ Show the add form """
153
+        tg.override_template(self.new, self.TEMPLATE_NEW)
154
+
155
+        workspace_id = tg.request.GET['workspace_id']
156
+        parent_id = tg.request.GET['parent_id'] if 'parent_id' in tg.request.GET else None
157
+
158
+        return DictLikeClass(result=self._struct_new_serialized(workspace_id, parent_id))
159
+
138
 
160
 
139
 class TIMWorkspaceContentRestController(TIMRestControllerWithBreadcrumb):
161
 class TIMWorkspaceContentRestController(TIMRestControllerWithBreadcrumb):
140
     """
162
     """
197
         """
219
         """
198
         raise NotImplementedError('You must implement this method in child controllers')
220
         raise NotImplementedError('You must implement this method in child controllers')
199
 
221
 
200
-
201
-    @property
202
-    def _edit_template(self) -> str:
222
+    @tg.require(current_user_is_contributor())
223
+    @tg.expose()
224
+    def new(self, parent_id=None, workspace_id=None):
225
+        """ Show the add form
226
+         Note: parent is the /folders/{parent_id} value
227
+         When refactoring urls, this may be need somme update
203
         """
228
         """
204
-        dotted path to the template used for edit form.
205
-        This path must include the engine (mako, genshi...)
206
-        like it is explained in the override_template() function documentation
229
+        tg.override_template(self.new, self.TEMPLATE_NEW)
207
 
230
 
208
-        example: mako:tracim.templates.user_workspace_folder_page_edit
209
-        """
210
-        raise NotImplementedError('You must implement this method in child controllers')
231
+        workspace_id = tg.request.GET['workspace_id']
232
+        parent_id = tg.request.GET['parent_id'] if 'parent_id' in tg.request.GET else None
233
+
234
+        return DictLikeClass(result=self._struct_new_serialized(workspace_id, parent_id))
211
 
235
 
212
     @tg.require(current_user_is_contributor())
236
     @tg.require(current_user_is_contributor())
213
     @tg.expose()
237
     @tg.expose()
220
         """
244
         """
221
 
245
 
222
         # the follwing line allow to define the template to use in child classes.
246
         # the follwing line allow to define the template to use in child classes.
223
-        tg.override_template(self.edit, self._edit_template)
247
+        tg.override_template(self.edit, self.TEMPLATE_EDIT)
224
 
248
 
225
         item_id = int(item_id)
249
         item_id = int(item_id)
226
         user = tmpl_context.current_user
250
         user = tmpl_context.current_user
232
         dictified_item = Context(self._get_one_context).toDict(item, 'item')
256
         dictified_item = Context(self._get_one_context).toDict(item, 'item')
233
         return DictLikeClass(result = dictified_item)
257
         return DictLikeClass(result = dictified_item)
234
 
258
 
235
-
236
     @tg.require(current_user_is_contributor())
259
     @tg.require(current_user_is_contributor())
237
     @tg.expose()
260
     @tg.expose()
238
     def put(self, item_id, label='',content=''):
261
     def put(self, item_id, label='',content=''):

+ 25 - 24
tracim/tracim/controllers/admin/user.py Visa fil

181
         tg.tmpl_context.user = user
181
         tg.tmpl_context.user = user
182
 
182
 
183
 
183
 
184
-    @tg.expose('tracim.templates.user_password_edit')
184
+    @tg.expose('tracim.templates.admin.user_password_edit')
185
     def edit(self):
185
     def edit(self):
186
         current_user = tmpl_context.current_user
186
         current_user = tmpl_context.current_user
187
         api = UserApi(current_user)
187
         api = UserApi(current_user)
189
         return DictLikeClass(result = dictified_user)
189
         return DictLikeClass(result = dictified_user)
190
 
190
 
191
     @tg.expose()
191
     @tg.expose()
192
-    def put(self, current_password, new_password1, new_password2):
192
+    def put(self, new_password1, new_password2, next_url=''):
193
         # FIXME - Manage
193
         # FIXME - Manage
194
         current_user = tmpl_context.current_user
194
         current_user = tmpl_context.current_user
195
         user = tmpl_context.user
195
         user = tmpl_context.user
196
 
196
 
197
-        redirect_url = tg.lurl('/admin/users/{}'.format(user.user_id))
198
-        if current_user.user_id==user.user_id:
199
-            redirect_url = tg.lurl('/admin/users/me')
197
+        if not next_url:
198
+            next_url = tg.lurl('/admin/users/{}'.format(user.user_id))
200
 
199
 
201
-        if not current_password or not new_password1 or not new_password2:
200
+        if not new_password1 or not new_password2:
202
             tg.flash(_('Empty password is not allowed.'), CST.STATUS_ERROR)
201
             tg.flash(_('Empty password is not allowed.'), CST.STATUS_ERROR)
203
-            tg.redirect(redirect_url)
204
-
205
-        if user.validate_password(current_password) is False:
206
-            tg.flash(_('The current password you typed is wrong'))
207
-            tg.redirect(redirect_url)
202
+            tg.redirect(next_url)
208
 
203
 
209
         if new_password1!=new_password2:
204
         if new_password1!=new_password2:
210
             tg.flash(_('New passwords do not match.'), CST.STATUS_ERROR)
205
             tg.flash(_('New passwords do not match.'), CST.STATUS_ERROR)
211
-            tg.redirect(redirect_url)
206
+            tg.redirect(next_url)
212
 
207
 
213
         user.password = new_password1
208
         user.password = new_password1
214
         pm.DBSession.flush()
209
         pm.DBSession.flush()
215
 
210
 
216
-        tg.flash(_('Your password has been changed'), CST.STATUS_OK)
217
-        tg.redirect(redirect_url)
211
+        tg.flash(_('The password has been changed'), CST.STATUS_OK)
212
+        tg.redirect(next_url)
218
 
213
 
219
 
214
 
220
 class UserRestController(TIMRestController):
215
 class UserRestController(TIMRestController):
232
 
227
 
233
 
228
 
234
     @tg.require(predicates.in_group(Group.TIM_MANAGER_GROUPNAME))
229
     @tg.require(predicates.in_group(Group.TIM_MANAGER_GROUPNAME))
235
-    @tg.expose('tracim.templates.user_get_all')
230
+    @tg.expose('tracim.templates.admin.user_getall')
236
     def get_all(self, *args, **kw):
231
     def get_all(self, *args, **kw):
237
         current_user = tmpl_context.current_user
232
         current_user = tmpl_context.current_user
238
         api = UserApi(current_user)
233
         api = UserApi(current_user)
285
         tg.redirect(self.url())
280
         tg.redirect(self.url())
286
 
281
 
287
 
282
 
288
-    @tg.expose('tracim.templates.user_get_one')
283
+    @tg.expose('tracim.templates.admin.user_getone')
289
     def get_one(self, user_id):
284
     def get_one(self, user_id):
290
         current_user = tmpl_context.current_user
285
         current_user = tmpl_context.current_user
291
         api = UserApi(current_user )
286
         api = UserApi(current_user )
302
         return DictLikeClass(result = dictified_user, fake_api=fake_api)
297
         return DictLikeClass(result = dictified_user, fake_api=fake_api)
303
 
298
 
304
 
299
 
305
-    @tg.expose('tracim.templates.user_edit')
300
+    @tg.expose('tracim.templates.admin.user_edit')
306
     def edit(self, id):
301
     def edit(self, id):
307
         current_user = tmpl_context.current_user
302
         current_user = tmpl_context.current_user
308
         api = UserApi(current_user)
303
         api = UserApi(current_user)
313
         return DictLikeClass(result = dictified_user)
308
         return DictLikeClass(result = dictified_user)
314
 
309
 
315
     @tg.require(predicates.in_group(Group.TIM_MANAGER_GROUPNAME))
310
     @tg.require(predicates.in_group(Group.TIM_MANAGER_GROUPNAME))
316
-    @tg.expose('tracim.templates.workspace_edit')
317
-    def put(self, user_id, name, email):
311
+    @tg.expose()
312
+    def put(self, user_id, name, email, next_url=''):
318
         api = UserApi(tmpl_context.current_user)
313
         api = UserApi(tmpl_context.current_user)
319
 
314
 
320
         user = api.get_one(int(user_id))
315
         user = api.get_one(int(user_id))
321
         api.update(user, name, email, True)
316
         api.update(user, name, email, True)
322
 
317
 
323
         tg.flash(_('User {} updated.').format(user.get_display_name()), CST.STATUS_OK)
318
         tg.flash(_('User {} updated.').format(user.get_display_name()), CST.STATUS_OK)
319
+        if next_url:
320
+            tg.redirect(next_url)
324
         tg.redirect(self.url())
321
         tg.redirect(self.url())
325
-        return
322
+
326
 
323
 
327
     @tg.require(predicates.in_group(Group.TIM_ADMIN_GROUPNAME))
324
     @tg.require(predicates.in_group(Group.TIM_ADMIN_GROUPNAME))
328
     @tg.expose()
325
     @tg.expose()
329
-    def enable(self, id):
326
+    def enable(self, id, next_url=None):
330
         current_user = tmpl_context.current_user
327
         current_user = tmpl_context.current_user
331
         api = UserApi(current_user)
328
         api = UserApi(current_user)
332
 
329
 
334
         user.is_active = True
331
         user.is_active = True
335
         api.save(user)
332
         api.save(user)
336
 
333
 
337
-        tg.flash(_('User {} activated.').format(user.get_display_name()), CST.STATUS_OK)
334
+        tg.flash(_('User {} enabled.').format(user.get_display_name()), CST.STATUS_OK)
335
+        if next_url=='user':
336
+            tg.redirect(self.url(id=user.user_id))
338
         tg.redirect(self.url())
337
         tg.redirect(self.url())
339
 
338
 
340
     @tg.require(predicates.in_group(Group.TIM_ADMIN_GROUPNAME))
339
     @tg.require(predicates.in_group(Group.TIM_ADMIN_GROUPNAME))
341
     @tg.expose()
340
     @tg.expose()
342
-    def disable(self, id):
341
+    def disable(self, id, next_url=None):
343
         id = int(id)
342
         id = int(id)
344
         current_user = tmpl_context.current_user
343
         current_user = tmpl_context.current_user
345
         api = UserApi(current_user)
344
         api = UserApi(current_user)
350
             user = api.get_one(id)
349
             user = api.get_one(id)
351
             user.is_active = False
350
             user.is_active = False
352
             api.save(user)
351
             api.save(user)
353
-            tg.flash(_('User {} desactivated').format(user.get_display_name()), CST.STATUS_OK)
352
+            tg.flash(_('User {} disabled').format(user.get_display_name()), CST.STATUS_OK)
354
 
353
 
354
+        if next_url=='user':
355
+            tg.redirect(self.url(id=user.user_id))
355
         tg.redirect(self.url())
356
         tg.redirect(self.url())
356
 
357
 
357
 
358
 

+ 4 - 5
tracim/tracim/controllers/admin/workspace.py Visa fil

114
 
114
 
115
         tg.redirect(self.parent_controller.url(tg.tmpl_context.workspace_id))
115
         tg.redirect(self.parent_controller.url(tg.tmpl_context.workspace_id))
116
 
116
 
117
-
118
     @tg.expose()
117
     @tg.expose()
119
     def change(self, user_id, new_role):
118
     def change(self, user_id, new_role):
120
         # FIXME CHECK RIGHTS
119
         # FIXME CHECK RIGHTS
158
     def current_item_id_key_in_context(cls):
157
     def current_item_id_key_in_context(cls):
159
         return 'workspace_id'
158
         return 'workspace_id'
160
 
159
 
161
-    @tg.expose('tracim.templates.workspace_get_all')
160
+    @tg.expose('tracim.templates.admin.workspace_getall')
162
     def get_all(self, *args, **kw):
161
     def get_all(self, *args, **kw):
163
 
162
 
164
         user = tmpl_context.current_user
163
         user = tmpl_context.current_user
172
         dictified_workspaces = Context(CTX.ADMIN_WORKSPACES).toDict(workspaces, 'workspaces', 'workspace_nb')
171
         dictified_workspaces = Context(CTX.ADMIN_WORKSPACES).toDict(workspaces, 'workspaces', 'workspace_nb')
173
         return DictLikeClass(result = dictified_workspaces, fake_api=fake_api)
172
         return DictLikeClass(result = dictified_workspaces, fake_api=fake_api)
174
 
173
 
175
-    @tg.expose('tracim.templates.workspace_get_one')
174
+    @tg.expose('tracim.templates.admin.workspace_getone')
176
     def get_one(self, workspace_id):
175
     def get_one(self, workspace_id):
177
         user = tmpl_context.current_user
176
         user = tmpl_context.current_user
178
         workspace_api_controller = WorkspaceApi(user)
177
         workspace_api_controller = WorkspaceApi(user)
203
         tg.redirect(self.url())
202
         tg.redirect(self.url())
204
         return
203
         return
205
 
204
 
206
-    @tg.expose('tracim.templates.workspace_edit')
205
+    @tg.expose('tracim.templates.workspace.edit')
207
     def edit(self, id):
206
     def edit(self, id):
208
         user = tmpl_context.current_user
207
         user = tmpl_context.current_user
209
         workspace_api_controller = WorkspaceApi(user)
208
         workspace_api_controller = WorkspaceApi(user)
213
         dictified_workspace = Context(CTX.ADMIN_WORKSPACE).toDict(workspace, 'workspace')
212
         dictified_workspace = Context(CTX.ADMIN_WORKSPACE).toDict(workspace, 'workspace')
214
         return DictLikeClass(result = dictified_workspace)
213
         return DictLikeClass(result = dictified_workspace)
215
 
214
 
216
-    @tg.expose('tracim.templates.workspace_edit')
215
+    @tg.expose('tracim.templates.workspace.edit')
217
     def put(self, id, name, description):
216
     def put(self, id, name, description):
218
         user = tmpl_context.current_user
217
         user = tmpl_context.current_user
219
         workspace_api_controller = WorkspaceApi(user)
218
         workspace_api_controller = WorkspaceApi(user)

+ 81 - 50
tracim/tracim/controllers/content.py Visa fil

30
 from tracim.model.data import ActionDescription
30
 from tracim.model.data import ActionDescription
31
 from tracim.model.data import Content
31
 from tracim.model.data import Content
32
 from tracim.model.data import ContentType
32
 from tracim.model.data import ContentType
33
+from tracim.model.data import UserRoleInWorkspace
33
 from tracim.model.data import Workspace
34
 from tracim.model.data import Workspace
34
 
35
 
35
 class UserWorkspaceFolderThreadCommentRestController(TIMRestController):
36
 class UserWorkspaceFolderThreadCommentRestController(TIMRestController):
136
     manage a path like this: /workspaces/1/folders/XXX/files/4
137
     manage a path like this: /workspaces/1/folders/XXX/files/4
137
     """
138
     """
138
 
139
 
140
+    TEMPLATE_NEW = 'mako:tracim.templates.file.new'
141
+    TEMPLATE_EDIT = 'mako:tracim.templates.file.edit'
142
+
139
     @property
143
     @property
140
     def _std_url(self):
144
     def _std_url(self):
141
         return tg.url('/workspaces/{}/folders/{}/files/{}')
145
         return tg.url('/workspaces/{}/folders/{}/files/{}')
160
     def _get_all_context(self) -> str:
164
     def _get_all_context(self) -> str:
161
         return CTX.FILES
165
         return CTX.FILES
162
 
166
 
163
-    @property
164
-    def _edit_template(self) -> str:
165
-        return 'mako:tracim.templates.user_workspace_folder_file_edit'
166
-
167
-
168
     @tg.require(current_user_is_reader())
167
     @tg.require(current_user_is_reader())
169
-    @tg.expose('tracim.templates.user_workspace_folder_file_get_one')
168
+    @tg.expose('tracim.templates.file.getone')
170
     def get_one(self, file_id, revision_id=None):
169
     def get_one(self, file_id, revision_id=None):
171
         file_id = int(file_id)
170
         file_id = int(file_id)
172
         user = tmpl_context.current_user
171
         user = tmpl_context.current_user
324
     manage a path like this: /workspaces/1/folders/XXX/pages/4
323
     manage a path like this: /workspaces/1/folders/XXX/pages/4
325
     """
324
     """
326
 
325
 
326
+    TEMPLATE_NEW = 'mako:tracim.templates.page.new'
327
+    TEMPLATE_EDIT = 'mako:tracim.templates.page.edit'
328
+
327
     @property
329
     @property
328
     def _std_url(self):
330
     def _std_url(self):
329
         return tg.url('/workspaces/{}/folders/{}/pages/{}')
331
         return tg.url('/workspaces/{}/folders/{}/pages/{}')
348
     def _get_all_context(self) -> str:
350
     def _get_all_context(self) -> str:
349
         return CTX.PAGES
351
         return CTX.PAGES
350
 
352
 
351
-    @property
352
-    def _edit_template(self) -> str:
353
-        return 'mako:tracim.templates.user_workspace_folder_page_edit'
354
-
355
-
356
     @tg.require(current_user_is_reader())
353
     @tg.require(current_user_is_reader())
357
-    @tg.expose('tracim.templates.user_workspace_folder_page_get_one')
354
+    @tg.expose('tracim.templates.page.getone')
358
     def get_one(self, page_id, revision_id=None):
355
     def get_one(self, page_id, revision_id=None):
359
         page_id = int(page_id)
356
         page_id = int(page_id)
360
         user = tmpl_context.current_user
357
         user = tmpl_context.current_user
442
     """
439
     """
443
     manage a path like this: /workspaces/1/folders/XXX/pages/4
440
     manage a path like this: /workspaces/1/folders/XXX/pages/4
444
     """
441
     """
445
-    comments = UserWorkspaceFolderThreadCommentRestController()
446
 
442
 
443
+    TEMPLATE_NEW = 'mako:tracim.templates.thread.new'
444
+    TEMPLATE_EDIT = 'mako:tracim.templates.thread.edit'
445
+
446
+    comments = UserWorkspaceFolderThreadCommentRestController()
447
 
447
 
448
     def _before(self, *args, **kw):
448
     def _before(self, *args, **kw):
449
         TIMRestPathContextSetup.current_user()
449
         TIMRestPathContextSetup.current_user()
450
         TIMRestPathContextSetup.current_workspace()
450
         TIMRestPathContextSetup.current_workspace()
451
         TIMRestPathContextSetup.current_folder()
451
         TIMRestPathContextSetup.current_folder()
452
 
452
 
453
-
454
     @property
453
     @property
455
     def _std_url(self):
454
     def _std_url(self):
456
         return tg.url('/workspaces/{}/folders/{}/threads/{}')
455
         return tg.url('/workspaces/{}/folders/{}/threads/{}')
457
 
456
 
458
-
459
     @property
457
     @property
460
     def _err_url(self):
458
     def _err_url(self):
461
         return self._std_url
459
         return self._std_url
462
 
460
 
463
-
464
     @property
461
     @property
465
     def _parent_url(self):
462
     def _parent_url(self):
466
         return tg.url('/workspaces/{}/folders/{}')
463
         return tg.url('/workspaces/{}/folders/{}')
467
 
464
 
468
-
469
     @property
465
     @property
470
     def _item_type(self):
466
     def _item_type(self):
471
         return ContentType.Thread
467
         return ContentType.Thread
480
     def _get_one_context(self) -> str:
476
     def _get_one_context(self) -> str:
481
         return CTX.THREAD
477
         return CTX.THREAD
482
 
478
 
483
-
484
     @property
479
     @property
485
     def _get_all_context(self) -> str:
480
     def _get_all_context(self) -> str:
486
         return CTX.THREADS
481
         return CTX.THREADS
487
 
482
 
488
-
489
-    @property
490
-    def _edit_template(self) -> str:
491
-        return 'mako:tracim.templates.user_workspace_folder_thread_edit'
492
-
493
-
494
     @tg.require(current_user_is_contributor())
483
     @tg.require(current_user_is_contributor())
495
     @tg.expose()
484
     @tg.expose()
496
-    def post(self, label='', content=''):
485
+    def post(self, label='', content='', parent_id=None):
497
         """
486
         """
498
         Creates a new thread. Actually, on POST, the content will be included in a user comment instead of being the thread description
487
         Creates a new thread. Actually, on POST, the content will be included in a user comment instead of being the thread description
499
         :param label:
488
         :param label:
520
 
509
 
521
 
510
 
522
     @tg.require(current_user_is_reader())
511
     @tg.require(current_user_is_reader())
523
-    @tg.expose('tracim.templates.user_workspace_folder_thread_get_one')
512
+    @tg.expose('tracim.templates.thread.getone')
524
     def get_one(self, thread_id):
513
     def get_one(self, thread_id):
525
         thread_id = int(thread_id)
514
         thread_id = int(thread_id)
526
         user = tmpl_context.current_user
515
         user = tmpl_context.current_user
556
 
545
 
557
 
546
 
558
     @tg.require(current_user_is_content_manager())
547
     @tg.require(current_user_is_content_manager())
559
-    @tg.expose('tracim.templates.item_location_edit')
548
+    @tg.expose('tracim.templates.folder.move')
560
     def edit(self, item_id):
549
     def edit(self, item_id):
561
         """
550
         """
562
         Show the edit form (do not really edit the data)
551
         Show the edit form (do not really edit the data)
577
         dictified_item = Context(CTX.DEFAULT).toDict(item, 'item')
566
         dictified_item = Context(CTX.DEFAULT).toDict(item, 'item')
578
         return DictLikeClass(result = dictified_item, fake_api=fake_api)
567
         return DictLikeClass(result = dictified_item, fake_api=fake_api)
579
 
568
 
580
-
581
-
582
-
583
-
584
-
585
     @tg.require(current_user_is_content_manager())
569
     @tg.require(current_user_is_content_manager())
586
     @tg.expose()
570
     @tg.expose()
587
     def put(self, item_id, folder_id='0'):
571
     def put(self, item_id, folder_id='0'):
588
         """
572
         """
589
         :param item_id:
573
         :param item_id:
590
-        :param folder_id: id of the folder, in the 'workspace_14__content_1586' style
574
+        :param folder_id: id of the folder, in a style like 'workspace_14__content_1586'
591
         :return:
575
         :return:
592
         """
576
         """
593
         # TODO - SECURE THIS
577
         # TODO - SECURE THIS
595
         item_id = int(item_id)
579
         item_id = int(item_id)
596
         new_workspace, new_parent = convert_id_into_instances(folder_id)
580
         new_workspace, new_parent = convert_id_into_instances(folder_id)
597
 
581
 
598
-        api = ContentApi(tmpl_context.current_user)
599
-        item = api.get_one(item_id, ContentType.Any, workspace)
600
-        api.move(item, new_parent)
601
-        next_url = self.parent_controller.url(item_id)
602
-        if new_parent:
603
-            tg.flash(_('Item moved to {}').format(new_parent.label), CST.STATUS_OK)
582
+        if new_workspace != workspace:
583
+            # check that user is at least
584
+            # - content manager in current workspace
585
+            # - content manager in new workspace
586
+            user = tmpl_context.current_user
587
+
588
+            if user.get_role(workspace) < UserRoleInWorkspace.CONTENT_MANAGER:
589
+                tg.flash(_('You are not allowed '
590
+                           'to move this folder'), CST.STATUS_ERROR)
591
+                tg.redirect(self.parent_controller.url(item_id))
592
+
593
+            if user.get_role(new_workspace) < UserRoleInWorkspace.CONTENT_MANAGER:
594
+                tg.flash(_('You are not allowed to move '
595
+                           'this folder to this workspace'), CST.STATUS_ERROR)
596
+                tg.redirect(self.parent_controller.url(item_id))
597
+
598
+            api = ContentApi(tmpl_context.current_user)
599
+            item = api.get_one(item_id, ContentType.Any, workspace)
600
+            api.move_recursively(item, new_parent, new_workspace)
601
+
602
+            next_url = tg.url('/workspaces/{}/folders/{}'.format(
603
+                new_workspace.workspace_id, item_id))
604
+            if new_parent:
605
+                tg.flash(_('Item moved to {} (workspace {})').format(
606
+                    new_parent.label,
607
+                    new_workspace.label), CST.STATUS_OK)
608
+            else:
609
+                tg.flash(_('Item moved to workspace {}').format(
610
+                    new_workspace.label))
611
+
612
+            tg.redirect(next_url)
613
+
604
         else:
614
         else:
605
-            tg.flash(_('Item moved to workspace root'))
615
+            # Default move inside same workspace
616
+            api = ContentApi(tmpl_context.current_user)
617
+            item = api.get_one(item_id, ContentType.Any, workspace)
618
+            api.move(item, new_parent)
619
+            next_url = self.parent_controller.url(item_id)
620
+            if new_parent:
621
+                tg.flash(_('Item moved to {}').format(new_parent.label), CST.STATUS_OK)
622
+            else:
623
+                tg.flash(_('Item moved to workspace root'))
606
 
624
 
607
-        tg.redirect(next_url)
625
+            tg.redirect(next_url)
608
 
626
 
609
 
627
 
610
 
628
 
611
 class UserWorkspaceFolderRestController(TIMRestControllerWithBreadcrumb):
629
 class UserWorkspaceFolderRestController(TIMRestControllerWithBreadcrumb):
612
 
630
 
631
+    TEMPLATE_NEW = 'mako:tracim.templates.folder.new'
632
+
613
     location = ItemLocationController()
633
     location = ItemLocationController()
614
 
634
 
615
     files = UserWorkspaceFolderFileRestController()
635
     files = UserWorkspaceFolderFileRestController()
622
 
642
 
623
 
643
 
624
     @tg.require(current_user_is_content_manager())
644
     @tg.require(current_user_is_content_manager())
625
-    @tg.expose('tracim.templates.folder_edit')
645
+    @tg.expose('tracim.templates.folder.edit')
626
     def edit(self, folder_id):
646
     def edit(self, folder_id):
627
         """
647
         """
628
         Show the edit form (do not really edit the data)
648
         Show the edit form (do not really edit the data)
643
 
663
 
644
 
664
 
645
     @tg.require(current_user_is_reader())
665
     @tg.require(current_user_is_reader())
646
-    @tg.expose('tracim.templates.user_workspace_folder_get_one')
666
+    @tg.expose('tracim.templates.folder.getone')
647
     def get_one(self, folder_id):
667
     def get_one(self, folder_id):
648
         folder_id = int(folder_id)
668
         folder_id = int(folder_id)
649
         user = tmpl_context.current_user
669
         user = tmpl_context.current_user
663
         fake_api_threads = self.threads.get_all_fake(workspace, folder).result
683
         fake_api_threads = self.threads.get_all_fake(workspace, folder).result
664
 
684
 
665
         fake_api_content = DictLikeClass(
685
         fake_api_content = DictLikeClass(
666
-            current_user = current_user_content,
667
-            breadcrumb = fake_api_breadcrumb,
668
-            current_folder_subfolders = fake_api_subfolders,
669
-            current_folder_pages = fake_api_pages,
670
-            current_folder_files = fake_api_files,
671
-            current_folder_threads = fake_api_threads
686
+            current_user=current_user_content,
687
+            breadcrumb=fake_api_breadcrumb,
688
+            current_folder_subfolders=fake_api_subfolders,
689
+            current_folder_pages=fake_api_pages,
690
+            current_folder_files=fake_api_files,
691
+            current_folder_threads=fake_api_threads,
672
         )
692
         )
693
+
673
         fake_api = Context(CTX.FOLDER).toDict(fake_api_content)
694
         fake_api = Context(CTX.FOLDER).toDict(fake_api_content)
674
 
695
 
696
+        fake_api.sub_items = Context(CTX.FOLDER_CONTENT_LIST).toDict(
697
+            folder.get_valid_children([ContentType.Folder,
698
+                                       ContentType.File,
699
+                                       ContentType.Page,
700
+                                       ContentType.Thread]))
701
+
702
+        fake_api.content_types = Context(CTX.DEFAULT).toDict(
703
+            content_api.get_all_types())
675
 
704
 
676
         dictified_folder = Context(CTX.FOLDER).toDict(folder, 'folder')
705
         dictified_folder = Context(CTX.FOLDER).toDict(folder, 'folder')
677
         return DictLikeClass(result = dictified_folder, fake_api=fake_api)
706
         return DictLikeClass(result = dictified_folder, fake_api=fake_api)
759
                 file = True if can_contain_files=='on' else False,
788
                 file = True if can_contain_files=='on' else False,
760
                 page = True if can_contain_pages=='on' else False
789
                 page = True if can_contain_pages=='on' else False
761
             )
790
             )
762
-            api.update_content(folder, label, folder.description)
791
+            if label != folder.label:
792
+                # TODO - D.A. - 2015-05-25 - Allow to set folder description
793
+                api.update_content(folder, label, folder.description)
763
             api.set_allowed_content(folder, subcontent)
794
             api.set_allowed_content(folder, subcontent)
764
             api.save(folder)
795
             api.save(folder)
765
 
796
 

+ 36 - 6
tracim/tracim/controllers/root.py Visa fil

15
 from tracim.lib import CST
15
 from tracim.lib import CST
16
 from tracim.lib.base import logger
16
 from tracim.lib.base import logger
17
 from tracim.lib.user import UserStaticApi
17
 from tracim.lib.user import UserStaticApi
18
+from tracim.lib.content import ContentApi
18
 
19
 
19
 from tracim.controllers import StandardController
20
 from tracim.controllers import StandardController
20
 from tracim.controllers.admin import AdminController
21
 from tracim.controllers.admin import AdminController
24
 from tracim.controllers.user import UserRestController
25
 from tracim.controllers.user import UserRestController
25
 from tracim.controllers.workspace import UserWorkspaceRestController
26
 from tracim.controllers.workspace import UserWorkspaceRestController
26
 
27
 
28
+from tracim.model.data import ContentType
27
 from tracim.model.serializers import DictLikeClass
29
 from tracim.model.serializers import DictLikeClass
28
 from tracim.model.serializers import CTX
30
 from tracim.model.serializers import CTX
29
 from tracim.model.serializers import Context
31
 from tracim.model.serializers import Context
65
                 logger.info(self, 'Will redirect to {}'.format(came_from))
67
                 logger.info(self, 'Will redirect to {}'.format(came_from))
66
                 redirect(url(came_from))
68
                 redirect(url(came_from))
67
             else:
69
             else:
68
-                redirect(self.url(None, self.dashboard.__name__))
70
+                redirect(self.url(None, self.home.__name__))
69
 
71
 
70
         login_counter = request.environ.get('repoze.who.logins', 0)
72
         login_counter = request.environ.get('repoze.who.logins', 0)
71
         if login_counter > 0:
73
         if login_counter > 0:
90
 
92
 
91
 
93
 
92
     @expose()
94
     @expose()
93
-    def post_login(self, came_from=lurl('/dashboard')):
95
+    def post_login(self, came_from=lurl('/home')):
94
         """
96
         """
95
         Redirect the user to the initially requested page on successful
97
         Redirect the user to the initially requested page on successful
96
         authentication or redirect her back to the login page if login failed.
98
         authentication or redirect her back to the login page if login failed.
115
         
117
         
116
 
118
 
117
     @require(predicates.not_anonymous())
119
     @require(predicates.not_anonymous())
118
-    @expose('tracim.templates.dashboard')
119
-    def dashboard(self):
120
+    @expose('tracim.templates.home')
121
+    def home(self):
120
         user = tmpl_context.current_user
122
         user = tmpl_context.current_user
121
 
123
 
122
         current_user_content = Context(CTX.CURRENT_USER).toDict(user)
124
         current_user_content = Context(CTX.CURRENT_USER).toDict(user)
123
-        fake_api = Context(CTX.CURRENT_USER).toDict({'current_user': current_user_content})
125
+        fake_api = Context(CTX.CURRENT_USER).toDict({
126
+            'current_user': current_user_content})
127
+
128
+
129
+        last_active_contents = ContentApi(user).get_last_active(None, ContentType.Any, None)
130
+        fake_api.last_actives = Context(CTX.CONTENT_LIST).toDict(last_active_contents, 'contents', 'nb')
124
 
131
 
132
+        # INFO - D.A. - 2015-05-20
133
+        # For now, we do not have favorties and read/unread status
134
+        # so we only show:
135
+        # - workspaces
136
+        # - last activity
137
+        # - oldest open stuff
138
+
139
+        items = ContentApi(user).get_all(None, ContentType.Any, None)[:4]
140
+        fake_api.favorites = Context(CTX.CONTENT_LIST).toDict(items, 'contents', 'nb')
125
         return DictLikeClass(fake_api=fake_api)
141
         return DictLikeClass(fake_api=fake_api)
126
 
142
 
143
+        # user_id = tmpl_context.current_user.user_id
144
+        #
145
+        # current_user = tmpl_context.current_user
146
+        # assert user_id==current_user.user_id
147
+        # api = UserApi(current_user)
148
+        # current_user = api.get_one(current_user.user_id)
149
+        # dictified_user = Context(CTX.USER).toDict(current_user, 'user')
150
+        # current_user_content = Context(CTX.CURRENT_USER).toDict(tmpl_context.current_user)
151
+        # fake_api_content = DictLikeClass(current_user=current_user_content)
152
+        # fake_api = Context(CTX.WORKSPACE).toDict(fake_api_content)
153
+        #
154
+        # return DictLikeClass(result = dictified_user, fake_api=fake_api)
155
+
156
+
127
     @require(predicates.not_anonymous())
157
     @require(predicates.not_anonymous())
128
-    @expose('tracim.templates.search')
158
+    @expose('tracim.templates.search.display')
129
     def search(self, keywords = ''):
159
     def search(self, keywords = ''):
130
         from tracim.lib.content import ContentApi
160
         from tracim.lib.content import ContentApi
131
 
161
 

+ 17 - 9
tracim/tracim/controllers/user.py Visa fil

45
         user = tmpl_context.current_user
45
         user = tmpl_context.current_user
46
 
46
 
47
     @tg.expose()
47
     @tg.expose()
48
-    def enable_notifications(self, workspace_id):
48
+    def enable_notifications(self, workspace_id, next_url=None):
49
         workspace_id = int(workspace_id)
49
         workspace_id = int(workspace_id)
50
         api = WorkspaceApi(tg.tmpl_context.current_user)
50
         api = WorkspaceApi(tg.tmpl_context.current_user)
51
 
51
 
52
         workspace = api.get_one(workspace_id)
52
         workspace = api.get_one(workspace_id)
53
         api.enable_notifications(tg.tmpl_context.current_user, workspace)
53
         api.enable_notifications(tg.tmpl_context.current_user, workspace)
54
         tg.flash(_('Notification enabled for workspace {}').format(workspace.label))
54
         tg.flash(_('Notification enabled for workspace {}').format(workspace.label))
55
+
56
+        if next_url:
57
+            tg.redirect(tg.url(next_url))
55
         tg.redirect(self.parent_controller.url(None, 'me'))
58
         tg.redirect(self.parent_controller.url(None, 'me'))
56
 
59
 
57
     @tg.expose()
60
     @tg.expose()
58
-    def disable_notifications(self, workspace_id):
61
+    def disable_notifications(self, workspace_id, next_url=None):
59
         workspace_id = int(workspace_id)
62
         workspace_id = int(workspace_id)
60
         api = WorkspaceApi(tg.tmpl_context.current_user)
63
         api = WorkspaceApi(tg.tmpl_context.current_user)
61
 
64
 
62
         workspace = api.get_one(workspace_id)
65
         workspace = api.get_one(workspace_id)
63
         api.disable_notifications(tg.tmpl_context.current_user, workspace)
66
         api.disable_notifications(tg.tmpl_context.current_user, workspace)
64
         tg.flash(_('Notification disabled for workspace {}').format(workspace.label))
67
         tg.flash(_('Notification disabled for workspace {}').format(workspace.label))
68
+
69
+        if next_url:
70
+            tg.redirect(tg.url(next_url))
65
         tg.redirect(self.parent_controller.url(None, 'me'))
71
         tg.redirect(self.parent_controller.url(None, 'me'))
66
 
72
 
67
 
73
 
95
         # FIXME - Allow only self password or operation for managers
101
         # FIXME - Allow only self password or operation for managers
96
         current_user = tmpl_context.current_user
102
         current_user = tmpl_context.current_user
97
 
103
 
98
-        redirect_url = tg.lurl('/user/me')
104
+        redirect_url = tg.lurl('/home')
99
 
105
 
100
         if not current_password or not new_password1 or not new_password2:
106
         if not current_password or not new_password1 or not new_password2:
101
             tg.flash(_('Empty password is not allowed.'))
107
             tg.flash(_('Empty password is not allowed.'))
150
         fake_api_content = DictLikeClass(current_user=current_user_content)
156
         fake_api_content = DictLikeClass(current_user=current_user_content)
151
         fake_api = Context(CTX.WORKSPACE).toDict(fake_api_content)
157
         fake_api = Context(CTX.WORKSPACE).toDict(fake_api_content)
152
 
158
 
153
-        return DictLikeClass(result = dictified_user, fake_api=fake_api)
159
+        return DictLikeClass(result=dictified_user, fake_api=fake_api)
154
 
160
 
155
     @tg.expose('tracim.templates.user_edit_me')
161
     @tg.expose('tracim.templates.user_edit_me')
156
-    def edit(self, id):
162
+    def edit(self, id, next_url=None):
157
         id = tmpl_context.current_user.user_id
163
         id = tmpl_context.current_user.user_id
158
         current_user = tmpl_context.current_user
164
         current_user = tmpl_context.current_user
159
         assert id==current_user.user_id
165
         assert id==current_user.user_id
160
 
166
 
161
         dictified_user = Context(CTX.USER).toDict(current_user, 'user')
167
         dictified_user = Context(CTX.USER).toDict(current_user, 'user')
162
-        return DictLikeClass(result = dictified_user)
168
+        fake_api = DictLikeClass(next_url=next_url)
169
+        return DictLikeClass(result=dictified_user, fake_api=fake_api)
163
 
170
 
164
-    @tg.expose('tracim.templates.workspace_edit')
165
-    def put(self, user_id, name, email):
171
+    @tg.expose('tracim.templates.workspace.edit')
172
+    def put(self, user_id, name, email, next_url=None):
166
         user_id = tmpl_context.current_user.user_id
173
         user_id = tmpl_context.current_user.user_id
167
         current_user = tmpl_context.current_user
174
         current_user = tmpl_context.current_user
168
         assert user_id==current_user.user_id
175
         assert user_id==current_user.user_id
170
         api = UserApi(tmpl_context.current_user)
177
         api = UserApi(tmpl_context.current_user)
171
         api.update(current_user, name, email, True)
178
         api.update(current_user, name, email, True)
172
         tg.flash(_('profile updated.'))
179
         tg.flash(_('profile updated.'))
180
+        if next_url:
181
+            tg.redirect(tg.url(next_url))
173
         tg.redirect(self.url())
182
         tg.redirect(self.url())
174
-        return

+ 30 - 18
tracim/tracim/controllers/workspace.py Visa fil

37
         return 'workspace_id'
37
         return 'workspace_id'
38
 
38
 
39
 
39
 
40
-    @tg.expose('tracim.templates.user_workspace_get_all')
40
+    @tg.expose()
41
     def get_all(self, *args, **kw):
41
     def get_all(self, *args, **kw):
42
-        user = tmpl_context.current_user
43
-
44
-        current_user_content = Context(CTX.CURRENT_USER).toDict(user)
45
-        current_user_content.roles.sort(key=lambda role: role.workspace.name)
46
-
47
-        workspace_api = WorkspaceApi(user)
48
-        workspaces = workspace_api.get_all_for_user(user)
49
-        fake_api = Context(CTX.CURRENT_USER).toDict({'current_user': current_user_content})
50
-        dictified_workspaces = Context(CTX.ADMIN_WORKSPACES).toDict(workspaces, 'workspaces', 'workspace_nb')
42
+        tg.redirect(tg.url('/home'))
51
 
43
 
52
-        return DictLikeClass(result = dictified_workspaces, fake_api=fake_api)
53
-
54
-    @tg.expose('tracim.templates.user_workspace_get_one')
44
+    @tg.expose('tracim.templates.workspace.getone')
55
     def get_one(self, workspace_id):
45
     def get_one(self, workspace_id):
56
         user = tmpl_context.current_user
46
         user = tmpl_context.current_user
57
 
47
 
63
 
53
 
64
         dictified_current_user = Context(CTX.CURRENT_USER).toDict(user)
54
         dictified_current_user = Context(CTX.CURRENT_USER).toDict(user)
65
         dictified_folders = self.folders.get_all_fake(workspace).result
55
         dictified_folders = self.folders.get_all_fake(workspace).result
66
-        fake_api = DictLikeClass(current_user = dictified_current_user, current_workspace_folders = dictified_folders)
56
+        fake_api = DictLikeClass(current_user=dictified_current_user,
57
+                                 current_workspace_folders=dictified_folders)\
58
+        # ,
59
+        #                      sub_items=Context(CTX.FOLDER_CONTENT_LIST).toDict(dictified_folders))
60
+
61
+        fake_api.sub_items = Context(CTX.FOLDER_CONTENT_LIST).toDict(workspace.get_valid_children())
62
+
67
         dictified_workspace = Context(CTX.WORKSPACE).toDict(workspace, 'workspace')
63
         dictified_workspace = Context(CTX.WORKSPACE).toDict(workspace, 'workspace')
68
 
64
 
69
         return DictLikeClass(result = dictified_workspace, fake_api=fake_api)
65
         return DictLikeClass(result = dictified_workspace, fake_api=fake_api)
70
 
66
 
71
 
67
 
72
     @tg.expose('json')
68
     @tg.expose('json')
73
-    def treeview_root(self, id='#', current_id=None, all_workspaces=True, folder_allowed_content_types='', ignore_id=None):
69
+    def treeview_root(self, id='#',
70
+                      current_id=None,
71
+                      all_workspaces=True,
72
+                      folder_allowed_content_types='',
73
+                      ignore_id=None,
74
+                      ignore_workspace_id=None):
74
         all_workspaces = bool(int(all_workspaces))
75
         all_workspaces = bool(int(all_workspaces))
75
 
76
 
77
+        # ignore_workspace_id is a string like 3,12,78,15
78
+        ignored_ids = [int(id) for id in ignore_workspace_id.split(',')] if ignore_workspace_id else None
79
+
76
         if not current_id:
80
         if not current_id:
77
             # Default case is to return list of workspaces
81
             # Default case is to return list of workspaces
82
+            print('ignore : ', ignored_ids)
78
             api = WorkspaceApi(tmpl_context.current_user)
83
             api = WorkspaceApi(tmpl_context.current_user)
79
-            workspaces = api.get_all_for_user(tmpl_context.current_user)
84
+            workspaces = api.get_all_for_user(tmpl_context.current_user,
85
+                                              ignored_ids)
80
             dictified_workspaces = Context(CTX.MENU_API).toDict(workspaces, 'd')
86
             dictified_workspaces = Context(CTX.MENU_API).toDict(workspaces, 'd')
81
             return dictified_workspaces
87
             return dictified_workspaces
82
 
88
 
179
 
185
 
180
 
186
 
181
     @tg.expose('json')
187
     @tg.expose('json')
182
-    def treeview_children(self, id='#', ignore_id=None):
188
+    def treeview_children(self, id='#',
189
+                          ignore_id=None,
190
+                          allowed_content_types = None):
183
         """
191
         """
184
         id must be "#" or something like "workspace_3__document_8"
192
         id must be "#" or something like "workspace_3__document_8"
185
         """
193
         """
189
         ignore_item_ids = [int(ignore_id)] if ignore_id else []
197
         ignore_item_ids = [int(ignore_id)] if ignore_id else []
190
         workspace, content = convert_id_into_instances(id)
198
         workspace, content = convert_id_into_instances(id)
191
 
199
 
192
-        viewable_content_types = self._get_treeviewable_content_types_or_none()
200
+        viewable_content_types = []
201
+        if allowed_content_types:
202
+            viewable_content_types = allowed_content_types.split(',')
203
+        else:
204
+            viewable_content_types = self._get_treeviewable_content_types_or_none()
193
         contents = ContentApi(tmpl_context.current_user).get_child_folders(content, workspace, [], ignore_item_ids, viewable_content_types)
205
         contents = ContentApi(tmpl_context.current_user).get_child_folders(content, workspace, [], ignore_item_ids, viewable_content_types)
194
         # This allow to show contents and folders group by type
206
         # This allow to show contents and folders group by type
195
         sorted_contents = ContentApi.sort_content(contents)
207
         sorted_contents = ContentApi.sort_content(contents)

Binär
tracim/tracim/i18n/fr/LC_MESSAGES/tracim.mo Visa fil


+ 16 - 271
tracim/tracim/i18n/fr/LC_MESSAGES/tracim.po Visa fil

7
 msgstr ""
7
 msgstr ""
8
 "Project-Id-Version: pod 0.1\n"
8
 "Project-Id-Version: pod 0.1\n"
9
 "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
9
 "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
10
-<<<<<<< HEAD
11
-<<<<<<< HEAD
12
-<<<<<<< HEAD
13
-<<<<<<< HEAD
14
-"POT-Creation-Date: 2015-03-02 22:28+0100\n"
15
-"PO-Revision-Date: 2015-03-02 22:32+0100\n"
16
-=======
17
-"POT-Creation-Date: 2015-03-09 16:56+0100\n"
18
-"PO-Revision-Date: 2015-03-09 17:00+0100\n"
19
->>>>>>> b2e4664ae2ad0cc8fbc3344f6fa37845cf7e344d
20
-=======
21
-"POT-Creation-Date: 2015-03-10 18:35+0100\n"
22
-"PO-Revision-Date: 2015-03-10 18:32+0100\n"
23
->>>>>>> 139e854c54cbb438fb69dda1149d450228cf2e8a
24
-=======
25
-"POT-Creation-Date: 2015-03-10 18:35+0100\n"
26
-"PO-Revision-Date: 2015-03-10 18:32+0100\n"
27
->>>>>>> 139e854c54cbb438fb69dda1149d450228cf2e8a
28
-=======
29
-"POT-Creation-Date: 2015-03-20 00:44+0100\n"
10
+"POT-Creation-Date: 2015-03-25 12:53+0100\n"
30
 "PO-Revision-Date: 2015-03-20 00:37+0100\n"
11
 "PO-Revision-Date: 2015-03-20 00:37+0100\n"
31
->>>>>>> b67ad8598a3cfae087b99a8b7bf905ae8b8ec991
32
 "Last-Translator: Damien Accorsi <damien.accorsi@free.fr>\n"
12
 "Last-Translator: Damien Accorsi <damien.accorsi@free.fr>\n"
33
 "Language-Team: fr_FR <LL@li.org>\n"
13
 "Language-Team: fr_FR <LL@li.org>\n"
34
 "Plural-Forms: nplurals=2; plural=(n > 1)\n"
14
 "Plural-Forms: nplurals=2; plural=(n > 1)\n"
101
 msgid "Password changed successfully"
81
 msgid "Password changed successfully"
102
 msgstr "Mot de passe changé"
82
 msgstr "Mot de passe changé"
103
 
83
 
104
-<<<<<<< HEAD
105
-<<<<<<< HEAD
106
-<<<<<<< HEAD
107
-<<<<<<< HEAD
108
-#: tracim/controllers/__init__.py:139
109
-#: tracim/templates/dashboard.mak:36
110
-#: tracim/templates/master_authenticated.mak:94
111
-#: tracim/templates/master_no_toolbar_no_login.mak:112
112
-#: tracim/templates/user_get_one.mak:42
113
-#: tracim/templates/user_profile.mak:39
114
-#: tracim/templates/user_workspace_folder_file_get_one.mak:10
115
-#: tracim/templates/user_workspace_folder_get_one.mak:11
116
-#: tracim/templates/user_workspace_folder_page_get_one.mak:11
117
-#: tracim/templates/user_workspace_folder_thread_get_one.mak:11
118
-#: tracim/templates/user_workspace_get_all.mak:11
119
-#: tracim/templates/user_workspace_get_one.mak:11
120
-#: tracim/templates/workspace_get_all.mak:13
121
-msgid "Workspaces"
122
-msgstr "Espaces de travail"
123
-
124
-#: tracim/controllers/__init__.py:274
125
-=======
126
-#: tracim/controllers/__init__.py:247
127
->>>>>>> b2e4664ae2ad0cc8fbc3344f6fa37845cf7e344d
128
-#: tracim/controllers/content.py:283
129
-msgid "{} updated"
130
-msgstr "{} mis(e) à jour"
131
-
132
-<<<<<<< HEAD
133
-#: tracim/controllers/__init__.py:279
134
-=======
135
-#: tracim/controllers/__init__.py:252
136
->>>>>>> b2e4664ae2ad0cc8fbc3344f6fa37845cf7e344d
137
-#: tracim/controllers/content.py:288
138
-=======
139
-#: tracim/controllers/__init__.py:247 tracim/controllers/content.py:283
140
-msgid "{} updated"
141
-msgstr "{} mis(e) à jour"
142
-
143
-#: tracim/controllers/__init__.py:252 tracim/controllers/content.py:288
144
->>>>>>> 139e854c54cbb438fb69dda1149d450228cf2e8a
145
-=======
146
-#: tracim/controllers/__init__.py:247 tracim/controllers/content.py:283
147
-msgid "{} updated"
148
-msgstr "{} mis(e) à jour"
149
-
150
-#: tracim/controllers/__init__.py:252 tracim/controllers/content.py:288
151
->>>>>>> 139e854c54cbb438fb69dda1149d450228cf2e8a
152
-=======
153
 #: tracim/controllers/__init__.py:247 tracim/controllers/content.py:310
84
 #: tracim/controllers/__init__.py:247 tracim/controllers/content.py:310
154
 #: tracim/controllers/content.py:425
85
 #: tracim/controllers/content.py:425
155
 msgid "{} updated"
86
 msgid "{} updated"
157
 
88
 
158
 #: tracim/controllers/__init__.py:252 tracim/controllers/content.py:315
89
 #: tracim/controllers/__init__.py:252 tracim/controllers/content.py:315
159
 #: tracim/controllers/content.py:430
90
 #: tracim/controllers/content.py:430
160
->>>>>>> b67ad8598a3cfae087b99a8b7bf905ae8b8ec991
161
 msgid "{} not updated - error: {}"
91
 msgid "{} not updated - error: {}"
162
 msgstr "{} pas mis(e) à jour - erreur : {}"
92
 msgstr "{} pas mis(e) à jour - erreur : {}"
163
 
93
 
164
-<<<<<<< HEAD
165
-#: tracim/controllers/__init__.py:293
166
-msgid "{} status updated"
167
-msgstr "Statut de {} mis(e) à jour"
168
-
169
-#: tracim/controllers/__init__.py:297
170
-msgid "{} status not updated: {}"
171
-msgstr "Statut de {} non mis(e) à jour : {}"
172
-
173
-#: tracim/controllers/__init__.py:329
174
-=======
175
 #: tracim/controllers/__init__.py:266
94
 #: tracim/controllers/__init__.py:266
176
 msgid "{} status updated"
95
 msgid "{} status updated"
177
 msgstr "Statut de {} mis(e) à jour"
96
 msgstr "Statut de {} mis(e) à jour"
180
 msgid "{} status not updated: {}"
99
 msgid "{} status not updated: {}"
181
 msgstr "Statut de {} non mis(e) à jour : {}"
100
 msgstr "Statut de {} non mis(e) à jour : {}"
182
 
101
 
183
-<<<<<<< HEAD
184
-<<<<<<< HEAD
185
-<<<<<<< HEAD
186
-#: tracim/controllers/__init__.py:302
187
->>>>>>> b2e4664ae2ad0cc8fbc3344f6fa37845cf7e344d
188
-#: tracim/controllers/content.py:748
189
-msgid "{} archived. <a class=\"alert-link\" href=\"{}\">Cancel action</a>"
190
-msgstr "{} archivé(e). <a class=\"alert-link\" href=\"{}\">Annuler l'opération</a>"
191
-
192
-<<<<<<< HEAD
193
-#: tracim/controllers/__init__.py:338
194
-=======
195
-#: tracim/controllers/__init__.py:311
196
->>>>>>> b2e4664ae2ad0cc8fbc3344f6fa37845cf7e344d
197
-#: tracim/controllers/content.py:757
198
-msgid "{} not archived: {}"
199
-msgstr "{} non archivé(e) : {}"
200
-
201
-<<<<<<< HEAD
202
-#: tracim/controllers/__init__.py:352
203
-#: tracim/controllers/content.py:772
204
-msgid "{} unarchived."
205
-msgstr "{} désarchivé(e)"
206
-
207
-#: tracim/controllers/__init__.py:360
208
-#: tracim/controllers/content.py:780
209
-msgid "{} not un-archived: {}"
210
-msgstr "{} non désarchivé(e) : {}"
211
-
212
-#: tracim/controllers/__init__.py:378
213
-#: tracim/controllers/content.py:88
214
-#: tracim/controllers/content.py:797
215
-=======
216
-#: tracim/controllers/__init__.py:302 tracim/controllers/content.py:748
217
-=======
218
 #: tracim/controllers/__init__.py:302 tracim/controllers/content.py:798
102
 #: tracim/controllers/__init__.py:302 tracim/controllers/content.py:798
219
->>>>>>> b67ad8598a3cfae087b99a8b7bf905ae8b8ec991
220
 msgid "{} archived. <a class=\"alert-link\" href=\"{}\">Cancel action</a>"
103
 msgid "{} archived. <a class=\"alert-link\" href=\"{}\">Cancel action</a>"
221
 msgstr "{} archivé(e). <a class=\"alert-link\" href=\"{}\">Annuler l'opération</a>"
104
 msgstr "{} archivé(e). <a class=\"alert-link\" href=\"{}\">Annuler l'opération</a>"
222
 
105
 
233
 msgstr "{} non désarchivé(e) : {}"
116
 msgstr "{} non désarchivé(e) : {}"
234
 
117
 
235
 #: tracim/controllers/__init__.py:351 tracim/controllers/content.py:88
118
 #: tracim/controllers/__init__.py:351 tracim/controllers/content.py:88
236
-<<<<<<< HEAD
237
-#: tracim/controllers/content.py:796
238
->>>>>>> 139e854c54cbb438fb69dda1149d450228cf2e8a
239
-msgid "{} deleted. <a class=\"alert-link\" href=\"{}\">Cancel action</a>"
240
-msgstr ""
241
-"{} supprimé(e). <a class=\"alert-link\" href=\"{}\">Annuler "
242
-"l'opération</a>"
243
-
244
-<<<<<<< HEAD
245
-#: tracim/controllers/__init__.py:387
246
-#: tracim/controllers/content.py:99
247
-#: tracim/controllers/content.py:806
248
-msgid "{} not deleted: {}"
249
-msgstr "{} non supprimé(e) : {}"
250
-
251
-#: tracim/controllers/__init__.py:402
252
-#: tracim/controllers/content.py:116
253
-#: tracim/controllers/content.py:821
254
-msgid "{} undeleted."
255
-msgstr "{} restauré(e)."
256
-
257
-#: tracim/controllers/__init__.py:412
258
-#: tracim/controllers/content.py:128
259
-#: tracim/controllers/content.py:831
260
-=======
261
-#: tracim/controllers/__init__.py:325
262
-#: tracim/controllers/content.py:771
263
-=======
264
-#: tracim/controllers/__init__.py:302 tracim/controllers/content.py:748
265
-msgid "{} archived. <a class=\"alert-link\" href=\"{}\">Cancel action</a>"
266
-msgstr "{} archivé(e). <a class=\"alert-link\" href=\"{}\">Annuler l'opération</a>"
267
-
268
-#: tracim/controllers/__init__.py:311 tracim/controllers/content.py:757
269
-msgid "{} not archived: {}"
270
-msgstr "{} non archivé(e) : {}"
271
-
272
-#: tracim/controllers/__init__.py:325 tracim/controllers/content.py:771
273
->>>>>>> 139e854c54cbb438fb69dda1149d450228cf2e8a
274
-msgid "{} unarchived."
275
-msgstr "{} désarchivé(e)"
276
-
277
-#: tracim/controllers/__init__.py:333 tracim/controllers/content.py:779
278
-msgid "{} not un-archived: {}"
279
-msgstr "{} non désarchivé(e) : {}"
280
-
281
-#: tracim/controllers/__init__.py:351 tracim/controllers/content.py:88
282
-#: tracim/controllers/content.py:796
283
-=======
284
 #: tracim/controllers/content.py:846
119
 #: tracim/controllers/content.py:846
285
->>>>>>> b67ad8598a3cfae087b99a8b7bf905ae8b8ec991
286
 msgid "{} deleted. <a class=\"alert-link\" href=\"{}\">Cancel action</a>"
120
 msgid "{} deleted. <a class=\"alert-link\" href=\"{}\">Cancel action</a>"
287
 msgstr ""
121
 msgstr ""
288
 "{} supprimé(e). <a class=\"alert-link\" href=\"{}\">Annuler "
122
 "{} supprimé(e). <a class=\"alert-link\" href=\"{}\">Annuler "
298
 msgid "{} undeleted."
132
 msgid "{} undeleted."
299
 msgstr "{} restauré(e)."
133
 msgstr "{} restauré(e)."
300
 
134
 
301
-=======
302
-#: tracim/controllers/__init__.py:360 tracim/controllers/content.py:99
303
-#: tracim/controllers/content.py:805
304
-msgid "{} not deleted: {}"
305
-msgstr "{} non supprimé(e) : {}"
306
-
307
-#: tracim/controllers/__init__.py:375 tracim/controllers/content.py:116
308
-#: tracim/controllers/content.py:820
309
-msgid "{} undeleted."
310
-msgstr "{} restauré(e)."
311
-
312
->>>>>>> 139e854c54cbb438fb69dda1149d450228cf2e8a
313
 #: tracim/controllers/__init__.py:385 tracim/controllers/content.py:128
135
 #: tracim/controllers/__init__.py:385 tracim/controllers/content.py:128
314
-<<<<<<< HEAD
315
-#: tracim/controllers/content.py:830
316
->>>>>>> b2e4664ae2ad0cc8fbc3344f6fa37845cf7e344d
317
-=======
318
 #: tracim/controllers/content.py:880
136
 #: tracim/controllers/content.py:880
319
->>>>>>> b67ad8598a3cfae087b99a8b7bf905ae8b8ec991
320
 msgid "{} not un-deleted: {}"
137
 msgid "{} not un-deleted: {}"
321
 msgstr "{} non restauré(e) : {}"
138
 msgstr "{} non restauré(e) : {}"
322
 
139
 
379
 
196
 
380
 #: tracim/controllers/content.py:780
197
 #: tracim/controllers/content.py:780
381
 msgid "Folder"
198
 msgid "Folder"
382
-<<<<<<< HEAD
383
 msgstr "Dossier"
199
 msgstr "Dossier"
384
-=======
385
-msgstr "Dossiers"
386
->>>>>>> b2e4664ae2ad0cc8fbc3344f6fa37845cf7e344d
387
 
200
 
388
 #: tracim/controllers/root.py:72
201
 #: tracim/controllers/root.py:72
389
 msgid "Wrong credentials"
202
 msgid "Wrong credentials"
529
 msgid "%B %d at %I:%M%p"
342
 msgid "%B %d at %I:%M%p"
530
 msgstr "le %d %B à %H:%M"
343
 msgstr "le %d %B à %H:%M"
531
 
344
 
532
-<<<<<<< HEAD
533
-<<<<<<< HEAD
534
-<<<<<<< HEAD
535
-<<<<<<< HEAD
536
-=======
537
-#: tracim/lib/content.py:98
538
-#: tracim/templates/dashboard.mak:36
539
-=======
540
-#: tracim/lib/content.py:98 tracim/templates/dashboard.mak:36
541
->>>>>>> 139e854c54cbb438fb69dda1149d450228cf2e8a
542
-=======
543
-#: tracim/lib/content.py:98 tracim/templates/dashboard.mak:36
544
->>>>>>> 139e854c54cbb438fb69dda1149d450228cf2e8a
545
-=======
546
-#: tracim/lib/content.py:100 tracim/templates/dashboard.mak:36
547
->>>>>>> b67ad8598a3cfae087b99a8b7bf905ae8b8ec991
345
+#: tracim/lib/content.py:101 tracim/templates/dashboard.mak:36
548
 #: tracim/templates/master_authenticated.mak:94
346
 #: tracim/templates/master_authenticated.mak:94
549
 #: tracim/templates/master_no_toolbar_no_login.mak:112
347
 #: tracim/templates/master_no_toolbar_no_login.mak:112
550
-#: tracim/templates/search.mak:11 tracim/templates/user_get_one.mak:39
348
+#: tracim/templates/search.mak:11 tracim/templates/user_get_one.mak:42
551
 #: tracim/templates/user_profile.mak:39
349
 #: tracim/templates/user_profile.mak:39
552
 #: tracim/templates/user_workspace_folder_file_get_one.mak:10
350
 #: tracim/templates/user_workspace_folder_file_get_one.mak:10
553
 #: tracim/templates/user_workspace_folder_get_one.mak:11
351
 #: tracim/templates/user_workspace_folder_get_one.mak:11
559
 msgid "Workspaces"
357
 msgid "Workspaces"
560
 msgstr "Espaces de travail"
358
 msgstr "Espaces de travail"
561
 
359
 
562
-<<<<<<< HEAD
563
->>>>>>> b2e4664ae2ad0cc8fbc3344f6fa37845cf7e344d
564
-=======
565
-#: tracim/lib/notifications.py:289
360
+#: tracim/lib/notifications.py:285
566
 msgid "<span id=\"content-intro-username\">{}</span> added a comment:"
361
 msgid "<span id=\"content-intro-username\">{}</span> added a comment:"
567
 msgstr "<span id=\"content-intro-username\">{}</span> a ajouté un commentaire :"
362
 msgstr "<span id=\"content-intro-username\">{}</span> a ajouté un commentaire :"
568
 
363
 
569
-#: tracim/lib/notifications.py:291 tracim/lib/notifications.py:300
364
+#: tracim/lib/notifications.py:287 tracim/lib/notifications.py:296
570
 msgid "Answer"
365
 msgid "Answer"
571
 msgstr "Répondre"
366
 msgstr "Répondre"
572
 
367
 
573
-#: tracim/lib/notifications.py:297 tracim/lib/notifications.py:321
574
-#: tracim/lib/notifications.py:347
368
+#: tracim/lib/notifications.py:293 tracim/lib/notifications.py:317
369
+#: tracim/lib/notifications.py:350
575
 msgid "View online"
370
 msgid "View online"
576
 msgstr "Voir en ligne"
371
 msgstr "Voir en ligne"
577
 
372
 
578
-#: tracim/lib/notifications.py:301
373
+#: tracim/lib/notifications.py:297
579
 msgid "<span id=\"content-intro-username\">{}</span> started a thread entitled:"
374
 msgid "<span id=\"content-intro-username\">{}</span> started a thread entitled:"
580
 msgstr ""
375
 msgstr ""
581
 "<span id=\"content-intro-username\">{}</span> a lancé une discussion "
376
 "<span id=\"content-intro-username\">{}</span> a lancé une discussion "
582
 "intitulée :"
377
 "intitulée :"
583
 
378
 
584
-#: tracim/lib/notifications.py:306
379
+#: tracim/lib/notifications.py:302
585
 msgid "<span id=\"content-intro-username\">{}</span> added a file entitled:"
380
 msgid "<span id=\"content-intro-username\">{}</span> added a file entitled:"
586
 msgstr ""
381
 msgstr ""
587
 "<span id=\"content-intro-username\">{}</span> a ajouté un fichier "
382
 "<span id=\"content-intro-username\">{}</span> a ajouté un fichier "
588
 "intitulé :"
383
 "intitulé :"
589
 
384
 
590
-#: tracim/lib/notifications.py:316
385
+#: tracim/lib/notifications.py:312
591
 msgid "<span id=\"content-intro-username\">{}</span> added a page entitled:"
386
 msgid "<span id=\"content-intro-username\">{}</span> added a page entitled:"
592
 msgstr ""
387
 msgstr ""
593
 "<span id=\"content-intro-username\">{}</span> a ajouté une page intitulée"
388
 "<span id=\"content-intro-username\">{}</span> a ajouté une page intitulée"
594
 " :"
389
 " :"
595
 
390
 
596
-#: tracim/lib/notifications.py:324
391
+#: tracim/lib/notifications.py:320
597
 msgid "<span id=\"content-intro-username\">{}</span> uploaded a new revision."
392
 msgid "<span id=\"content-intro-username\">{}</span> uploaded a new revision."
598
 msgstr ""
393
 msgstr ""
599
 "<span id=\"content-intro-username\">{}</span> a téléchargé une nouvelle "
394
 "<span id=\"content-intro-username\">{}</span> a téléchargé une nouvelle "
600
 "version."
395
 "version."
601
 
396
 
602
-#: tracim/lib/notifications.py:328
397
+#: tracim/lib/notifications.py:324
603
 msgid "<span id=\"content-intro-username\">{}</span> updated this page."
398
 msgid "<span id=\"content-intro-username\">{}</span> updated this page."
604
 msgstr "<span id=\"content-intro-username\">{}</span> a mis à jour cette page."
399
 msgstr "<span id=\"content-intro-username\">{}</span> a mis à jour cette page."
605
 
400
 
606
-#: tracim/lib/notifications.py:333
401
+#: tracim/lib/notifications.py:329 tracim/lib/notifications.py:339
607
 msgid "<p id=\"content-body-intro\">Here is an overview of the changes:</p>"
402
 msgid "<p id=\"content-body-intro\">Here is an overview of the changes:</p>"
608
 msgstr "<p id=\"content-body-intro\">Voici un aperçu des modifications :</p>"
403
 msgstr "<p id=\"content-body-intro\">Voici un aperçu des modifications :</p>"
609
 
404
 
610
-#: tracim/lib/notifications.py:338
405
+#: tracim/lib/notifications.py:334
611
 msgid ""
406
 msgid ""
612
 "<span id=\"content-intro-username\">{}</span> updated the thread "
407
 "<span id=\"content-intro-username\">{}</span> updated the thread "
613
 "description."
408
 "description."
615
 "<span id=\"content-intro-username\">{}</span> a mis à jour la description"
410
 "<span id=\"content-intro-username\">{}</span> a mis à jour la description"
616
 " de la discussion."
411
 " de la discussion."
617
 
412
 
618
-#: tracim/lib/notifications.py:350
413
+#: tracim/lib/notifications.py:353
619
 msgid ""
414
 msgid ""
620
 "<span id=\"content-intro-username\">{}</span> updated the file "
415
 "<span id=\"content-intro-username\">{}</span> updated the file "
621
 "description."
416
 "description."
623
 "<span id=\"content-intro-username\">{}</span> a mis à jour la description"
418
 "<span id=\"content-intro-username\">{}</span> a mis à jour la description"
624
 " du fichier."
419
 " du fichier."
625
 
420
 
626
->>>>>>> b67ad8598a3cfae087b99a8b7bf905ae8b8ec991
627
 #: tracim/lib/predicates.py:17
421
 #: tracim/lib/predicates.py:17
628
 msgid "You are not authorized to access this resource"
422
 msgid "You are not authorized to access this resource"
629
 msgstr "Vous n'êtes pas autorisé à accéder à cette ressource"
423
 msgstr "Vous n'êtes pas autorisé à accéder à cette ressource"
741
 
535
 
742
 #: tracim/model/data.py:291
536
 #: tracim/model/data.py:291
743
 msgid "Delete this workspace"
537
 msgid "Delete this workspace"
744
-<<<<<<< HEAD
745
 msgstr "Supprimer cet espace de travail"
538
 msgstr "Supprimer cet espace de travail"
746
-=======
747
-msgstr "Supprimer l'espace de travail"
748
->>>>>>> b2e4664ae2ad0cc8fbc3344f6fa37845cf7e344d
749
 
539
 
750
 #: tracim/model/data.py:292
540
 #: tracim/model/data.py:292
751
 msgid "Delete this folder"
541
 msgid "Delete this folder"
753
 
543
 
754
 #: tracim/model/data.py:293
544
 #: tracim/model/data.py:293
755
 msgid "Delete this file"
545
 msgid "Delete this file"
756
-<<<<<<< HEAD
757
 msgstr "Supprimer ce fichier"
546
 msgstr "Supprimer ce fichier"
758
-=======
759
-msgstr "Supprimer le fichier"
760
->>>>>>> b2e4664ae2ad0cc8fbc3344f6fa37845cf7e344d
761
 
547
 
762
 #: tracim/model/data.py:294
548
 #: tracim/model/data.py:294
763
 msgid "Delete this page"
549
 msgid "Delete this page"
867
 msgid "Delete thread"
653
 msgid "Delete thread"
868
 msgstr "Supprimer la discussion"
654
 msgstr "Supprimer la discussion"
869
 
655
 
870
-<<<<<<< HEAD
871
-<<<<<<< HEAD
872
-#: tracim/templates/index.mak:30
873
-#: tracim/templates/index.mak:51
874
-<<<<<<< HEAD
875
-#: tracim/templates/master_authenticated.mak:147
876
-=======
877
-=======
878
-#: tracim/templates/index.mak:30 tracim/templates/index.mak:51
879
->>>>>>> 139e854c54cbb438fb69dda1149d450228cf2e8a
880
-=======
881
 #: tracim/templates/index.mak:30 tracim/templates/index.mak:51
656
 #: tracim/templates/index.mak:30 tracim/templates/index.mak:51
882
->>>>>>> 139e854c54cbb438fb69dda1149d450228cf2e8a
883
 #: tracim/templates/master_authenticated.mak:154
657
 #: tracim/templates/master_authenticated.mak:154
884
->>>>>>> b2e4664ae2ad0cc8fbc3344f6fa37845cf7e344d
885
 msgid "Login"
658
 msgid "Login"
886
 msgstr "Login"
659
 msgstr "Login"
887
 
660
 
925
 msgid "you MUST desactivate debug in production"
698
 msgid "you MUST desactivate debug in production"
926
 msgstr "vous DEVEZ désactiver le mode \"debug\" en production"
699
 msgstr "vous DEVEZ désactiver le mode \"debug\" en production"
927
 
700
 
928
-<<<<<<< HEAD
929
-#: tracim/templates/master_authenticated.mak:137
930
-=======
931
 #: tracim/templates/master_authenticated.mak:119
701
 #: tracim/templates/master_authenticated.mak:119
932
 msgid "Search for..."
702
 msgid "Search for..."
933
 msgstr "Rechercher..."
703
 msgstr "Rechercher..."
937
 msgstr "Rechercher..."
707
 msgstr "Rechercher..."
938
 
708
 
939
 #: tracim/templates/master_authenticated.mak:144
709
 #: tracim/templates/master_authenticated.mak:144
940
->>>>>>> b2e4664ae2ad0cc8fbc3344f6fa37845cf7e344d
941
 #: tracim/templates/master_no_toolbar_no_login.mak:144
710
 #: tracim/templates/master_no_toolbar_no_login.mak:144
942
 msgid "My account"
711
 msgid "My account"
943
 msgstr "Mon compte"
712
 msgstr "Mon compte"
944
 
713
 
945
-<<<<<<< HEAD
946
-#: tracim/templates/master_authenticated.mak:142
947
-=======
948
 #: tracim/templates/master_authenticated.mak:149
714
 #: tracim/templates/master_authenticated.mak:149
949
->>>>>>> b2e4664ae2ad0cc8fbc3344f6fa37845cf7e344d
950
 #: tracim/templates/master_no_toolbar_no_login.mak:149
715
 #: tracim/templates/master_no_toolbar_no_login.mak:149
951
 msgid "Logout"
716
 msgid "Logout"
952
 msgstr "Fermer la session"
717
 msgstr "Fermer la session"
1206
 msgid "This user is an administrator."
971
 msgid "This user is an administrator."
1207
 msgstr "Cet utilisateur est un administrateur"
972
 msgstr "Cet utilisateur est un administrateur"
1208
 
973
 
1209
-<<<<<<< HEAD
1210
-<<<<<<< HEAD
1211
-#: tracim/templates/user_get_one.mak:45
1212
-#: tracim/templates/user_profile.mak:42
1213
-=======
1214
-#: tracim/templates/user_get_one.mak:42 tracim/templates/user_profile.mak:42
1215
->>>>>>> 139e854c54cbb438fb69dda1149d450228cf2e8a
1216
-=======
1217
-#: tracim/templates/user_get_one.mak:42 tracim/templates/user_profile.mak:42
1218
->>>>>>> 139e854c54cbb438fb69dda1149d450228cf2e8a
974
+#: tracim/templates/user_get_one.mak:45 tracim/templates/user_profile.mak:42
1219
 msgid "This user is not member of any workspace."
975
 msgid "This user is not member of any workspace."
1220
 msgstr "Cet utilisateur n'est membre d'aucun espace de travail"
976
 msgstr "Cet utilisateur n'est membre d'aucun espace de travail"
1221
 
977
 
2395
 #~ msgid "Go to information:"
2151
 #~ msgid "Go to information:"
2396
 #~ msgstr "Voir en ligne :"
2152
 #~ msgstr "Voir en ligne :"
2397
 
2153
 
2398
-#~ msgid ""
2399
-#~ "*{user_display_name}*, you receive this email"
2400
-#~ " because you are *{user_role_label}* in "
2401
-#~ "the workspace {workspace_label} - "
2402
-#~ "{workspace_url}"
2403
-#~ msgstr ""
2404
-#~ "*{user_display_name}*, vous recevez cet email"
2405
-#~ " car vous êtes *{user_role_label}* dans "
2406
-#~ "l'espace de travail {workspace_label} - "
2407
-#~ "{workspace_url}"
2408
-

+ 62 - 5
tracim/tracim/lib/content.py Visa fil

11
 from sqlalchemy.orm import aliased
11
 from sqlalchemy.orm import aliased
12
 from sqlalchemy.orm import joinedload
12
 from sqlalchemy.orm import joinedload
13
 from sqlalchemy.orm.attributes import get_history
13
 from sqlalchemy.orm.attributes import get_history
14
+from sqlalchemy import desc
14
 from sqlalchemy import not_
15
 from sqlalchemy import not_
15
 from sqlalchemy import or_
16
 from sqlalchemy import or_
16
 from tracim.lib import cmp_to_key
17
 from tracim.lib import cmp_to_key
99
         breadcrumb = []
100
         breadcrumb = []
100
 
101
 
101
         if not skip_root:
102
         if not skip_root:
102
-            breadcrumb.append(BreadcrumbItem(ContentType.icon(ContentType.FAKE_Dashboard), _('Workspaces'), tg.url('/workspaces')))
103
-        breadcrumb.append(BreadcrumbItem(ContentType.icon(ContentType.FAKE_Workspace), workspace.label, tg.url('/workspaces/{}'.format(workspace.workspace_id))))
103
+            breadcrumb.append(BreadcrumbItem(ContentType.get_icon(ContentType.FAKE_Dashboard), _('Workspaces'), tg.url('/workspaces')))
104
+        breadcrumb.append(BreadcrumbItem(ContentType.get_icon(ContentType.FAKE_Workspace), workspace.label, tg.url('/workspaces/{}'.format(workspace.workspace_id))))
104
 
105
 
105
         if item_id:
106
         if item_id:
106
             breadcrumb_folder_items = []
107
             breadcrumb_folder_items = []
112
                 next_url = tg.url('/workspaces/{}/folders/{}/{}s/{}'.format(workspace_id, current_item.parent_id, current_item.type, current_item.content_id))
113
                 next_url = tg.url('/workspaces/{}/folders/{}/{}s/{}'.format(workspace_id, current_item.parent_id, current_item.type, current_item.content_id))
113
 
114
 
114
             while current_item:
115
             while current_item:
115
-                breadcrumb_item = BreadcrumbItem(ContentType.icon(current_item.type),
116
+                breadcrumb_item = BreadcrumbItem(ContentType.get_icon(current_item.type),
116
                                                  current_item.label,
117
                                                  current_item.label,
117
                                                  next_url,
118
                                                  next_url,
118
                                                  is_active)
119
                                                  is_active)
302
 
303
 
303
         return resultset.all()
304
         return resultset.all()
304
 
305
 
306
+    def get_last_active(self, parent_id: int, content_type: str, workspace: Workspace=None, limit=10) -> Content:
307
+        assert parent_id is None or isinstance(parent_id, int) # DYN_REMOVE
308
+        assert content_type is not None# DYN_REMOVE
309
+        assert isinstance(content_type, str) # DYN_REMOVE
310
+
311
+        resultset = self._base_query(workspace).order_by(desc(Content.updated))
312
+
313
+        if content_type!=ContentType.Any:
314
+            resultset = resultset.filter(Content.type==content_type)
315
+
316
+        if parent_id:
317
+            resultset = resultset.filter(Content.parent_id==parent_id)
318
+
319
+        result = []
320
+        for item in resultset:
321
+            new_item = None
322
+            if ContentType.Comment == item.type:
323
+                new_item = item.parent
324
+            else:
325
+                new_item = item
326
+
327
+            # INFO - D.A. - 2015-05-20
328
+            # We do not want to show only one item if the last 10 items are
329
+            # comments about one thread for example
330
+            if new_item not in result:
331
+                result.append(new_item)
332
+
333
+            if len(result) >= limit:
334
+                break
335
+
336
+        return result
337
+
305
     def set_allowed_content(self, folder: Content, allowed_content_dict:dict):
338
     def set_allowed_content(self, folder: Content, allowed_content_dict:dict):
306
         """
339
         """
307
         :param folder: the given folder instance
340
         :param folder: the given folder instance
326
             raise ValueError('The given value {} is not allowed'.format(new_status))
359
             raise ValueError('The given value {} is not allowed'.format(new_status))
327
 
360
 
328
 
361
 
329
-    def move(self, item: Content, new_parent: Content, must_stay_in_same_workspace:bool=True):
362
+    def move(self, item: Content,
363
+             new_parent: Content,
364
+             must_stay_in_same_workspace:bool=True,
365
+             new_workspace:Workspace=None):
330
         if must_stay_in_same_workspace:
366
         if must_stay_in_same_workspace:
331
-            if new_parent and new_parent.workspace_id!=item.workspace_id:
367
+            if new_parent and new_parent.workspace_id != item.workspace_id:
332
                 raise ValueError('the item should stay in the same workspace')
368
                 raise ValueError('the item should stay in the same workspace')
333
 
369
 
334
         item.parent = new_parent
370
         item.parent = new_parent
371
+        if new_parent:
372
+            item.workspace = new_parent.workspace
373
+        elif new_workspace:
374
+            item.workspace = new_workspace
375
+
335
         item.revision_type = ActionDescription.EDITION
376
         item.revision_type = ActionDescription.EDITION
336
 
377
 
378
+    def move_recursively(self, item: Content,
379
+                         new_parent: Content, new_workspace: Workspace):
380
+        self.move(item, new_parent, False, new_workspace)
381
+        self.save(item, do_notify=False)
382
+        print('saved item #', item.content_id, new_workspace)
383
+        for child in item.children:
384
+            self.move_recursively(child, item, new_workspace)
385
+        return
337
 
386
 
338
     def update_content(self, item: Content, new_label: str, new_content: str=None) -> Content:
387
     def update_content(self, item: Content, new_label: str, new_content: str=None) -> Content:
339
         if item.label==new_label and item.description==new_content:
388
         if item.label==new_label and item.description==new_content:
442
 
491
 
443
         return title_keyworded_items
492
         return title_keyworded_items
444
 
493
 
494
+    def get_all_types(self) -> [ContentType]:
495
+        labels = ContentType.all()
496
+        content_types = []
497
+        for label in labels:
498
+            content_types.append(ContentType(label))
499
+
500
+        return ContentType.sorted(content_types)
501
+

+ 19 - 4
tracim/tracim/lib/helpers.py Visa fil

5
 #from webhelpers import date, feedgenerator, html, number, misc, text
5
 #from webhelpers import date, feedgenerator, html, number, misc, text
6
 
6
 
7
 import datetime
7
 import datetime
8
+
9
+from babel.dates import format_date, format_time
8
 from markupsafe import Markup
10
 from markupsafe import Markup
9
 
11
 
10
 import tg
12
 import tg
11
-
13
+from tg.i18n import ugettext as _
12
 from tracim.config.app_cfg import CFG
14
 from tracim.config.app_cfg import CFG
13
 
15
 
14
 from tracim.lib import app_globals as plag
16
 from tracim.lib import app_globals as plag
25
 from tracim.model.data import Workspace
27
 from tracim.model.data import Workspace
26
 
28
 
27
 def date_time_in_long_format(datetime_object, format=''):
29
 def date_time_in_long_format(datetime_object, format=''):
28
-    if not format:
29
-        format = plag.Globals.LONG_DATE_FORMAT
30
-    return datetime_object.strftime(format.__str__())
31
 
30
 
31
+    current_locale = tg.i18n.get_lang()[0]
32
+    date = format_date(datetime_object, locale=current_locale)
33
+    time = format_time(datetime_object, locale=current_locale)
34
+    return _('{date} at {time}').format(date=date, time=time)
35
+
36
+def date_time(datetime_object):
37
+    return date_time_in_long_format(datetime_object)
38
+
39
+def date(datetime_object):
40
+    current_locale = tg.i18n.get_lang()[0]
41
+    return format_date(datetime_object, locale=current_locale)
42
+
43
+
44
+def time(datetime_object):
45
+    current_locale = tg.i18n.get_lang()[0]
46
+    return format_time(datetime_object, locale=current_locale)
32
 
47
 
33
 def format_short(datetime_object):
48
 def format_short(datetime_object):
34
     return datetime_object.strftime(format = plag.Globals.SHORT_DATE_FORMAT.__str__())
49
     return datetime_object.strftime(format = plag.Globals.SHORT_DATE_FORMAT.__str__())

+ 12 - 2
tracim/tracim/lib/workspace.py Visa fil

68
     def get_all(self):
68
     def get_all(self):
69
         return self._base_query().all()
69
         return self._base_query().all()
70
 
70
 
71
-    def get_all_for_user(self, user: User):
72
-        workspaces = [role.workspace for role in user.roles if not role.workspace.is_deleted]
71
+    def get_all_for_user(self, user: User, ignored_ids=None):
72
+        workspaces = []
73
+
74
+        for role in user.roles:
75
+            if not role.workspace.is_deleted:
76
+                if not ignored_ids:
77
+                    workspaces.append(role.workspace)
78
+                elif role.workspace.workspace_id not in ignored_ids:
79
+                        workspaces.append(role.workspace)
80
+                else:
81
+                    pass  # do not return workspace
82
+
73
         workspaces.sort(key=lambda workspace: workspace.label.lower())
83
         workspaces.sort(key=lambda workspace: workspace.label.lower())
74
         return workspaces
84
         return workspaces
75
 
85
 

+ 8 - 0
tracim/tracim/model/auth.py Visa fil

211
         else:
211
         else:
212
             return self.email
212
             return self.email
213
 
213
 
214
+    def get_role(self, workspace: 'Workspace') -> int:
215
+        for role in self.roles:
216
+            print('IS EQUALS ? ', role.workspace, workspace)
217
+            if role.workspace == workspace:
218
+                return role.role
219
+
220
+        from tracim.model.data import UserRoleInWorkspace
221
+        return UserRoleInWorkspace.NOT_APPLICABLE
214
 
222
 
215
 class Permission(DeclarativeBase):
223
 class Permission(DeclarativeBase):
216
     """
224
     """

+ 150 - 37
tracim/tracim/model/data.py Visa fil

1
 # -*- coding: utf-8 -*-
1
 # -*- coding: utf-8 -*-
2
 
2
 
3
+import tg
4
+from datetime import datetime
5
+from babel.dates import format_timedelta
6
+
3
 from bs4 import BeautifulSoup
7
 from bs4 import BeautifulSoup
4
 import datetime as datetime_root
8
 import datetime as datetime_root
5
 import json
9
 import json
61
         """ this method is for interoperability with Content class"""
65
         """ this method is for interoperability with Content class"""
62
         return self.label
66
         return self.label
63
 
67
 
68
+    def get_allowed_content_types(self):
69
+        # @see Content.get_allowed_content_types()
70
+        return [ContentType('folder')]
71
+
72
+    def get_valid_children(self, content_types: list=None):
73
+        for child in self.contents:
74
+            # we search only direct children
75
+            if not child.parent \
76
+                    and not child.is_deleted \
77
+                    and not child.is_archived:
78
+                if not content_types or child.type in content_types:
79
+                    yield child
80
+
64
 class UserRoleInWorkspace(DeclarativeBase):
81
 class UserRoleInWorkspace(DeclarativeBase):
65
 
82
 
66
     __tablename__ = 'user_workspace'
83
     __tablename__ = 'user_workspace'
93
     STYLE[4] = 'color: #ea983d;'
110
     STYLE[4] = 'color: #ea983d;'
94
     STYLE[8] = 'color: #F00;'
111
     STYLE[8] = 'color: #F00;'
95
 
112
 
113
+    ICON = dict()
114
+    ICON[0] = ''
115
+    ICON[1] = 'fa-eye'
116
+    ICON[2] = 'fa-pencil'
117
+    ICON[4] = 'fa-graduation-cap'
118
+    ICON[8] = 'fa-legal'
119
+
120
+
121
+    @property
122
+    def icon(self):
123
+        return UserRoleInWorkspace.ICON[self.role]
96
 
124
 
97
     @property
125
     @property
98
     def style(self):
126
     def style(self):
113
 class RoleType(object):
141
 class RoleType(object):
114
     def __init__(self, role_id):
142
     def __init__(self, role_id):
115
         self.role_type_id = role_id
143
         self.role_type_id = role_id
144
+        self.icon = UserRoleInWorkspace.ICON[role_id]
116
         self.role_label = UserRoleInWorkspace.LABEL[role_id]
145
         self.role_label = UserRoleInWorkspace.LABEL[role_id]
117
         self.css_style = UserRoleInWorkspace.STYLE[role_id]
146
         self.css_style = UserRoleInWorkspace.STYLE[role_id]
118
 
147
 
142
     UNDELETION = 'undeletion'
171
     UNDELETION = 'undeletion'
143
 
172
 
144
     _ICONS = {
173
     _ICONS = {
145
-        'archiving': 'mimetypes/package-x-generic',
146
-        'content-comment': 'apps/internet-group-chat',
147
-        'creation': 'actions/document-new',
148
-        'deletion': 'status/user-trash-full',
149
-        'edition': 'apps/accessories-text-editor',
150
-        'revision': 'apps/accessories-text-editor',
151
-        'status-update': 'apps/utilities-system-monitor',
152
-        'unarchiving': 'mimetypes/package-x-generic',
153
-        'undeletion': 'places/user-trash'
174
+        'archiving': 'fa fa-archive',
175
+        'content-comment': 'fa-comment-o',
176
+        'creation': 'fa-magic',
177
+        'deletion': 'fa fa-trash',
178
+        'edition': 'fa fa-edit',
179
+        'revision': 'fa-history',
180
+        'status-update': 'fa-random',
181
+        'unarchiving': 'fa fa-file-archive-o',
182
+        'undeletion': 'fa-trash-o'
154
     }
183
     }
155
 
184
 
156
     _LABELS = {
185
     _LABELS = {
157
-        'archiving': l_('Item archived'),
158
-        'content-comment': l_('Item commented'),
159
-        'creation': l_('Item created'),
160
-        'deletion': l_('Item deleted'),
161
-        'edition': l_('Item modified'),
162
-        'revision': l_('New revision'),
163
-        'status-update': l_('Status modified'),
164
-        'unarchiving': l_('Item un-archived'),
165
-        'undeletion': l_('Item undeleted'),
186
+        'archiving': l_('archive'),
187
+        'content-comment': l_('commente'),
188
+        'creation': l_('creation'),
189
+        'deletion': l_('deletion'),
190
+        'edition': l_('modified'),
191
+        'revision': l_('revision'),
192
+        'status-update': l_('statut'),
193
+        'unarchiving': l_('un-archived'),
194
+        'undeletion': l_('un-deleted'),
166
     }
195
     }
167
 
196
 
168
     def __init__(self, id):
197
     def __init__(self, id):
214
                     'closed-deprecated': l_('deprecated')}
243
                     'closed-deprecated': l_('deprecated')}
215
 
244
 
216
     _ICONS = {
245
     _ICONS = {
217
-        'open': 'status/status-open',
218
-        'closed-validated': 'emblems/emblem-checked',
219
-        'closed-unvalidated': 'emblems/emblem-unreadable',
220
-        'closed-deprecated': 'status/status-outdated',
246
+        'open': 'fa fa-square-o',
247
+        'closed-validated': 'fa fa-check-square-o',
248
+        'closed-unvalidated': 'fa fa-close',
249
+        'closed-deprecated': 'fa fa-warning',
221
     }
250
     }
222
 
251
 
223
     _CSS = {
252
     _CSS = {
268
 
297
 
269
     _STRING_LIST_SEPARATOR = ','
298
     _STRING_LIST_SEPARATOR = ','
270
 
299
 
271
-    _ICONS = {
272
-        'dashboard': 'places/user-desktop',
273
-        'workspace': 'places/folder-remote',
274
-        'folder': 'places/jstree-folder',
275
-        'file': 'mimetypes/text-x-generic-template',
276
-        'page': 'mimetypes/text-html',
277
-        'thread': 'apps/internet-group-chat',
278
-        'comment': 'apps/internet-group-chat',
300
+    _ICONS = {  # Deprecated
301
+        'dashboard': 'fa-home',
302
+        'workspace': 'fa-bank',
303
+        'folder': 'fa fa-folder-open-o',
304
+        'file': 'fa fa-paperclip',
305
+        'page': 'fa fa-file-text-o',
306
+        'thread': 'fa fa-comments-o',
307
+        'comment': 'fa fa-comment-o',
308
+    }
309
+
310
+    _CSS_ICONS = {
311
+        'dashboard': 'fa fa-home',
312
+        'workspace': 'fa fa-bank',
313
+        'folder': 'fa fa-folder-open-o',
314
+        'file': 'fa fa-paperclip',
315
+        'page': 'fa fa-file-text-o',
316
+        'thread': 'fa fa-comments-o',
317
+        'comment': 'fa fa-comment-o'
318
+    }
319
+
320
+    _CSS_COLORS = {
321
+        'dashboard': 't-dashboard-color',
322
+        'workspace': 't-less-visible',
323
+        'folder': 't-folder-color',
324
+        'file': 't-file-color',
325
+        'page': 't-page-color',
326
+        'thread': 't-thread-color',
327
+        'comment': 't-thread-color'
279
     }
328
     }
280
 
329
 
281
     _ORDER_WEIGHT = {
330
     _ORDER_WEIGHT = {
286
         'comment': 4,
335
         'comment': 4,
287
     }
336
     }
288
 
337
 
338
+    _LABEL = {
339
+        'dashboard': '',
340
+        'workspace': l_('workspace'),
341
+        'folder': l_('folder'),
342
+        'file': l_('file'),
343
+        'page': l_('page'),
344
+        'thread': l_('thread'),
345
+        'comment': l_('comment'),
346
+    }
347
+
289
     _DELETE_LABEL = {
348
     _DELETE_LABEL = {
290
         'dashboard': '',
349
         'dashboard': '',
291
         'workspace': l_('Delete this workspace'),
350
         'workspace': l_('Delete this workspace'),
297
     }
356
     }
298
 
357
 
299
     @classmethod
358
     @classmethod
300
-    def icon(cls, type: str):
359
+    def get_icon(cls, type: str):
301
         assert(type in ContentType._ICONS) # DYN_REMOVE
360
         assert(type in ContentType._ICONS) # DYN_REMOVE
302
         return ContentType._ICONS[type]
361
         return ContentType._ICONS[type]
303
 
362
 
343
         # Make this code dynamic loading data types
402
         # Make this code dynamic loading data types
344
         return '/workspaces/{}'.format(workspace.workspace_id)
403
         return '/workspaces/{}'.format(workspace.workspace_id)
345
 
404
 
405
+    @classmethod
406
+    def sorted(cls, types: ['ContentType']) -> ['ContentType']:
407
+        return sorted(types, key=lambda content_type: content_type.priority)
408
+
409
+    def __init__(self, type):
410
+        self.type = type
411
+        self.icon = ContentType._CSS_ICONS[type]
412
+        self.color = ContentType._CSS_COLORS[type]
413
+        self.label = ContentType._LABEL[type]
414
+        self.priority = ContentType._ORDER_WEIGHT[type]
415
+
416
+    def toDict(self):
417
+        return dict(id=self.type,
418
+                    type=self.type,
419
+                    icon=self.icon,
420
+                    color=self.color,
421
+                    label=self.label,
422
+                    priority=self.priority)
346
 
423
 
347
 class Content(DeclarativeBase):
424
 class Content(DeclarativeBase):
348
 
425
 
381
     parent = relationship('Content', remote_side=[content_id], backref='children')
458
     parent = relationship('Content', remote_side=[content_id], backref='children')
382
     owner = relationship('User', remote_side=[User.user_id])
459
     owner = relationship('User', remote_side=[User.user_id])
383
 
460
 
384
-    @property
385
-    def valid_children(self):
461
+    def get_valid_children(self, content_types: list=None):
386
         for child in self.children:
462
         for child in self.children:
387
             if not child.is_deleted and not child.is_archived:
463
             if not child.is_deleted and not child.is_archived:
388
-                yield child
464
+                if not content_types or child.type in content_types:
465
+                    yield child
389
 
466
 
390
     @hybrid_property
467
     @hybrid_property
391
     def properties(self):
468
     def properties(self):
400
         self._properties = json.dumps(properties_struct)
477
         self._properties = json.dumps(properties_struct)
401
         ContentChecker.check_properties(self)
478
         ContentChecker.check_properties(self)
402
 
479
 
480
+    def created_as_delta(self, delta_from_datetime:datetime=None):
481
+        if not delta_from_datetime:
482
+            delta_from_datetime = datetime.now()
483
+        return format_timedelta(delta_from_datetime - self.created,
484
+                                locale=tg.i18n.get_lang()[0])
485
+
486
+    def datetime_as_delta(self, datetime_object,
487
+                          delta_from_datetime:datetime=None):
488
+        if not delta_from_datetime:
489
+            delta_from_datetime = datetime.now()
490
+        return format_timedelta(delta_from_datetime - datetime_object,
491
+                                locale=tg.i18n.get_lang()[0])
492
+
493
+
403
     def extract_links_from_content(self, other_content: str=None) -> [LinkItem]:
494
     def extract_links_from_content(self, other_content: str=None) -> [LinkItem]:
404
         """
495
         """
405
         parse html content and extract links. By default, it works on the description property
496
         parse html content and extract links. By default, it works on the description property
427
 
518
 
428
     def get_child_nb(self, content_type: ContentType, content_status = ''):
519
     def get_child_nb(self, content_type: ContentType, content_status = ''):
429
         child_nb = 0
520
         child_nb = 0
430
-        for child in self.valid_children:
521
+        for child in self.get_valid_children():
431
             if child.type == content_type or content_type == ContentType.Any:
522
             if child.type == content_type or content_type == ContentType.Any:
432
                 if not content_status:
523
                 if not content_status:
433
                     child_nb = child_nb+1
524
                     child_nb = child_nb+1
441
     def get_status(self) -> ContentStatus:
532
     def get_status(self) -> ContentStatus:
442
         return ContentStatus(self.status, self.type.__str__())
533
         return ContentStatus(self.status, self.type.__str__())
443
 
534
 
444
-
445
     def get_last_action(self) -> ActionDescription:
535
     def get_last_action(self) -> ActionDescription:
446
         return ActionDescription(self.revision_type)
536
         return ActionDescription(self.revision_type)
447
 
537
 
538
+    def get_last_activity_date(self) -> datetime_root.datetime:
539
+        last_revision_date = self.updated
540
+        for revision in self.revisions:
541
+            if revision.updated > last_revision_date:
542
+                last_revision_date = revision.updated
543
+
544
+        for child in self.children:
545
+            if child.updated > last_revision_date:
546
+                last_revision_date = child.updated
547
+        return last_revision_date
448
 
548
 
449
     def get_comments(self):
549
     def get_comments(self):
450
         children = []
550
         children = []
466
 
566
 
467
         return last_comment
567
         return last_comment
468
 
568
 
469
-
470
     def get_previous_revision(self) -> 'ContentRevisionRO':
569
     def get_previous_revision(self) -> 'ContentRevisionRO':
471
         rev_ids = [revision.revision_id for revision in self.revisions]
570
         rev_ids = [revision.revision_id for revision in self.revisions]
472
         rev_ids.sort()
571
         rev_ids.sort()
485
         # see http://stackoverflow.com/questions/12618567/problems-running-beautifulsoup4-within-apache-mod-python-django
584
         # see http://stackoverflow.com/questions/12618567/problems-running-beautifulsoup4-within-apache-mod-python-django
486
         return BeautifulSoup(self.description, 'html.parser').text
585
         return BeautifulSoup(self.description, 'html.parser').text
487
 
586
 
587
+    def get_allowed_content_types(self):
588
+        types = []
589
+        try:
590
+            allowed_types = self.properties['allowed_content']
591
+            for type_label, is_allowed in allowed_types.items():
592
+                if is_allowed:
593
+                    types.append(ContentType(type_label))
594
+        except Exception as e:
595
+            print(e.__str__())
596
+            print('----- /*\ *****')
597
+            raise ValueError('No allowed content property')
598
+
599
+        return ContentType.sorted(types)
600
+
488
 
601
 
489
 class ContentChecker(object):
602
 class ContentChecker(object):
490
 
603
 

+ 147 - 37
tracim/tracim/model/serializers.py Visa fil

2
 import types
2
 import types
3
 
3
 
4
 from bs4 import BeautifulSoup
4
 from bs4 import BeautifulSoup
5
+from babel.dates import format_timedelta
6
+from babel.dates import format_datetime
7
+
8
+from datetime import datetime
5
 import tg
9
 import tg
10
+from tg.i18n import ugettext as _
6
 from tg.util import LazyString
11
 from tg.util import LazyString
7
 from tracim.lib.base import logger
12
 from tracim.lib.base import logger
8
 from tracim.lib.utils import exec_time_monitor
13
 from tracim.lib.utils import exec_time_monitor
58
     """ constants that are used for serialization / dictification of models"""
63
     """ constants that are used for serialization / dictification of models"""
59
     ADMIN_WORKSPACE = 'ADMIN_WORKSPACE'
64
     ADMIN_WORKSPACE = 'ADMIN_WORKSPACE'
60
     ADMIN_WORKSPACES = 'ADMIN_WORKSPACES'
65
     ADMIN_WORKSPACES = 'ADMIN_WORKSPACES'
66
+    CONTENT_LIST = 'CONTENT_LIST'
61
     CURRENT_USER = 'CURRENT_USER'
67
     CURRENT_USER = 'CURRENT_USER'
62
     DEFAULT = 'DEFAULT' # default context. This will allow to define a serialization method to be used by default
68
     DEFAULT = 'DEFAULT' # default context. This will allow to define a serialization method to be used by default
63
     EMAIL_NOTIFICATION = 'EMAIL_NOTIFICATION'
69
     EMAIL_NOTIFICATION = 'EMAIL_NOTIFICATION'
64
     FILE = 'FILE'
70
     FILE = 'FILE'
65
     FILES = 'FILES'
71
     FILES = 'FILES'
66
     FOLDER = 'FOLDER'
72
     FOLDER = 'FOLDER'
73
+    FOLDER_CONTENT_LIST = 'FOLDER_CONTENT_LIST'
67
     FOLDERS = 'FOLDERS'
74
     FOLDERS = 'FOLDERS'
68
     MENU_API = 'MENU_API'
75
     MENU_API = 'MENU_API'
69
     MENU_API_BUILD_FROM_TREE_ITEM = 'MENU_API_BUILD_FROM_TREE_ITEM'
76
     MENU_API_BUILD_FROM_TREE_ITEM = 'MENU_API_BUILD_FROM_TREE_ITEM'
265
     result = DictLikeClass(
272
     result = DictLikeClass(
266
         id = content.content_id,
273
         id = content.content_id,
267
         label = content.label if content.label else content.file_name,
274
         label = content.label if content.label else content.file_name,
268
-        icon = ContentType.icon(content.type),
275
+        icon = ContentType.get_icon(content.type),
269
         status = context.toDict(content.get_status()),
276
         status = context.toDict(content.get_status()),
270
         folder = context.toDict(DictLikeClass(id = content.parent.content_id if content.parent else None)),
277
         folder = context.toDict(DictLikeClass(id = content.parent.content_id if content.parent else None)),
271
         workspace = context.toDict(content.workspace),
278
         workspace = context.toDict(content.workspace),
362
             content = data_container.description,
369
             content = data_container.description,
363
             created = data_container.created,
370
             created = data_container.created,
364
             label = data_container.label,
371
             label = data_container.label,
365
-            icon = ContentType.icon(content.type),
372
+            icon = ContentType.get_icon(content.type),
366
             owner = context.toDict(data_container.owner),
373
             owner = context.toDict(data_container.owner),
367
             status = context.toDict(data_container.get_status()),
374
             status = context.toDict(data_container.get_status()),
368
             links = context.toDict(content.extract_links_from_content(data_container.description)),
375
             links = context.toDict(content.extract_links_from_content(data_container.description)),
394
         return DictLikeClass(
401
         return DictLikeClass(
395
             content = item.description,
402
             content = item.description,
396
             created = item.created,
403
             created = item.created,
397
-            icon = ContentType.icon(item.type),
404
+            icon = ContentType.get_icon(item.type),
398
             id = item.content_id,
405
             id = item.content_id,
399
             label = item.label,
406
             label = item.label,
400
             links = context.toDict(item.extract_links_from_content(item.description)),
407
             links = context.toDict(item.extract_links_from_content(item.description)),
411
         return DictLikeClass(
418
         return DictLikeClass(
412
             content = item.description,
419
             content = item.description,
413
             created = item.created,
420
             created = item.created,
414
-            icon = ContentType.icon(item.type),
421
+            created_as_delta = item.created_as_delta(),
422
+            icon = ContentType.get_icon(item.type),
415
             id = item.content_id,
423
             id = item.content_id,
416
             label = item.label,
424
             label = item.label,
417
             owner = context.toDict(item.owner),
425
             owner = context.toDict(item.owner),
432
     if content.type==ContentType.Thread:
440
     if content.type==ContentType.Thread:
433
         return DictLikeClass(
441
         return DictLikeClass(
434
             id = content.content_id,
442
             id = content.content_id,
435
-            label = content.label,
436
-            status = context.toDict(content.get_status()),
437
-            folder = context.toDict(content.parent),
438
-            comment_nb = len(content.get_comments())
443
+            url=ContentType.fill_url(content),
444
+            label=content.get_label(),
445
+            status=context.toDict(content.get_status()),
446
+            folder=context.toDict(content.parent),
447
+            workspace=context.toDict(content.workspace) if content.workspace else None,
448
+            comment_nb=len(content.get_comments())
439
         )
449
         )
440
 
450
 
441
     if content.type==ContentType.Folder:
451
     if content.type==ContentType.Folder:
514
 
524
 
515
     result = None
525
     result = None
516
     if content.type==ContentType.Folder:
526
     if content.type==ContentType.Folder:
527
+        allowed_content = DictLikeClass(content.properties['allowed_content']),
528
+
517
         result = DictLikeClass(
529
         result = DictLikeClass(
518
-            id = content.content_id,
519
-            label = content.label,
520
-            created = content.created,
521
-            workspace = context.toDict(content.workspace),
522
-            allowed_content = DictLikeClass(content.properties['allowed_content']),
523
-            selected_revision = 'latest',
524
-            status = context.toDict(content.get_status()),
525
-            owner = context.toDict(content.owner),
526
-            thread_nb = DictLikeClass(
527
-                all = thread_nb_all,
528
-                open = thread_nb_open,
529
-            ),
530
-            file_nb = DictLikeClass(
531
-                all = file_nb_all,
532
-                open = file_nb_open,
533
-            ),
534
-            folder_nb = DictLikeClass(
535
-                all = folder_nb_all,
536
-                open = folder_nb_open,
537
-            ),
538
-            page_nb = DictLikeClass(
539
-                all = page_nb_all,
540
-                open = page_nb_open,
541
-            ),
542
-            content_nb = DictLikeClass(all = content_nb_all)
530
+            id=content.content_id,
531
+            label=content.label,
532
+            created=content.created,
533
+            workspace=context.toDict(content.workspace),
534
+            allowed_content=DictLikeClass(content.properties['allowed_content']),
535
+            allowed_content_types=context.toDict(content.get_allowed_content_types()),
536
+            selected_revision='latest',
537
+            status=context.toDict(content.get_status()),
538
+            owner=context.toDict(content.owner),
539
+            thread_nb=DictLikeClass(all=thread_nb_all,
540
+                                    open=thread_nb_open),
541
+            file_nb=DictLikeClass(all=file_nb_all,
542
+                                  open=file_nb_open),
543
+            folder_nb=DictLikeClass(all=folder_nb_all,
544
+                                    open=folder_nb_open),
545
+            page_nb=DictLikeClass(all=page_nb_all,
546
+                                  open=page_nb_open),
547
+            content_nb=DictLikeClass(all = content_nb_all)
543
         )
548
         )
544
 
549
 
545
     elif content.type==ContentType.Page:
550
     elif content.type==ContentType.Page:
558
     return result
563
     return result
559
 
564
 
560
 
565
 
561
-from tg import cache
566
+@pod_serializer(Content, CTX.CONTENT_LIST)
567
+def serialize_content_for_general_list(content: Content, context: Context):
568
+    content_type = ContentType(content.type)
569
+
570
+    last_activity_date = content.get_last_activity_date()
571
+    last_activity_date_formatted = format_datetime(last_activity_date,
572
+                                                   locale=tg.i18n.get_lang()[0])
573
+    last_activity_label = format_timedelta(datetime.now() - last_activity_date,
574
+                                           locale=tg.i18n.get_lang()[0])
575
+    last_activity_label = last_activity_label.replace(' ', '\u00A0') # espace insécable
576
+
577
+    return DictLikeClass(
578
+        id=content.content_id,
579
+        folder = DictLikeClass({'id': content.parent_id}) if content.parent else None,
580
+        workspace=context.toDict(content.workspace) if content.workspace else None,
581
+        label=content.get_label(),
582
+        url=ContentType.fill_url(content),
583
+        type=DictLikeClass(content_type.toDict()),
584
+        status=context.toDict(content.get_status()),
585
+        last_activity = DictLikeClass({'date': last_activity_date,
586
+                                       'label': last_activity_date_formatted,
587
+                                       'delta': last_activity_label})
588
+    )
589
+
590
+@pod_serializer(Content, CTX.FOLDER_CONTENT_LIST)
591
+def serialize_content_for_folder_content_list(content: Content, context: Context):
592
+    content_type = ContentType(content.type)
593
+
594
+    last_activity_date = content.get_last_activity_date()
595
+    last_activity_date_formatted = format_datetime(last_activity_date,
596
+                                                   locale=tg.i18n.get_lang()[0])
597
+    last_activity_label = format_timedelta(datetime.now() - last_activity_date,
598
+                                           locale=tg.i18n.get_lang()[0])
599
+    last_activity_label = last_activity_label.replace(' ', '\u00A0') # espace insécable
600
+
601
+
602
+    item = None
603
+    if ContentType.Thread == content.type:
604
+        item = Context(CTX.THREADS).toDict(content)
605
+        item.type = context.toDict(content_type)
606
+        item.folder = DictLikeClass({'id': content.parent_id}) if content.parent else None
607
+        item.workspace = DictLikeClass({'id': content.workspace.workspace_id}) if content.workspace else None
608
+        item.last_activity = DictLikeClass({'date': last_activity_date,
609
+                                            'label': last_activity_date_formatted,
610
+                                            'delta': last_activity_label})
611
+
612
+        comments = content.get_comments()
613
+        if len(comments)>1:
614
+            item.notes = _('{nb} messages').format(nb=len(comments))
615
+        else:
616
+            item.notes = _('1 message')
617
+
618
+    elif ContentType.File == content.type:
619
+        item = Context(CTX.CONTENT_LIST).toDict(content)
620
+        if len(content.revisions)>1:
621
+            item.notes = _('{nb} revisions').format(nb=len(content.revisions))
622
+        else:
623
+            item.notes = _('1 revision')
624
+
625
+    elif ContentType.Folder == content.type:
626
+        item = Context(CTX.CONTENT_LIST).toDict(content)
627
+        item.notes = ''
628
+
629
+        folder_nb = content.get_child_nb(ContentType.Folder)
630
+        if folder_nb == 1:
631
+            item.notes += _('1 subfolder<br/>\n')
632
+        elif folder_nb > 1:
633
+            item.notes += _('{} subfolders<br/>').format(folder_nb)
634
+
635
+        file_nb = content.get_child_nb(ContentType.File, ContentStatus.OPEN)
636
+        if file_nb == 1:
637
+            item.notes += _('1 open file<br/>\n')
638
+        elif file_nb > 1:
639
+            item.notes += _('{} open files<br/>').format(file_nb)
640
+
641
+        thread_nb = content.get_child_nb(ContentType.Thread, ContentStatus.OPEN)
642
+        if thread_nb == 1:
643
+            item.notes += _('1 open thread<br/>\n')
644
+        elif thread_nb > 1:
645
+            item.notes += _('{} open threads<br/>').format(thread_nb)
646
+
647
+        page_nb = content.get_child_nb(ContentType.Page, ContentStatus.OPEN)
648
+        if page_nb == 1:
649
+            item.notes += _('1 open page<br/>\n')
650
+        elif page_nb > 1:
651
+            item.notes += _('{} open pages<br/>').format(page_nb)
652
+    else:
653
+        item = Context(CTX.CONTENT_LIST).toDict(content)
654
+        item.notes = ''
655
+
656
+    return item
657
+
658
+
659
+@pod_serializer(ContentType, CTX.DEFAULT)
660
+def serialize_breadcrumb_item(content_type: ContentType, context: Context):
661
+    return DictLikeClass(content_type.toDict())
562
 
662
 
563
 @pod_serializer(Content, CTX.SEARCH)
663
 @pod_serializer(Content, CTX.SEARCH)
564
 def serialize_content_for_search_result(content: Content, context: Context):
664
 def serialize_content_for_search_result(content: Content, context: Context):
587
         if comments:
687
         if comments:
588
             last_comment_datetime = max(last_comment_datetime, max(comment.updated for comment in comments))
688
             last_comment_datetime = max(last_comment_datetime, max(comment.updated for comment in comments))
589
 
689
 
690
+        content_type = ContentType(content.type)
590
         result = DictLikeClass(
691
         result = DictLikeClass(
591
             id = content.content_id,
692
             id = content.content_id,
693
+            type = DictLikeClass(content_type.toDict()),
592
             parent = context.toDict(content.parent),
694
             parent = context.toDict(content.parent),
593
             workspace = context.toDict(content.workspace),
695
             workspace = context.toDict(content.workspace),
594
-            type = content.type,
595
 
696
 
596
             content = data_container.description,
697
             content = data_container.description,
597
             content_raw = data_container.description_as_raw_text(),
698
             content_raw = data_container.description_as_raw_text(),
598
 
699
 
599
             created = data_container.created,
700
             created = data_container.created,
701
+            created_as_delta = data_container.created_as_delta(),
600
             label = data_container.label,
702
             label = data_container.label,
601
-            icon = ContentType.icon(content.type),
703
+            icon = ContentType.get_icon(content.type),
602
             owner = context.toDict(data_container.owner),
704
             owner = context.toDict(data_container.owner),
603
             status = context.toDict(data_container.get_status()),
705
             status = context.toDict(data_container.get_status()),
604
             breadcrumb = context.toDict(breadcrumbs),
706
             breadcrumb = context.toDict(breadcrumbs),
605
-            last_activity = last_comment_datetime
707
+            last_activity=last_comment_datetime,
708
+            last_activity_as_delta=content.datetime_as_delta(last_comment_datetime)
606
         )
709
         )
607
 
710
 
608
         if content.type==ContentType.File:
711
         if content.type==ContentType.File:
663
     """
766
     """
664
     result = DictLikeClass()
767
     result = DictLikeClass()
665
     result['id'] = role_type.role_type_id
768
     result['id'] = role_type.role_type_id
769
+    result['icon'] = role_type.icon
666
     result['label'] = role_type.role_label
770
     result['label'] = role_type.role_label
667
     result['style'] = role_type.css_style
771
     result['style'] = role_type.css_style
668
     return result
772
     return result
738
     """
842
     """
739
     result = DictLikeClass()
843
     result = DictLikeClass()
740
     result['id'] = role.user_id
844
     result['id'] = role.user_id
845
+    result['icon'] = role.icon
741
     result['name'] = role.user.display_name
846
     result['name'] = role.user.display_name
742
     result['role'] = role.role
847
     result['role'] = role.role
743
     result['style'] = role.style
848
     result['style'] = role.style
744
     result['role_description'] = role.role_as_label()
849
     result['role_description'] = role.role_as_label()
745
     result['email'] = role.user.email
850
     result['email'] = role.user.email
851
+    result['user'] = role.user
852
+    result['notifications_subscribed'] = role.do_notify
746
     return result
853
     return result
747
 
854
 
748
 
855
 
757
     """
864
     """
758
     result = DictLikeClass()
865
     result = DictLikeClass()
759
     result['id'] = role.role
866
     result['id'] = role.role
867
+    result['icon'] = role.icon
760
     result['label'] = role.role_as_label()
868
     result['label'] = role.role_as_label()
761
     result['style'] = RoleType(role.role).css_style
869
     result['style'] = RoleType(role.role).css_style
762
     result['workspace'] =  context.toDict(role.workspace)
870
     result['workspace'] =  context.toDict(role.workspace)
871
+    result['user'] = role.user
763
     result['notifications_subscribed'] = role.do_notify
872
     result['notifications_subscribed'] = role.do_notify
764
 
873
 
765
     # result['workspace_name'] = role.workspace.label
874
     # result['workspace_name'] = role.workspace.label
816
     result['created'] = workspace.created
925
     result['created'] = workspace.created
817
     result['members'] = context.toDict(workspace.roles)
926
     result['members'] = context.toDict(workspace.roles)
818
     result['member_nb'] = len(workspace.roles)
927
     result['member_nb'] = len(workspace.roles)
928
+    result['allowed_content_types'] = context.toDict(workspace.get_allowed_content_types())
819
 
929
 
820
     return result
930
     return result
821
 
931
 

+ 158 - 9
tracim/tracim/public/assets/css/dashboard.css Visa fil

23
  */
23
  */
24
 .navbar-fixed-top {
24
 .navbar-fixed-top {
25
   border: 0;
25
   border: 0;
26
-  background-color: #f5f5f5;
27
-  border-bottom: 1px solid #CCC;
26
+  /* background-color: #f5f5f5;*/
27
+  border-bottom: 0px solid #CCF;
28
+
29
+
30
+  background-color: #555;
31
+      color: #DDD;
28
 }
32
 }
29
 
33
 
30
 .navbar-fixed-top-transparent {
34
 .navbar-fixed-top-transparent {
31
   border: 0;
35
   border: 0;
32
   background-color: #f5f5f5;
36
   background-color: #f5f5f5;
37
+    background-color: #555;
33
   background-color: transparent;
38
   background-color: transparent;
34
 }
39
 }
35
 
40
 
37
     border: 0;
42
     border: 0;
38
 }
43
 }
39
 
44
 
45
+.navbar-fixed-top a, #sidebar #toggle-left-sidebar-width {
46
+    color: #DDD;
47
+}
48
+
40
 /*
49
 /*
41
  * Sidebar
50
  * Sidebar
42
  */
51
  */
56
     padding: 20px;
65
     padding: 20px;
57
     overflow-x: hidden;
66
     overflow-x: hidden;
58
     overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */
67
     overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */
59
-    background-color: #f5f5f5;
68
+/*    background-color: #333;
69
+      color: #FFF;*/
70
+    background-color: #555;
71
+      color: #DDD;
60
     border-right: 1px solid #CCC;
72
     border-right: 1px solid #CCC;
61
-    
73
+
62
   }
74
   }
63
 }
75
 }
64
 
76
 
65
 #sidebar-right {
77
 #sidebar-right {
66
   overflow-x: visible;
78
   overflow-x: visible;
67
   overflow-y: auto;
79
   overflow-y: auto;
68
-  
80
+    background-color: #F5F5F5;
81
+    border-left: 1px solid #CCC;
82
+
69
 }
83
 }
70
 
84
 
71
 /* Sidebar navigation */
85
 /* Sidebar navigation */
117
   border-radius: 50%;
131
   border-radius: 50%;
118
 }
132
 }
119
 
133
 
120
-.page-header {
121
-    font-size: 20px;
134
+h1.page-header {
135
+    font-size: 30px;
122
 }
136
 }
123
 
137
 
124
 /*************************************
138
 /*************************************
155
 .tracim-status-selected { background-color: #EEE; }
169
 .tracim-status-selected { background-color: #EEE; }
156
 .tracim-panel-separator { border-width: 12px 0 0 0; }
170
 .tracim-panel-separator { border-width: 12px 0 0 0; }
157
 
171
 
158
-.tracim-timeline-item {}
159
-.tracim-timeline-item-content { margin-left: 12px; border-left: 8px solid #EEE; padding: 0 0.5em; }
172
+.t-status-open-color { color: #759ac5; }
173
+.t-status-closed-validated-color { color: #1fdb11;}
174
+.t-status-closed-unvalidated-color { color: #F00;}
175
+.t-status-closed-deprecated-color { color: #ea983d;}
176
+.t-status-selected-color { background-color: #EEE; }
177
+
160
 
178
 
161
 #tracim-footer-separator { margin-bottom: 30px; }
179
 #tracim-footer-separator { margin-bottom: 30px; }
162
 .pod-footer {
180
 .pod-footer {
201
     margin-top: -1em;
219
     margin-top: -1em;
202
     margin-bottom: 0;
220
     margin-bottom: 0;
203
 }
221
 }
222
+
223
+#sidebar-right, a.btn { font-size: 1.2em; text-align: left;}
224
+#sidebar-right .btn-group-vertical { width: 100%; }
225
+
226
+th { text-align: center; }
227
+
228
+.t-green { color: green; }
229
+.t-orange { color: orange; }
230
+.t-red { color: red; }
231
+.tracim-less-visible { color: #999; } /* TODO REMOVE THIS CSS */
232
+.t-less-visible { color: #999; }
233
+.t-less-visible-border, .page-header.t-less-visible-border { border-color: #999; }
234
+
235
+.t-folder-color { color: #CCCC00; }
236
+.t-folder-color-border, .page-header.t-folder-color-border  { border-color: #CCCC00; }
237
+
238
+.t-thread-color { color: #428BCA; }
239
+.t-thread-color-border, .page-header.t-thread-color-border  { border-color: #428BCA; }
240
+
241
+.t-file-color { color: orange;}
242
+.t-file-color-border, .page-header.t-file-color-border  { border-color: orange; }
243
+
244
+.t-page-color { color: #00CC00; }
245
+.t-page-color-border, .page-header.t-page-color-border  { border-color: #00CC00; }
246
+
247
+.t-search-color { color: #AAA; }
248
+.t-search-color-border, .page-header.t-search-color-border  { border-color: #AAA; }
249
+
250
+.t-user-color { color: #428BCA; }
251
+.t-enabled-color { color: #0C0; }
252
+.t-disabled-color { color: #CCC; }
253
+
254
+.t-bg-grey {background-color: #F5F5F5; }
255
+
256
+.t-spacer-left { margin-left: 1em; }
257
+.t-spacer-right { margin-right: 1em; }
258
+
259
+.t-spacer-above { margin-top: 2em; }
260
+.t-half-spacer-above { margin-top: 1em; }
261
+.t-half-spacer-below { margin-bottom: 1em; }
262
+.t-spacer-below { margin-bottom: 2em; }
263
+
264
+a.btn.disabled { color: #CCC; }
265
+a.btn.disabled i.fa { color: #DDD; }
266
+
267
+.t-active-color { color: #428BCA; }
268
+.t-inactive-color { color: #CCC; }
269
+.t-bold { font-weight: bold; }
270
+.t-red-on-hover:Hover {
271
+    color: red;
272
+}
273
+
274
+div.t-page-header-row {
275
+    background-color: #F5F5F5;
276
+    border-bottom: 1px solid #CCC;
277
+}
278
+
279
+div.t-page-metadata-row, div.t-metadata-row {
280
+    background-color: #F5F5F5;
281
+    border-top: 1px solid #CCC;
282
+}
283
+
284
+.t-modal-form-submit-button { margin-top: 0.5em;}
285
+.modal-header h4 { font-size: 1.5em; }
286
+.modal-header { background-color: #F5F5F5; border-radius: 5px 5px 0 0; }
287
+.modal-footer { background-color: #F5F5F5; border-radius: 0 0 5px 5px; }
288
+
289
+/* left bar is almost black, so links must be almost white */
290
+#sidebar-left .btn.btn-link,
291
+#sidebar-left .list-unstyled a {
292
+    color: #DDD;
293
+}
294
+
295
+h1.page-header {
296
+    border-bottom-style: solid;
297
+    border-bottom-width: 4px;
298
+}
299
+
300
+h3 { background-color: #f5f5f5;}
301
+
302
+
303
+.sidebar .list-group-item { background-color: transparent; }
304
+
305
+/* show button disabled even when it has been selected - and has the focus) */
306
+.btn.t-inactive-color:focus { color: #CCC; background-color: #fff;}
307
+
308
+/* INFO - D.A - 2015-07-20 - Allow real fullscreen edition for page content */
309
+.mce-fullscreen .modal-dialog {
310
+    margin: 0 0 0 0;
311
+    width: 100%;
312
+    height: 100%;
313
+    min-height: 100%;
314
+    padding: 0;
315
+}
316
+
317
+.t-odd-or-even:nth-child(odd) {
318
+    background-color:#FFF;
319
+}
320
+.t-odd-or-even:nth-child(even) {
321
+    background-color:#F5F5F5;
322
+}
323
+
324
+.t-hacky-thread-comment-border-top {
325
+    border-top: 1px solid #CCC;
326
+}
327
+
328
+.t-timeline-item-icon {
329
+    margin-left: -1.5em;
330
+    float:left;
331
+}
332
+
333
+.t-timeline-item h5 {
334
+    margin-bottom: 1em;
335
+    font-size: 1.2em;
336
+}
337
+
338
+.t-timeline-item { padding: 1em; padding-left: 5em;}
339
+.t-timeline-item-content { margin-top: 0.5em; padding: 0 0.5em 0.5em 0; }
340
+
341
+.t-timeline-item-moment { font-size: 1em; color: #999; }
342
+.t-timeline-comment-delete-button { font-size: 0.8em; }
343
+
344
+#sidebar-right h3 { color: #555; margin: 0.5em 0 1em 0; }
345
+#sidebar-right h4 { color: #555; margin: 1.5em 0 1em 0; }
346
+
347
+#t-full-app-alert-message-id {
348
+    z-index: 10001;
349
+    padding: 0;
350
+    position: absolute;
351
+    top: 0;
352
+}

Filskillnaden har hållits tillbaka eftersom den är för stor
+ 4 - 0
tracim/tracim/public/assets/js/jquery.tablesorter.min.js


Binär
tracim/tracim/public/assets/jstree/themes/default/32px.png Visa fil


+ 37 - 0
tracim/tracim/public/assets/jstree/themes/tracim/style.css Visa fil

1
+.jstree-default .jstree-hovered {
2
+    background: #e7f4f9;
3
+    color: #333;
4
+    border-radius: 2px;
5
+    box-shadow: inset 0 0 1px #ccc;
6
+}
7
+.jstree-default .jstree-clicked {
8
+    background: #beebff;
9
+    border-radius: 2px;
10
+    box-shadow: inset 0 0 1px #999;
11
+    color: #333;
12
+}
13
+.jstree-default.jstree-checkbox-no-clicked .jstree-clicked.jstree-hovered {
14
+    background: #e7f4f9;
15
+    color: #333;
16
+}
17
+.jstree-default.jstree-checkbox-no-clicked > .jstree-wholerow-ul .jstree-wholerow-clicked.jstree-wholerow-hovered {
18
+    background: #e7f4f9;
19
+    color: #333;
20
+}
21
+.jstree-default .jstree-wholerow-hovered {
22
+    background: #e7f4f9;
23
+    color: #333;
24
+}
25
+.jstree-default .jstree-wholerow-clicked {
26
+    color: #333;
27
+}
28
+@media (max-width: 768px) {
29
+    .jstree-default-responsive .jstree-wholerow-hovered {
30
+        background: #e7f4f9;
31
+        color: #333;
32
+    }
33
+    .jstree-default-responsive .jstree-wholerow-clicked {
34
+        background: #beebff;
35
+        color: #333;
36
+    }
37
+}

+ 21 - 0
tracim/tracim/public/assets/tablesorter/LICENSE Visa fil

1
+The MIT License (MIT)
2
+
3
+Copyright (c) 2014 Christian Bach
4
+
5
+Permission is hereby granted, free of charge, to any person obtaining a copy
6
+of this software and associated documentation files (the "Software"), to deal
7
+in the Software without restriction, including without limitation the rights
8
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+copies of the Software, and to permit persons to whom the Software is
10
+furnished to do so, subject to the following conditions:
11
+
12
+The above copyright notice and this permission notice shall be included in all
13
+copies or substantial portions of the Software.
14
+
15
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+SOFTWARE.

+ 90 - 0
tracim/tracim/public/assets/tablesorter/README.md Visa fil

1
+tablesorter
2
+===========
3
+
4
+###Flexible client-side table sorting
5
+####Getting started
6
+
7
+To use the tablesorter plugin, include the jQuery library and the tablesorter plugin inside the head-tag of your HTML document:
8
+
9
+```html
10
+<script type="text/javascript" src="/path/to/jquery-latest.js"></script> 
11
+<script type="text/javascript" src="/path/to/jquery.tablesorter.js"></script> 
12
+```
13
+
14
+Tablesorter works on all standard HTML tables. You must include THEAD and TBODY tags:
15
+
16
+```html
17
+<table id="myTable" class="tablesorter"> 
18
+<thead> 
19
+<tr> 
20
+    <th>Last Name</th> 
21
+    <th>First Name</th> 
22
+    <th>Email</th> 
23
+    <th>Due</th> 
24
+    <th>Web Site</th> 
25
+</tr> 
26
+</thead> 
27
+<tbody> 
28
+<tr> 
29
+    <td>Smith</td> 
30
+    <td>John</td> 
31
+    <td>jsmith@gmail.com</td> 
32
+    <td>$50.00</td> 
33
+    <td>http://www.jsmith.com</td> 
34
+</tr> 
35
+<tr> 
36
+    <td>Bach</td> 
37
+    <td>Frank</td> 
38
+    <td>fbach@yahoo.com</td> 
39
+    <td>$50.00</td> 
40
+    <td>http://www.frank.com</td> 
41
+</tr> 
42
+<tr> 
43
+    <td>Doe</td> 
44
+    <td>Jason</td> 
45
+    <td>jdoe@hotmail.com</td> 
46
+    <td>$100.00</td> 
47
+    <td>http://www.jdoe.com</td> 
48
+</tr> 
49
+<tr> 
50
+    <td>Conway</td> 
51
+    <td>Tim</td> 
52
+    <td>tconway@earthlink.net</td> 
53
+    <td>$50.00</td> 
54
+    <td>http://www.timconway.com</td> 
55
+</tr> 
56
+</tbody> 
57
+</table> 
58
+```
59
+
60
+Start by telling tablesorter to sort your table when the document is loaded:
61
+
62
+```javascript
63
+$(document).ready(function() 
64
+    { 
65
+        $("#myTable").tablesorter(); 
66
+    } 
67
+); 
68
+```
69
+
70
+Click on the headers and you'll see that your table is now sortable! You can also pass in configuration options when you initialize the table. This tells tablesorter to sort on the first and second column in ascending order.
71
+
72
+```javascript
73
+$(document).ready(function() 
74
+    { 
75
+        $("#myTable").tablesorter( {sortList: [[0,0], [1,0]]} ); 
76
+    } 
77
+); 
78
+```
79
+
80
+For DateTime columns you can specify your format, like this:
81
+
82
+```javascript
83
+$(document).ready(function() 
84
+    { 
85
+        $("#myTable").tablesorter( {dateFormat: 'pt'} ); 
86
+    } 
87
+); 
88
+```
89
+
90
+The available ones (currently) are: us, pt and uk. (for pt you can use 'dd/MM/yyyy hh:mm:ss')

+ 25 - 0
tracim/tracim/public/assets/tablesorter/addons/pager/jquery.tablesorter.pager.css Visa fil

1
+div.tablesorterPager {
2
+	padding: 10px 0 10px 0;
3
+	background-color: #D6D2C2;
4
+	text-align: center;
5
+}
6
+div.tablesorterPager span {
7
+	padding: 0 5px 0 5px;
8
+}
9
+div.tablesorterPager input.prev {
10
+	width: auto;
11
+	margin-right: 10px;
12
+}
13
+div.tablesorterPager input.next {
14
+	width: auto;
15
+	margin-left: 10px;
16
+}
17
+div.tablesorterPager input {
18
+	font-size: 8px;
19
+	width: 50px;
20
+	border: 1px solid #330000;
21
+	text-align: center;
22
+}
23
+
24
+
25
+  

+ 184 - 0
tracim/tracim/public/assets/tablesorter/addons/pager/jquery.tablesorter.pager.js Visa fil

1
+(function($) {
2
+	$.extend({
3
+		tablesorterPager: new function() {
4
+			
5
+			function updatePageDisplay(c) {
6
+				var s = $(c.cssPageDisplay,c.container).val((c.page+1) + c.seperator + c.totalPages);	
7
+			}
8
+			
9
+			function setPageSize(table,size) {
10
+				var c = table.config;
11
+				c.size = size;
12
+				c.totalPages = Math.ceil(c.totalRows / c.size);
13
+				c.pagerPositionSet = false;
14
+				moveToPage(table);
15
+				fixPosition(table);
16
+			}
17
+			
18
+			function fixPosition(table) {
19
+				var c = table.config;
20
+				if(!c.pagerPositionSet && c.positionFixed) {
21
+					var c = table.config, o = $(table);
22
+					if(o.offset) {
23
+						c.container.css({
24
+							top: o.offset().top + o.height() + 'px',
25
+							position: 'absolute'
26
+						});
27
+					}
28
+					c.pagerPositionSet = true;
29
+				}
30
+			}
31
+			
32
+			function moveToFirstPage(table) {
33
+				var c = table.config;
34
+				c.page = 0;
35
+				moveToPage(table);
36
+			}
37
+			
38
+			function moveToLastPage(table) {
39
+				var c = table.config;
40
+				c.page = (c.totalPages-1);
41
+				moveToPage(table);
42
+			}
43
+			
44
+			function moveToNextPage(table) {
45
+				var c = table.config;
46
+				c.page++;
47
+				if(c.page >= (c.totalPages-1)) {
48
+					c.page = (c.totalPages-1);
49
+				}
50
+				moveToPage(table);
51
+			}
52
+			
53
+			function moveToPrevPage(table) {
54
+				var c = table.config;
55
+				c.page--;
56
+				if(c.page <= 0) {
57
+					c.page = 0;
58
+				}
59
+				moveToPage(table);
60
+			}
61
+						
62
+			
63
+			function moveToPage(table) {
64
+				var c = table.config;
65
+				if(c.page < 0 || c.page > (c.totalPages-1)) {
66
+					c.page = 0;
67
+				}
68
+				
69
+				renderTable(table,c.rowsCopy);
70
+			}
71
+			
72
+			function renderTable(table,rows) {
73
+				
74
+				var c = table.config;
75
+				var l = rows.length;
76
+				var s = (c.page * c.size);
77
+				var e = (s + c.size);
78
+				if(e > rows.length ) {
79
+					e = rows.length;
80
+				}
81
+				
82
+				
83
+				var tableBody = $(table.tBodies[0]);
84
+				
85
+				// clear the table body
86
+				
87
+				$.tablesorter.clearTableBody(table);
88
+				
89
+				for(var i = s; i < e; i++) {
90
+					
91
+					//tableBody.append(rows[i]);
92
+					
93
+					var o = rows[i];
94
+					var l = o.length;
95
+					for(var j=0; j < l; j++) {
96
+						
97
+						tableBody[0].appendChild(o[j]);
98
+
99
+					}
100
+				}
101
+				
102
+				fixPosition(table,tableBody);
103
+				
104
+				$(table).trigger("applyWidgets");
105
+				
106
+				if( c.page >= c.totalPages ) {
107
+        			moveToLastPage(table);
108
+				}
109
+				
110
+				updatePageDisplay(c);
111
+			}
112
+			
113
+			this.appender = function(table,rows) {
114
+				
115
+				var c = table.config;
116
+				
117
+				c.rowsCopy = rows;
118
+				c.totalRows = rows.length;
119
+				c.totalPages = Math.ceil(c.totalRows / c.size);
120
+				
121
+				renderTable(table,rows);
122
+			};
123
+			
124
+			this.defaults = {
125
+				size: 10,
126
+				offset: 0,
127
+				page: 0,
128
+				totalRows: 0,
129
+				totalPages: 0,
130
+				container: null,
131
+				cssNext: '.next',
132
+				cssPrev: '.prev',
133
+				cssFirst: '.first',
134
+				cssLast: '.last',
135
+				cssPageDisplay: '.pagedisplay',
136
+				cssPageSize: '.pagesize',
137
+				seperator: "/",
138
+				positionFixed: true,
139
+				appender: this.appender
140
+			};
141
+			
142
+			this.construct = function(settings) {
143
+				
144
+				return this.each(function() {	
145
+					
146
+					config = $.extend(this.config, $.tablesorterPager.defaults, settings);
147
+					
148
+					var table = this, pager = config.container;
149
+				
150
+					$(this).trigger("appendCache");
151
+					
152
+					config.size = parseInt($(".pagesize",pager).val());
153
+					
154
+					$(config.cssFirst,pager).click(function() {
155
+						moveToFirstPage(table);
156
+						return false;
157
+					});
158
+					$(config.cssNext,pager).click(function() {
159
+						moveToNextPage(table);
160
+						return false;
161
+					});
162
+					$(config.cssPrev,pager).click(function() {
163
+						moveToPrevPage(table);
164
+						return false;
165
+					});
166
+					$(config.cssLast,pager).click(function() {
167
+						moveToLastPage(table);
168
+						return false;
169
+					});
170
+					$(config.cssPageSize,pager).change(function() {
171
+						setPageSize(table,parseInt($(this).val()));
172
+						return false;
173
+					});
174
+				});
175
+			};
176
+			
177
+		}
178
+	});
179
+	// extend plugin scope
180
+	$.fn.extend({
181
+        tablesorterPager: $.tablesorterPager.construct
182
+	});
183
+	
184
+})(jQuery);				

+ 26 - 0
tracim/tracim/public/assets/tablesorter/bower.json Visa fil

1
+{
2
+  "name": "tablesorter",
3
+  "version": "2.0.5",
4
+  "homepage": "https://github.com/christianbach/tablesorter.git",
5
+  "authors": [
6
+    "Christian Bach"
7
+  ],
8
+  "description": "Flexible client-side table sorting",
9
+  "main": [
10
+    "jquery.metadata.js",
11
+    "jquery.tablesorter.min.js"
12
+  ],
13
+  "keywords": [
14
+    "client-side",
15
+    "sort",
16
+    "table"
17
+  ],
18
+  "license": "MIT,GPL",
19
+  "ignore": [
20
+    "**/.*",
21
+    "node_modules",
22
+    "bower_components",
23
+    "test",
24
+    "tests"
25
+  ]
26
+}

+ 26 - 0
tracim/tracim/public/assets/tablesorter/build.xml Visa fil

1
+<project name="tablesorter" default="default" basedir=".">
2
+
3
+    <!-- SETUP -->
4
+	<property description="Files for parsing etc." name="BUILD_DIR" value="build" />
5
+    <property description="Rhino JS Engine" name="JAR" value="${BUILD_DIR}/js.jar" />
6
+
7
+    <!-- Files names for distribution -->
8
+    <property name="TS" value="jquery.tablesorter.js" />
9
+	<property name="TS_MIN" value="jquery.tablesorter.min.js" />
10
+
11
+    <!-- MAIN -->
12
+	<target name="min">
13
+        <echo message="Building ${TS_MIN}" />
14
+        <java jar="${JAR}" fork="true">
15
+            <arg value="${BUILD_DIR}/min.js" />
16
+            <arg value="${TS}" />
17
+            <arg value="${TS_MIN}" />
18
+        </java>
19
+        <echo message="${TS_MIN} built." />
20
+    </target>
21
+
22
+   <target name="default">
23
+		<antcall target="min"/>
24
+    </target>
25
+	
26
+</project>

+ 41 - 0
tracim/tracim/public/assets/tablesorter/changelog Visa fil

1
+tablesorter changelog
2
+======================
3
+http://tablesorter.com
4
+
5
+Changes in version 2.0.3 (2008-03-17)
6
+-------------------------------------
7
+
8
+Bug fixes
9
+* Missing semicolon, broke the minified version
10
+
11
+
12
+Changes in version 2.0.2 (2008-03-14)
13
+-------------------------------------
14
+
15
+General
16
+* Added support for the new metadata plugin
17
+* Added support for jQuery 1.2.3
18
+* Added support for decimal numbers and negative and positive digits
19
+* Updated documenation and website with new examples
20
+* Removed packed version.
21
+
22
+Bug fixes
23
+* Sort force (Thanks to David Lynch)
24
+
25
+
26
+Changes in version 2.0.1 (2007-09-17)
27
+-------------------------------------
28
+
29
+General
30
+* Removed the need for Dimensions plugin when using the pagnation plugin thanks to offset being included in the jQuery 1.2 core.
31
+* Added support for jQuery 1.2
32
+* Added new Minified version of tablesorter
33
+* Updated documenation and website with new examples
34
+
35
+Bug fixes
36
+* If row values are identical the original order is kept (Thanks to David hull)
37
+* If thead includes a table $('tbody:first', table) breaks (Thanks to David Hull)
38
+
39
+Speed improvements:
40
+* appendToTable, setting innerHTML to "" before appending new content to table body.
41
+* zebra widget. (Thanks to James Dempster)

+ 43 - 0
tracim/tracim/public/assets/tablesorter/docs/assets/ajax-content.html Visa fil

1
+	<tr>
2
+				<td>Peter</td>
3
+				<td>Parker</td>
4
+				<td>28</td>
5
+				<td>$9.99</td>
6
+				<td>20%</td>
7
+				
8
+				<td>Jul 6, 2006 8:14 AM</td>
9
+			</tr>
10
+			<tr>
11
+				<td>John</td>
12
+				<td>Hood</td>
13
+				<td>33</td>
14
+				<td>$19.99</td>
15
+				<td>25%</td>
16
+				
17
+				<td>Dec 10, 2002 5:14 AM</td>
18
+			</tr>
19
+			<tr>
20
+				<td>Clark</td>
21
+				<td>Kent</td>
22
+				<td>18</td>
23
+				<td>$15.89</td>
24
+				<td>44%</td>
25
+				<td>Jan 12, 2003 11:14 AM</td>
26
+			</tr>
27
+			<tr>
28
+				<td>Bruce</td>
29
+				<td>Almighty</td>
30
+				<td>45</td>
31
+				<td>$153.19</td>
32
+				<td>44%</td>
33
+				
34
+				<td>Jan 18, 2001 9:12 AM</td>
35
+			</tr>
36
+			<tr>
37
+				<td>Bruce</td>
38
+				<td>Evans</td>
39
+				<td>22</td>
40
+				<td>$13.19</td>
41
+				<td>11%</td>
42
+				<td>Jan 18, 2007 9:12 AM</td>
43
+			</tr>

+ 29 - 0
tracim/tracim/public/assets/tablesorter/docs/css/jq.css Visa fil

1
+body,div,h1{font-family:'trebuchet ms', verdana, arial;margin:0;padding:0;}
2
+body{background-color:#fff;color:#333;font-size:small;margin:0;padding:0;}
3
+h1{font-size:large;font-weight:400;margin:0;}
4
+h2{color:#333;font-size:small;font-weight:400;margin:0;}
5
+pre{background-color:#eee;border:1px solid #ddd;border-left-width:5px;color:#333;font-size:small;overflow-x:auto;padding:15px;}
6
+pre.normal{background-color:transparent;border:none;border-left-width:0;overflow-x:auto;}
7
+#logo{background:url(images/jq.png);display:block;float:right;height:31px;margin-right:10px;margin-top:10px;width:110px;}
8
+#main{margin:0 20px 20px;padding:0 15px 15px 0;}
9
+#content{padding:20px;}
10
+#busy{background-color:#e95555;border:1px ridge #ccc;color:#eee;display:none;padding:3px;position:absolute;right:7px;top:7px;}
11
+hr{height:1px;}
12
+code{font-size:108%;font-style:normal;padding:0;}
13
+ul{color:#333;list-style:square;}
14
+#banner{margin:20px;padding-bottom:10px;text-align:left;}
15
+#banner *{color:#232121;font-family:Georgia, Palatino, Times New Roman;font-size:30px;font-style:normal;font-weight:400;margin:0;padding:0;}
16
+#banner h1{display:block;float:left;}
17
+#banner h1 em{color:#6cf;}
18
+#banner h2{float:right;font-size:26px;margin:10px 10px -10px -10px;}
19
+#banner h3{clear:both;display:block;font-size:12px;margin-top:-20px;}
20
+#banner a{border-top:1px solid #888;display:block;font-size:14px;margin:5px 0 0;padding:10px 0 0;text-align:right;width:auto;}
21
+a.external{background-image:url(../img/external.png);background-position:center right;background-repeat:no-repeat;padding-right:12px;}
22
+form{font-size:10pt;margin-bottom:20px;width:auto;}
23
+form fieldset{padding:10px;text-align:left;width:140px;}
24
+div#main h1{border-bottom:1px solid #CDCDCD;display:block;margin-top:20px;padding:10px 0 2px;}
25
+table#tablesorter-demo {margin: 10px 0 0 0;}
26
+table#options *{font-size:small;}
27
+p.tip em {padding: 2px; background-color: #6cf; color: #FFF;}
28
+p.tip.update em {background-color: #FF0000;}
29
+div.digg {float: right;}

+ 119 - 0
tracim/tracim/public/assets/tablesorter/docs/example-ajax.html Visa fil

1
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us">
4
+<head>
5
+	<title>jQuery plugin: Tablesorter 2.0 - Appending table data with ajax</title>
6
+	<link rel="stylesheet" href="css/jq.css" type="text/css" media="print, projection, screen" />
7
+	<link rel="stylesheet" href="../themes/blue/style.css" type="text/css" id="" media="print, projection, screen" />
8
+	<script type="text/javascript" src="../jquery-latest.js"></script>
9
+	<script type="text/javascript" src="../jquery.tablesorter.js"></script>
10
+	<script type="text/javascript" src="js/chili/chili-1.8b.js"></script>
11
+	<script type="text/javascript" src="js/docs.js"></script>
12
+	<script type="text/javascript" src="js/examples.js"></script>
13
+	<script type="text/javascript" id="js">
14
+	$(document).ready(function() {
15
+	$("table").tablesorter();
16
+	$("#ajax-append").click(function() {
17
+		 $.get("assets/ajax-content.html", function(html) {
18
+		 	// append the "ajax'd" data to the table body
19
+		 	$("table tbody").append(html);
20
+			// let the plugin know that we made a update
21
+			$("table").trigger("update");
22
+			// set sorting column and direction, this will sort on the first and third column
23
+			var sorting = [[2,1],[0,0]];
24
+			// sort on the first column
25
+			$("table").trigger("sorton",[sorting]);
26
+		});
27
+		return false;
28
+	});
29
+}); 		
30
+	</script>
31
+</head>
32
+<body>
33
+<div id="banner">	
34
+	<h1>table<em>sorter</em></h1>
35
+	<h2>Appending table data with ajax</h2>
36
+	<h3>Flexible client-side table sorting</h3>
37
+	<a href="index.html">Back to documentation</a>
38
+</div>
39
+<div id="main">
40
+	<h1>Demo</h1>
41
+	<div id="demo">
42
+		<table cellspacing="1" class="tablesorter">
43
+			<thead>
44
+				<tr>
45
+					<th>First Name</th>
46
+					<th>Last Name</th>
47
+					<th>Age</th>
48
+					<th>Total</th>
49
+					<th>Discount</th>
50
+					<th>Date</th>
51
+	
52
+				</tr>
53
+			</thead>
54
+			<tbody>
55
+				<tr>
56
+					<td>Peter</td>
57
+					<td>Parker</td>
58
+					<td>28</td>
59
+					<td>$9.99</td>
60
+					<td>20%</td>
61
+					
62
+					<td>Jul 6, 2006 8:14 AM</td>
63
+				</tr>
64
+				<tr>
65
+					<td>John</td>
66
+					<td>Hood</td>
67
+					<td>33</td>
68
+					<td>$19.99</td>
69
+					<td>25%</td>
70
+					
71
+					<td>Dec 10, 2002 5:14 AM</td>
72
+				</tr>
73
+				<tr>
74
+					<td>Clark</td>
75
+					<td>Kent</td>
76
+					<td>18</td>
77
+					<td>$15.89</td>
78
+					<td>44%</td>
79
+					<td>Jan 12, 2003 11:14 AM</td>
80
+				</tr>
81
+				<tr>
82
+					<td>Bruce</td>
83
+					<td>Almighty</td>
84
+					<td>45</td>
85
+					<td>$153.19</td>
86
+					<td>44%</td>
87
+					
88
+					<td>Jan 18, 2001 9:12 AM</td>
89
+				</tr>
90
+				<tr>
91
+					<td>Bruce</td>
92
+					<td>Evans</td>
93
+					<td>22</td>
94
+					<td>$13.19</td>
95
+					<td>11%</td>
96
+					<td>Jan 18, 2007 9:12 AM</td>
97
+				</tr>
98
+			</tbody>
99
+		</table>
100
+		<a href="#" id="ajax-append">Append new table data</a>
101
+		<br/>
102
+		<br/>
103
+	</div>
104
+	<h1>Javascript</h1>
105
+	<div id="javascript">
106
+		<pre class="javascript"></pre>
107
+	</div>
108
+	<h1>HTML</h1>
109
+	<div id="html">
110
+		<pre class="html"></pre>
111
+	</div>
112
+</div>
113
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
114
+<script type="text/javascript">
115
+_uacct = "UA-2189649-2";
116
+urchinTracker();
117
+</script>
118
+</body>
119
+</html>

+ 70 - 0
tracim/tracim/public/assets/tablesorter/docs/example-attribute-sort.html Visa fil

1
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us">
4
+<head>
5
+	<title>jQuery plugin: Tablesorter 2.0 - Sorting on a table cell attribute</title>
6
+	<link rel="stylesheet" href="css/jq.css" type="text/css" media="print, projection, screen" />
7
+	<link rel="stylesheet" href="../themes/blue/style.css" type="text/css" id="" media="print, projection, screen" />
8
+	<script type="text/javascript" src="../jquery-latest.js"></script>
9
+	<script type="text/javascript" src="../jquery.tablesorter.js"></script>
10
+	<script type="text/javascript" src="js/chili/chili-1.8b.js"></script>
11
+	<script type="text/javascript" src="js/docs.js"></script>
12
+	<script type="text/javascript" src="js/examples.js"></script>
13
+	<script type="text/javascript" id="js">$(document).ready(function() {
14
+	$("table").tablesorter();
15
+});</script>
16
+</head>
17
+<body>
18
+<div id="banner">	
19
+	<h1>table<em>sorter</em></h1>
20
+	<h2>Sorting on a table cell attribute</h2>
21
+	<h3>Flexible client-side table sorting</h3>
22
+	<a href="index.html">Back to documentation</a>
23
+</div>
24
+<div id="main">
25
+	<h1>Demo</h1>
26
+	<div id="demo">
27
+		<table cellspacing="1" class="tablesorter">
28
+			<thead>
29
+				<tr>
30
+					<th>Title</th>
31
+					<th>Priority</th>
32
+					<th>Date</th>
33
+				</tr>
34
+			</thead>
35
+			<tbody>
36
+				<tr>
37
+					<td>Earth</td>
38
+					<td data-sort-value="1">Mid</td>
39
+					<td data-sort-value="2013-06">June 2013</td>
40
+				</tr>
41
+				<tr>
42
+					<td>Pluto</td>
43
+					<td data-sort-value="2">Low</td>
44
+					<td data-sort-value="1999-05">May 1999</td>
45
+				</tr>
46
+				<tr>
47
+					<td>Sun</td>
48
+					<td data-sort-value="0">High</td>
49
+					<td data-sort-value="2002-04">April 2002</td>
50
+				</tr>
51
+			</tbody>
52
+		</table>
53
+		<br/>
54
+	</div>
55
+	<h1>Javascript</h1>
56
+	<div id="javascript">
57
+		<pre class="javascript"></pre>
58
+	</div>
59
+	<h1>HTML</h1>
60
+	<div id="html">
61
+		<pre class="html"></pre>
62
+	</div>
63
+</div>
64
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
65
+<script type="text/javascript">
66
+_uacct = "UA-2189649-2";
67
+urchinTracker();
68
+</script>
69
+</body>
70
+</html>

+ 75 - 0
tracim/tracim/public/assets/tablesorter/docs/example-empty-table.html Visa fil

1
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us">
4
+<head>
5
+	<title>jQuery plugin: Tablesorter 2.0 - Initializing tablesorter on a empty table</title>
6
+	<link rel="stylesheet" href="css/jq.css" type="text/css" media="print, projection, screen" />
7
+	<link rel="stylesheet" href="../themes/blue/style.css" type="text/css" id="" media="print, projection, screen" />
8
+	<script type="text/javascript" src="../jquery-latest.js"></script>
9
+	<script type="text/javascript" src="../jquery.tablesorter.js"></script>
10
+	<script type="text/javascript" src="js/chili/chili-1.8b.js"></script>
11
+	<script type="text/javascript" src="js/docs.js"></script>
12
+	<script type="text/javascript" src="js/examples.js"></script>
13
+	<script type="text/javascript" id="js">$(document).ready(function() {
14
+	$("table").tablesorter();
15
+	$("#append").click(function() {
16
+		// add some html
17
+		var html = "<tr><td>Peter</td><td>Parker</td><td>28</td><td>$9.99</td><td>20%</td><td>Jul 6, 2006 8:14 AM</td></tr>";
18
+		html += "<tr><td>John</td><td>Hood</td><td>33</td><td>$19.99</td><td>25%</td><td>Dec 10, 2002 5:14 AM</td></tr><tr><td>Clark</td><td>Kent</td><td>18</td><td>$15.89</td><td>44%</td><td>Jan 12, 2003 11:14 AM</td></tr>";		
19
+		html += "<tr><td>Bruce</td><td>Almighty</td><td>45</td><td>$153.19</td><td>44%</td><td>Jan 18, 2001 9:12 AM</td></tr>";
20
+		// append new html to table body 
21
+		 $("table tbody").append(html);
22
+		// let the plugin know that we made a update
23
+		$("table").trigger("update");
24
+		// set sorting column and direction, this will sort on the first and third column
25
+		var sorting = [[2,1],[0,0]];
26
+		// sort on the first column
27
+		$("table").trigger("sorton",[sorting]);
28
+		return false;
29
+	});
30
+});</script>
31
+</head>
32
+<body>
33
+<div id="banner">	
34
+	<h1>table<em>sorter</em></h1>
35
+	<h2>Initializing tablesorter on a empty table</h2>
36
+	<h3>Flexible client-side table sorting</h3>
37
+	<a href="index.html">Back to documentation</a>
38
+</div>
39
+<div id="main">
40
+	<h1>Demo</h1>
41
+	<div id="demo">
42
+		<table cellspacing="1" class="tablesorter">
43
+			<thead>
44
+				<tr>
45
+					<th>First Name</th>
46
+					<th>Last Name</th>
47
+					<th>Age</th>
48
+					<th>Total</th>
49
+					<th>Discount</th>
50
+					<th>Date</th>
51
+				</tr>
52
+			</thead>
53
+			<tbody>
54
+			</tbody>
55
+		</table>
56
+		<a href="#" id="append">Append new table data</a>
57
+		<br/>
58
+		<br/>
59
+	</div>
60
+	<h1>Javascript</h1>
61
+	<div id="javascript">
62
+		<pre class="javascript"></pre>
63
+	</div>
64
+	<h1>HTML</h1>
65
+	<div id="html">
66
+		<pre class="html"></pre>
67
+	</div>
68
+</div>
69
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
70
+<script type="text/javascript">
71
+_uacct = "UA-2189649-2";
72
+urchinTracker();
73
+</script>
74
+</body>
75
+</html>

+ 109 - 0
tracim/tracim/public/assets/tablesorter/docs/example-extending-defaults.html Visa fil

1
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us">
4
+<head>
5
+	<title>jQuery plugin: Tablesorter 2.0 - Extending default options</title>
6
+	<link rel="stylesheet" href="css/jq.css" type="text/css" media="print, projection, screen" />
7
+	<link rel="stylesheet" href="../themes/blue/style.css" type="text/css" id="" media="print, projection, screen" />
8
+	<script type="text/javascript" src="../jquery-latest.js"></script>
9
+	
10
+	<script type="text/javascript" src="../jquery.tablesorter.js"></script>
11
+	<script type="text/javascript" src="../addons/pager/jquery.tablesorter.pager.js"></script>
12
+	<script type="text/javascript" src="js/chili/chili-1.8b.js"></script>
13
+	<script type="text/javascript" src="js/docs.js"></script>
14
+	<script type="text/javascript" src="js/examples.js"></script>
15
+<script type="text/javascript" id="js">$(document).ready(function() {
16
+	// extend the default setting to always include the zebra widget.
17
+	$.tablesorter.defaults.widgets = ['zebra'];
18
+	// extend the default setting to always sort on the first column
19
+	$.tablesorter.defaults.sortList = [[0,0]];
20
+	// call the tablesorter plugin
21
+	$("table").tablesorter();
22
+}); </script>
23
+</head>
24
+<body>
25
+<div id="banner">	
26
+	<h1>table<em>sorter</em></h1>
27
+	<h2>Extending default options</h2>
28
+	<h3>Flexible client-side table sorting</h3>
29
+	<a href="index.html">Back to documentation</a>
30
+</div>
31
+<div id="main">
32
+	<h1>Demo</h1>
33
+	<div id="demo">
34
+		<table cellspacing="1" class="tablesorter">
35
+		<thead>
36
+				<tr>
37
+					<th>First Name</th>
38
+					<th>Last Name</th>
39
+					<th>Age</th>
40
+					<th>Total</th>
41
+					<th>Discount</th>
42
+					<th>Date</th>
43
+	
44
+				</tr>
45
+			</thead>
46
+			<tbody>
47
+				<tr>
48
+					<td>Peter</td>
49
+					<td>Parker</td>
50
+					<td>28</td>
51
+					<td>$9.99</td>
52
+					<td>20%</td>
53
+					
54
+					<td>Jul 6, 2006 8:14 AM</td>
55
+				</tr>
56
+				<tr>
57
+					<td>John</td>
58
+					<td>Hood</td>
59
+					<td>33</td>
60
+					<td>$19.99</td>
61
+					<td>25%</td>
62
+					
63
+					<td>Dec 10, 2002 5:14 AM</td>
64
+				</tr>
65
+				<tr>
66
+					<td>Clark</td>
67
+					<td>Kent</td>
68
+					<td>18</td>
69
+					<td>$15.89</td>
70
+					<td>44%</td>
71
+					<td>Jan 12, 2003 11:14 AM</td>
72
+				</tr>
73
+				<tr>
74
+					<td>Bruce</td>
75
+					<td>Almighty</td>
76
+					<td>45</td>
77
+					<td>$153.19</td>
78
+					<td>44%</td>
79
+					
80
+					<td>Jan 18, 2001 9:12 AM</td>
81
+				</tr>
82
+				<tr>
83
+					<td>Bruce</td>
84
+					<td>Evans</td>
85
+					<td>22</td>
86
+					<td>$13.19</td>
87
+					<td>11%</td>
88
+					<td>Jan 18, 2007 9:12 AM</td>
89
+				</tr>
90
+			</tbody>
91
+		</table>
92
+	</div>
93
+	<h1>Javascript</h1>
94
+	<div id="javascript">
95
+		<pre class="javascript"></pre>
96
+	</div>
97
+	<h1>HTML</h1>
98
+	<div id="html">
99
+		<pre class="html"></pre>
100
+	</div>
101
+</div>
102
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
103
+<script type="text/javascript">
104
+_uacct = "UA-2189649-2";
105
+urchinTracker();
106
+</script>
107
+</body>
108
+</html>
109
+

+ 108 - 0
tracim/tracim/public/assets/tablesorter/docs/example-meta-headers.html Visa fil

1
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us">
4
+<head>
5
+	<title>jQuery plugin: Tablesorter 2.0 - Disable headers using metadata</title>
6
+	<link rel="stylesheet" href="css/jq.css" type="text/css" media="print, projection, screen" />
7
+	<link rel="stylesheet" href="../themes/blue/style.css" type="text/css" id="" media="print, projection, screen" />
8
+	<script type="text/javascript" src="../jquery-latest.js"></script>
9
+	
10
+	<script type="text/javascript" src="../jquery.metadata.js"></script>
11
+	<script type="text/javascript" src="../jquery.tablesorter.js"></script>
12
+	<script type="text/javascript" src="../addons/pager/jquery.tablesorter.pager.js"></script>
13
+	<script type="text/javascript" src="js/chili/chili-1.8b.js"></script>
14
+	<script type="text/javascript" src="js/docs.js"></script>
15
+	<script type="text/javascript">
16
+		window.tableFile="table-metadata-disable.html";
17
+	</script>
18
+	<script type="text/javascript" src="js/examples.js"></script>
19
+<script type="text/javascript" id="js">$(document).ready(function() {
20
+	// call the tablesorter plugin, the magic happens in the markup
21
+	$("table").tablesorter();
22
+}); </script>
23
+</head>
24
+<body>
25
+<div id="banner">	
26
+	<h1>table<em>sorter</em></h1>
27
+	<h2>Disable headers using metadata</h2>
28
+	<h3>Flexible client-side table sorting</h3>
29
+	<a href="index.html">Back to documentation</a>
30
+</div>
31
+<div id="main">
32
+	<h1>Demo</h1>
33
+	<div id="demo">
34
+		<table cellspacing="1" class="tablesorter">
35
+				<thead>
36
+			<tr>
37
+				<th class="{sorter: false}">First Name</th>
38
+				<th>Last Name</th>
39
+				<th>Age</th>
40
+				<th>Total</th>
41
+				<th class="{sorter: false}">Discount</th>
42
+				<th>Date</th>
43
+			</tr>
44
+		</thead>
45
+	<tbody>
46
+		<tr>
47
+			<td>Peter</td>
48
+			<td>Parker</td>
49
+			<td>28</td>
50
+			<td>$9.99</td>
51
+			<td>20%</td>
52
+			
53
+			<td>Jul 6, 2006 8:14 AM</td>
54
+		</tr>
55
+		<tr>
56
+			<td>John</td>
57
+			<td>Hood</td>
58
+			<td>33</td>
59
+			<td>$19.99</td>
60
+			<td>25%</td>
61
+			
62
+			<td>Dec 10, 2002 5:14 AM</td>
63
+		</tr>
64
+		<tr>
65
+			<td>Clark</td>
66
+			<td>Kent</td>
67
+			<td>18</td>
68
+			<td>$15.89</td>
69
+			<td>44%</td>
70
+			<td>Jan 12, 2003 11:14 AM</td>
71
+		</tr>
72
+		<tr>
73
+			<td>Bruce</td>
74
+			<td>Almighty</td>
75
+			<td>45</td>
76
+			<td>$153.19</td>
77
+			<td>44%</td>
78
+			
79
+			<td>Jan 18, 2001 9:12 AM</td>
80
+		</tr>
81
+		<tr>
82
+			<td>Bruce</td>
83
+			<td>Evans</td>
84
+			<td>22</td>
85
+			<td>$13.19</td>
86
+			<td>11%</td>
87
+			<td>Jan 18, 2007 9:12 AM</td>
88
+		</tr>
89
+	</tbody>
90
+		</table>
91
+	</div>
92
+	<h1>Javascript</h1>
93
+	<div id="javascript">
94
+		<pre class="javascript"></pre>
95
+	</div>
96
+	<h1>HTML</h1>
97
+	<div id="html">
98
+		<pre class="html"></pre>
99
+	</div>
100
+</div>
101
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
102
+<script type="text/javascript">
103
+_uacct = "UA-2189649-2";
104
+urchinTracker();
105
+</script>
106
+</body>
107
+</html>
108
+

+ 107 - 0
tracim/tracim/public/assets/tablesorter/docs/example-meta-parsers.html Visa fil

1
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us">
4
+<head>
5
+	<title>jQuery plugin: Tablesorter 2.0 - Setting column parser using metadata</title>
6
+	<link rel="stylesheet" href="css/jq.css" type="text/css" media="print, projection, screen" />
7
+	<link rel="stylesheet" href="../themes/blue/style.css" type="text/css" id="" media="print, projection, screen" />
8
+	<script type="text/javascript" src="../jquery-latest.js"></script>
9
+	
10
+	<script type="text/javascript" src="../jquery.metadata.js"></script>
11
+	<script type="text/javascript" src="../jquery.tablesorter.js"></script>
12
+	<script type="text/javascript" src="../addons/pager/jquery.tablesorter.pager.js"></script>
13
+	<script type="text/javascript" src="js/chili/chili-1.8b.js"></script>
14
+	<script type="text/javascript" src="js/docs.js"></script>
15
+	<script type="text/javascript" src="js/examples.js"></script>
16
+<script type="text/javascript" id="js">$(document).ready(function() {
17
+	// call the tablesorter plugin, the magic happens in the markup
18
+	$("table").tablesorter();
19
+}); </script>
20
+</head>
21
+<body>
22
+<div id="banner">	
23
+	<h1>table<em>sorter</em></h1>
24
+	<h2>Setting column parser using metadata</h2>
25
+	<h3>Flexible client-side table sorting</h3>
26
+	<a href="index.html">Back to documentation</a>
27
+</div>
28
+<div id="main">
29
+
30
+	Available parsers: numeric, text, digit, currency, ipAddress, url, isoDate, percent, shortDate, usLongDate. 
31
+	<h1>Demo</h1>
32
+	<div id="demo">
33
+	<table cellspacing="1" class="tablesorter">
34
+		<thead>
35
+		<tr>
36
+			<th class="{sorter: 'text'}">First Name</th>
37
+			<th>Last Name</th>
38
+			<th>Age</th>
39
+			<th>Total</th>
40
+			<th class="{sorter: 'percent'}">Discount</th>
41
+			<th>Date</th>
42
+		</tr>
43
+	</thead>
44
+	<tbody>
45
+		<tr>
46
+			<td>Peter</td>
47
+			<td>Parker</td>
48
+			<td>28</td>
49
+			<td>$9.99</td>
50
+			<td>20%</td>
51
+			
52
+			<td>Jul 6, 2006 8:14 AM</td>
53
+		</tr>
54
+		<tr>
55
+			<td>John</td>
56
+			<td>Hood</td>
57
+			<td>33</td>
58
+			<td>$19.99</td>
59
+			<td>25%</td>
60
+			
61
+			<td>Dec 10, 2002 5:14 AM</td>
62
+		</tr>
63
+		<tr>
64
+			<td>Clark</td>
65
+			<td>Kent</td>
66
+			<td>18</td>
67
+			<td>$15.89</td>
68
+			<td>44%</td>
69
+			<td>Jan 12, 2003 11:14 AM</td>
70
+		</tr>
71
+		<tr>
72
+			<td>Bruce</td>
73
+			<td>Almighty</td>
74
+			<td>45</td>
75
+			<td>$153.19</td>
76
+			<td>44%</td>
77
+			
78
+			<td>Jan 18, 2001 9:12 AM</td>
79
+		</tr>
80
+		<tr>
81
+			<td>Bruce</td>
82
+			<td>Evans</td>
83
+			<td>22</td>
84
+			<td>$13.19</td>
85
+			<td>11%</td>
86
+			<td>Jan 18, 2007 9:12 AM</td>
87
+		</tr>
88
+	</tbody>
89
+		</table>
90
+	</div>
91
+	<h1>Javascript</h1>
92
+	<div id="javascript">
93
+		<pre class="javascript"></pre>
94
+	</div>
95
+	<h1>HTML</h1>
96
+	<div id="html">
97
+		<pre class="html"></pre>
98
+	</div>
99
+</div>
100
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
101
+<script type="text/javascript">
102
+_uacct = "UA-2189649-2";
103
+urchinTracker();
104
+</script>
105
+</body>
106
+</html>
107
+

+ 107 - 0
tracim/tracim/public/assets/tablesorter/docs/example-meta-sort-list.html Visa fil

1
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us">
4
+<head>
5
+	<title>jQuery plugin: Tablesorter 2.0 - Setting initial sorting order with metadata</title>
6
+	<link rel="stylesheet" href="css/jq.css" type="text/css" media="print, projection, screen" />
7
+	<link rel="stylesheet" href="../themes/blue/style.css" type="text/css" id="" media="print, projection, screen" />
8
+	<script type="text/javascript" src="../jquery-latest.js"></script>
9
+	
10
+	<script type="text/javascript" src="../jquery.metadata.js"></script>
11
+	<script type="text/javascript" src="../jquery.tablesorter.js"></script>
12
+	<script type="text/javascript" src="../addons/pager/jquery.tablesorter.pager.js"></script>
13
+	<script type="text/javascript" src="js/chili/chili-1.8b.js"></script>
14
+	<script type="text/javascript" src="js/docs.js"></script>
15
+	<script type="text/javascript" src="js/examples.js"></script>
16
+<script type="text/javascript" id="js">$(document).ready(function() {
17
+	// call the tablesorter plugin, the magic happens in the markup
18
+	$("table").tablesorter();
19
+}); </script>
20
+</head>
21
+<body>
22
+<div id="banner">	
23
+	<h1>table<em>sorter</em></h1>
24
+	<h2>Setting initial sorting order with metadata</h2>
25
+	<h3>Flexible client-side table sorting</h3>
26
+	<a href="index.html">Back to documentation</a>
27
+</div>
28
+<div id="main">
29
+	<h1>Demo</h1>
30
+	<div id="demo">
31
+		<!-- sortlist is appended to the table using the class attribute and is picked up by metadata plugin -->
32
+		<table cellspacing="1" class="tablesorter {sortlist: [[0,0],[4,0]]}">
33
+				<thead>
34
+			<tr>
35
+				<th>First Name</th>
36
+				<th>Last Name</th>
37
+				<th>Age</th>
38
+				<th>Total</th>
39
+				<th>Discount</th>
40
+				<th>Date</th>
41
+
42
+			</tr>
43
+		</thead>
44
+	<tbody>
45
+		<tr>
46
+			<td>Peter</td>
47
+			<td>Parker</td>
48
+			<td>28</td>
49
+			<td>$9.99</td>
50
+			<td>20%</td>
51
+			
52
+			<td>Jul 6, 2006 8:14 AM</td>
53
+		</tr>
54
+		<tr>
55
+			<td>John</td>
56
+			<td>Hood</td>
57
+			<td>33</td>
58
+			<td>$19.99</td>
59
+			<td>25%</td>
60
+			
61
+			<td>Dec 10, 2002 5:14 AM</td>
62
+		</tr>
63
+		<tr>
64
+			<td>Clark</td>
65
+			<td>Kent</td>
66
+			<td>18</td>
67
+			<td>$15.89</td>
68
+			<td>44%</td>
69
+			<td>Jan 12, 2003 11:14 AM</td>
70
+		</tr>
71
+		<tr>
72
+			<td>Bruce</td>
73
+			<td>Almighty</td>
74
+			<td>45</td>
75
+			<td>$153.19</td>
76
+			<td>44%</td>
77
+			
78
+			<td>Jan 18, 2001 9:12 AM</td>
79
+		</tr>
80
+		<tr>
81
+			<td>Bruce</td>
82
+			<td>Evans</td>
83
+			<td>22</td>
84
+			<td>$13.19</td>
85
+			<td>11%</td>
86
+			<td>Jan 18, 2007 9:12 AM</td>
87
+		</tr>
88
+	</tbody>
89
+		</table>
90
+	</div>
91
+	<h1>Javascript</h1>
92
+	<div id="javascript">
93
+		<pre class="javascript"></pre>
94
+	</div>
95
+	<h1>HTML</h1>
96
+	<div id="html">
97
+		<pre class="html"></pre>
98
+	</div>
99
+</div>
100
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
101
+<script type="text/javascript">
102
+_uacct = "UA-2189649-2";
103
+urchinTracker();
104
+</script>
105
+</body>
106
+</html>
107
+

+ 116 - 0
tracim/tracim/public/assets/tablesorter/docs/example-option-debug.html Visa fil

1
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us">
4
+<head>
5
+	<title>jQuery plugin: Tablesorter 2.0 - Enabling debug mode</title>
6
+	<link rel="stylesheet" href="css/jq.css" type="text/css" media="print, projection, screen" />
7
+	<link rel="stylesheet" href="../themes/blue/style.css" type="text/css" id="" media="print, projection, screen" />
8
+	<script type="text/javascript" src="../jquery-latest.js"></script>
9
+	
10
+	<script type="text/javascript" src="../jquery.tablesorter.js"></script>
11
+	<script type="text/javascript" src="../addons/pager/jquery.tablesorter.pager.js"></script>
12
+	<script type="text/javascript" src="js/chili/chili-1.8b.js"></script>
13
+	<script type="text/javascript" src="js/docs.js"></script>
14
+	<script type="text/javascript" src="js/examples.js"></script>
15
+<script type="text/javascript" id="js">$(document).ready(function() {
16
+	// call the tablesorter plugin
17
+	$("table").tablesorter({
18
+		// enable debug mode
19
+		debug: true
20
+	});
21
+}); </script>
22
+</head>
23
+<body>
24
+<div id="banner">	
25
+	<h1>table<em>sorter</em></h1>
26
+	<h2>Enabling debug mode</h2>
27
+	<h3>Flexible client-side table sorting</h3>
28
+	<a href="index.html">Back to documentation</a>
29
+</div>
30
+<div id="main">
31
+	
32
+		<p class="tip">
33
+			<em>NOTE!</em> If firebug is installed the debuging information will be displayed in the firebug console.
34
+		</p>
35
+	
36
+	<h1>Demo</h1>
37
+	<div id="demo">
38
+		
39
+		<table cellspacing="1" class="tablesorter">
40
+		<thead>
41
+				<tr>
42
+					<th>First Name</th>
43
+					<th>Last Name</th>
44
+					<th>Age</th>
45
+					<th>Total</th>
46
+					<th>Discount</th>
47
+					<th>Date</th>
48
+	
49
+				</tr>
50
+			</thead>
51
+			<tbody>
52
+				<tr>
53
+					<td>Peter</td>
54
+					<td>Parker</td>
55
+					<td>28</td>
56
+					<td>$9.99</td>
57
+					<td>20%</td>
58
+					
59
+					<td>Jul 6, 2006 8:14 AM</td>
60
+				</tr>
61
+				<tr>
62
+					<td>John</td>
63
+					<td>Hood</td>
64
+					<td>33</td>
65
+					<td>$19.99</td>
66
+					<td>25%</td>
67
+					
68
+					<td>Dec 10, 2002 5:14 AM</td>
69
+				</tr>
70
+				<tr>
71
+					<td>Clark</td>
72
+					<td>Kent</td>
73
+					<td>18</td>
74
+					<td>$15.89</td>
75
+					<td>44%</td>
76
+					<td>Jan 12, 2003 11:14 AM</td>
77
+				</tr>
78
+				<tr>
79
+					<td>Bruce</td>
80
+					<td>Almighty</td>
81
+					<td>45</td>
82
+					<td>$153.19</td>
83
+					<td>44%</td>
84
+					
85
+					<td>Jan 18, 2001 9:12 AM</td>
86
+				</tr>
87
+				<tr>
88
+					<td>Bruce</td>
89
+					<td>Evans</td>
90
+					<td>22</td>
91
+					<td>$13.19</td>
92
+					<td>11%</td>
93
+					<td>Jan 18, 2007 9:12 AM</td>
94
+				</tr>
95
+			</tbody>
96
+		</table>
97
+
98
+	</div>
99
+	
100
+	<h1>Javascript</h1>
101
+	<div id="javascript">
102
+		<pre class="javascript"></pre>
103
+	</div>
104
+	<h1>HTML</h1>
105
+	<div id="html">
106
+		<pre class="html"></pre>
107
+	</div>
108
+</div>
109
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
110
+<script type="text/javascript">
111
+_uacct = "UA-2189649-2";
112
+urchinTracker();
113
+</script>
114
+</body>
115
+</html>
116
+

+ 106 - 0
tracim/tracim/public/assets/tablesorter/docs/example-option-digits.html Visa fil

1
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us">
4
+<head>
5
+	<title>jQuery plugin: Tablesorter 2.0 - Enabling debug mode</title>
6
+	<link rel="stylesheet" href="css/jq.css" type="text/css" media="print, projection, screen" />
7
+	<link rel="stylesheet" href="../themes/blue/style.css" type="text/css" id="" media="print, projection, screen" />
8
+	<script type="text/javascript" src="../jquery-latest.js"></script>
9
+	
10
+	<script type="text/javascript" src="../jquery.tablesorter.js"></script>
11
+	<script type="text/javascript" src="../addons/pager/jquery.tablesorter.pager.js"></script>
12
+	<script type="text/javascript" src="js/chili/chili-1.8b.js"></script>
13
+	<script type="text/javascript" src="js/docs.js"></script>
14
+	<script type="text/javascript" src="js/examples.js"></script>
15
+<script type="text/javascript" id="js">$(document).ready(function() {
16
+	// call the tablesorter plugin
17
+	$("table").tablesorter();
18
+}); </script>
19
+</head>
20
+<body>
21
+<div id="banner">	
22
+	<h1>table<em>sorter</em></h1>
23
+	<h2>Dealing with digits</h2>
24
+	<h3>Flexible client-side table sorting</h3>
25
+	<a href="index.html">Back to documentation</a>
26
+</div>
27
+<div id="main">
28
+	
29
+	<h1>Demo</h1>
30
+	<div id="demo">
31
+		
32
+		<table cellspacing="1" class="tablesorter">
33
+		<thead>
34
+				<tr>
35
+					<th>First Name</th>
36
+					<th>Last Name</th>
37
+					<th>Age</th>
38
+					<th>Total</th>
39
+					<th>Discount</th>
40
+					<th>Diff</th>
41
+	
42
+				</tr>
43
+			</thead>
44
+			<tbody>
45
+				<tr>
46
+					<td>Peter</td>
47
+					<td>Parker</td>
48
+					<td>28</td>
49
+					<td>9.99</td>
50
+					<td>20.3%</td>
51
+					<td>+3.0</td>
52
+				</tr>
53
+				<tr>
54
+					<td>John</td>
55
+					<td>Hood</td>
56
+					<td>33</td>
57
+					<td>19.99</td>
58
+					<td>25.1%</td>
59
+					<td>-7</td>
60
+				</tr>
61
+				<tr>
62
+					<td>Clark</td>
63
+					<td>Kent</td>
64
+					<td>18</td>
65
+					<td>15.89</td>
66
+					<td>44.2%</td>
67
+					<td>-15</td>
68
+				</tr>
69
+				<tr>
70
+					<td>Bruce</td>
71
+					<td>Almighty</td>
72
+					<td>45</td>
73
+					<td>153.19</td>
74
+					<td>44%</td>
75
+					<td>+19</td>
76
+				</tr>
77
+				<tr>
78
+					<td>Bruce</td>
79
+					<td>Evans</td>
80
+					<td>56</td>
81
+					<td>153.19</td>
82
+					<td>23%</td>
83
+					<td>+9</td>
84
+				</tr>
85
+			</tbody>
86
+		</table>
87
+
88
+	</div>
89
+	
90
+	<h1>Javascript</h1>
91
+	<div id="javascript">
92
+		<pre class="javascript"></pre>
93
+	</div>
94
+	<h1>HTML</h1>
95
+	<div id="html">
96
+		<pre class="html"></pre>
97
+	</div>
98
+</div>
99
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
100
+<script type="text/javascript">
101
+_uacct = "UA-2189649-2";
102
+urchinTracker();
103
+</script>
104
+</body>
105
+</html>
106
+

+ 107 - 0
tracim/tracim/public/assets/tablesorter/docs/example-option-sort-force.html Visa fil

1
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us">
4
+<head>
5
+	<title>jQuery plugin: Tablesorter 2.0 - Force a default sorting order</title>
6
+	<link rel="stylesheet" href="css/jq.css" type="text/css" media="print, projection, screen" />
7
+	<link rel="stylesheet" href="../themes/blue/style.css" type="text/css" id="" media="print, projection, screen" />
8
+	<script type="text/javascript" src="../jquery-latest.js"></script>
9
+	
10
+	<script type="text/javascript" src="../jquery.tablesorter.js"></script>
11
+	<script type="text/javascript" src="js/chili/chili-1.8b.js"></script>
12
+	<script type="text/javascript" src="js/docs.js"></script>
13
+	<script type="text/javascript" src="js/examples.js"></script>
14
+<script type="text/javascript" id="js">$(document).ready(function() {
15
+	// call the tablesorter plugin
16
+	$("table").tablesorter({
17
+		// set forced sort on the fourth column and i decending order.
18
+		sortForce: [[0,0]]
19
+	});
20
+}); </script>
21
+</head>
22
+<body>
23
+<div id="banner">	
24
+	<h1>table<em>sorter</em></h1>
25
+	<h2>Force a default sorting order</h2>
26
+	<h3>Flexible client-side table sorting</h3>
27
+	<a href="index.html">Back to documentation</a>
28
+</div>
29
+<div id="main">
30
+	<h1>Demo</h1>
31
+	<div id="demo">
32
+		<table cellspacing="1" class="tablesorter">
33
+		<thead>
34
+				<tr>
35
+					<th>First Name</th>
36
+					<th>Last Name</th>
37
+					<th>Age</th>
38
+					<th>Total</th>
39
+					<th>Discount</th>
40
+					<th>Date</th>
41
+	
42
+				</tr>
43
+			</thead>
44
+			<tbody>
45
+				<tr>
46
+					<td>Peter</td>
47
+					<td>Parker</td>
48
+					<td>28</td>
49
+					<td>$9.99</td>
50
+					<td>20%</td>
51
+					
52
+					<td>Jul 6, 2006 8:14 AM</td>
53
+				</tr>
54
+				<tr>
55
+					<td>John</td>
56
+					<td>Hood</td>
57
+					<td>33</td>
58
+					<td>$19.99</td>
59
+					<td>25%</td>
60
+					
61
+					<td>Dec 10, 2002 5:14 AM</td>
62
+				</tr>
63
+				<tr>
64
+					<td>Clark</td>
65
+					<td>Kent</td>
66
+					<td>18</td>
67
+					<td>$15.89</td>
68
+					<td>44%</td>
69
+					<td>Jan 12, 2003 11:14 AM</td>
70
+				</tr>
71
+				<tr>
72
+					<td>Bruce</td>
73
+					<td>Almighty</td>
74
+					<td>45</td>
75
+					<td>$153.19</td>
76
+					<td>44%</td>
77
+					
78
+					<td>Jan 18, 2001 9:12 AM</td>
79
+				</tr>
80
+				<tr>
81
+					<td>Bruce</td>
82
+					<td>Evans</td>
83
+					<td>22</td>
84
+					<td>$13.19</td>
85
+					<td>11%</td>
86
+					<td>Jan 18, 2007 9:12 AM</td>
87
+				</tr>
88
+			</tbody>
89
+		</table>
90
+	</div>
91
+	<h1>Javascript</h1>
92
+	<div id="javascript">
93
+		<pre class="javascript"></pre>
94
+	</div>
95
+	<h1>HTML</h1>
96
+	<div id="html">
97
+		<pre class="html"></pre>
98
+	</div>
99
+</div>
100
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
101
+<script type="text/javascript">
102
+_uacct = "UA-2189649-2";
103
+urchinTracker();
104
+</script>
105
+</body>
106
+</html>
107
+

+ 108 - 0
tracim/tracim/public/assets/tablesorter/docs/example-option-sort-key.html Visa fil

1
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us">
4
+<head>
5
+	<title>jQuery plugin: Tablesorter 2.0 - Change multi-column sorting key</title>
6
+	<link rel="stylesheet" href="css/jq.css" type="text/css" media="print, projection, screen" />
7
+	<link rel="stylesheet" href="../themes/blue/style.css" type="text/css" id="" media="print, projection, screen" />
8
+	<script type="text/javascript" src="../jquery-latest.js"></script>
9
+	
10
+	<script type="text/javascript" src="../jquery.tablesorter.js"></script>
11
+	<script type="text/javascript" src="../addons/pager/jquery.tablesorter.pager.js"></script>
12
+	<script type="text/javascript" src="js/chili/chili-1.8b.js"></script>
13
+	<script type="text/javascript" src="js/docs.js"></script>
14
+	<script type="text/javascript" src="js/examples.js"></script>
15
+<script type="text/javascript" id="js">$(document).ready(function() {
16
+	// call the tablesorter plugin
17
+	$("table").tablesorter({
18
+		// change the multi sort key from the default shift to alt button
19
+		sortMultiSortKey: 'altKey'
20
+	});
21
+}); </script>
22
+</head>
23
+<body>
24
+<div id="banner">	
25
+	<h1>table<em>sorter</em></h1>
26
+	<h2>Change multi-column sorting key</h2>
27
+	<h3>Flexible client-side table sorting</h3>
28
+	<a href="index.html">Back to documentation</a>
29
+</div>
30
+<div id="main">
31
+	<h1>Demo</h1>
32
+	<div id="demo">
33
+		<table cellspacing="1" class="tablesorter">
34
+		<thead>
35
+				<tr>
36
+					<th>First Name</th>
37
+					<th>Last Name</th>
38
+					<th>Age</th>
39
+					<th>Total</th>
40
+					<th>Discount</th>
41
+					<th>Date</th>
42
+	
43
+				</tr>
44
+			</thead>
45
+			<tbody>
46
+				<tr>
47
+					<td>Peter</td>
48
+					<td>Parker</td>
49
+					<td>28</td>
50
+					<td>$9.99</td>
51
+					<td>20%</td>
52
+					
53
+					<td>Jul 6, 2006 8:14 AM</td>
54
+				</tr>
55
+				<tr>
56
+					<td>John</td>
57
+					<td>Hood</td>
58
+					<td>33</td>
59
+					<td>$19.99</td>
60
+					<td>25%</td>
61
+					
62
+					<td>Dec 10, 2002 5:14 AM</td>
63
+				</tr>
64
+				<tr>
65
+					<td>Clark</td>
66
+					<td>Kent</td>
67
+					<td>18</td>
68
+					<td>$15.89</td>
69
+					<td>44%</td>
70
+					<td>Jan 12, 2003 11:14 AM</td>
71
+				</tr>
72
+				<tr>
73
+					<td>Bruce</td>
74
+					<td>Almighty</td>
75
+					<td>45</td>
76
+					<td>$153.19</td>
77
+					<td>44%</td>
78
+					
79
+					<td>Jan 18, 2001 9:12 AM</td>
80
+				</tr>
81
+				<tr>
82
+					<td>Bruce</td>
83
+					<td>Evans</td>
84
+					<td>22</td>
85
+					<td>$13.19</td>
86
+					<td>11%</td>
87
+					<td>Jan 18, 2007 9:12 AM</td>
88
+				</tr>
89
+			</tbody>
90
+		</table>
91
+	</div>
92
+	<h1>Javascript</h1>
93
+	<div id="javascript">
94
+		<pre class="javascript"></pre>
95
+	</div>
96
+	<h1>HTML</h1>
97
+	<div id="html">
98
+		<pre class="html"></pre>
99
+	</div>
100
+</div>
101
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
102
+<script type="text/javascript">
103
+_uacct = "UA-2189649-2";
104
+urchinTracker();
105
+</script>
106
+</body>
107
+</html>
108
+

+ 108 - 0
tracim/tracim/public/assets/tablesorter/docs/example-option-sort-list.html Visa fil

1
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us">
4
+<head>
5
+	<title>jQuery plugin: Tablesorter 2.0 - Set a initial sorting order</title>
6
+	<link rel="stylesheet" href="css/jq.css" type="text/css" media="print, projection, screen" />
7
+	<link rel="stylesheet" href="../themes/blue/style.css" type="text/css" id="" media="print, projection, screen" />
8
+	<script type="text/javascript" src="../jquery-latest.js"></script>
9
+	
10
+	<script type="text/javascript" src="../jquery.tablesorter.js"></script>
11
+	<script type="text/javascript" src="../addons/pager/jquery.tablesorter.pager.js"></script>
12
+	<script type="text/javascript" src="js/chili/chili-1.8b.js"></script>
13
+	<script type="text/javascript" src="js/docs.js"></script>
14
+	<script type="text/javascript" src="js/examples.js"></script>
15
+<script type="text/javascript" id="js">$(document).ready(function() {
16
+	// call the tablesorter plugin
17
+	$("table").tablesorter({
18
+		// sort on the first column and third column, order asc
19
+		sortList: [[0,0],[2,0]]
20
+	});
21
+}); </script>
22
+</head>
23
+<body>
24
+<div id="banner">	
25
+	<h1>table<em>sorter</em></h1>
26
+	<h2>Set a initial sorting order</h2>
27
+	<h3>Flexible client-side table sorting</h3>
28
+	<a href="index.html">Back to documentation</a>
29
+</div>
30
+<div id="main">
31
+	<h1>Demo</h1>
32
+	<div id="demo">
33
+		<table cellspacing="1" class="tablesorter">
34
+		<thead>
35
+				<tr>
36
+					<th>First Name</th>
37
+					<th>Last Name</th>
38
+					<th>Age</th>
39
+					<th>Total</th>
40
+					<th>Discount</th>
41
+					<th>Date</th>
42
+	
43
+				</tr>
44
+			</thead>
45
+			<tbody>
46
+				<tr>
47
+					<td>Peter</td>
48
+					<td>Parker</td>
49
+					<td>28</td>
50
+					<td>$9.99</td>
51
+					<td>20%</td>
52
+					
53
+					<td>Jul 6, 2006 8:14 AM</td>
54
+				</tr>
55
+				<tr>
56
+					<td>John</td>
57
+					<td>Hood</td>
58
+					<td>33</td>
59
+					<td>$19.99</td>
60
+					<td>25%</td>
61
+					
62
+					<td>Dec 10, 2002 5:14 AM</td>
63
+				</tr>
64
+				<tr>
65
+					<td>Clark</td>
66
+					<td>Kent</td>
67
+					<td>18</td>
68
+					<td>$15.89</td>
69
+					<td>44%</td>
70
+					<td>Jan 12, 2003 11:14 AM</td>
71
+				</tr>
72
+				<tr>
73
+					<td>Bruce</td>
74
+					<td>Almighty</td>
75
+					<td>45</td>
76
+					<td>$153.19</td>
77
+					<td>44%</td>
78
+					
79
+					<td>Jan 18, 2001 9:12 AM</td>
80
+				</tr>
81
+				<tr>
82
+					<td>Bruce</td>
83
+					<td>Evans</td>
84
+					<td>22</td>
85
+					<td>$13.19</td>
86
+					<td>11%</td>
87
+					<td>Jan 18, 2007 9:12 AM</td>
88
+				</tr>
89
+			</tbody>
90
+		</table>
91
+	</div>
92
+	<h1>Javascript</h1>
93
+	<div id="javascript">
94
+		<pre class="javascript"></pre>
95
+	</div>
96
+	<h1>HTML</h1>
97
+	<div id="html">
98
+		<pre class="html"></pre>
99
+	</div>
100
+</div>
101
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
102
+<script type="text/javascript">
103
+_uacct = "UA-2189649-2";
104
+urchinTracker();
105
+</script>
106
+</body>
107
+</html>
108
+

+ 108 - 0
tracim/tracim/public/assets/tablesorter/docs/example-option-sort-order.html Visa fil

1
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us">
4
+<head>
5
+	<title>jQuery plugin: Tablesorter 2.0 - Set a initi
6
+	<link rel="stylesheet" href="css/jq.css" type="text/css" media="print, projection, screen" />
7
+	<link rel="stylesheet" href="../themes/blue/style.css" type="text/css" id="" media="print, projection, screen" />
8
+	<script type="text/javascript" src="../jquery-latest.js"></script>
9
+	
10
+	<script type="text/javascript" src="../jquery.tablesorter.js"></script>
11
+	<script type="text/javascript" src="../addons/pager/jquery.tablesorter.pager.js"></script>
12
+	<script type="text/javascript" src="js/chili/chili-1.8b.js"></script>
13
+	<script type="text/javascript" src="js/docs.js"></script>
14
+	<script type="text/javascript" src="js/examples.js"></script>
15
+<script type="text/javascript" id="js">$(document).ready(function() {
16
+	// call the tablesorter plugin
17
+	$("table").tablesorter({
18
+		// change the default sorting order from 'asc' to 'desc'
19
+		sortInitialOrder: 'desc'
20
+	});
21
+}); </script>
22
+</head>
23
+<body>
24
+<div id="banner">	
25
+	<h1>table<em>sorter</em></h1>
26
+	<h2>Set a initial sorting order</h2>
27
+	<h3>Flexible client-side table sorting</h3>
28
+	<a href="index.html">Back to documentation</a>
29
+</div>
30
+<div id="main">
31
+	<h1>Demo</h1>
32
+	<div id="demo">
33
+		<table cellspacing="1" class="tablesorter">
34
+		<thead>
35
+				<tr>
36
+					<th>First Name</th>
37
+					<th>Last Name</th>
38
+					<th>Age</th>
39
+					<th>Total</th>
40
+					<th>Discount</th>
41
+					<th>Date</th>
42
+	
43
+				</tr>
44
+			</thead>
45
+			<tbody>
46
+				<tr>
47
+					<td>Peter</td>
48
+					<td>Parker</td>
49
+					<td>28</td>
50
+					<td>$9.99</td>
51
+					<td>20%</td>
52
+					
53
+					<td>Jul 6, 2006 8:14 AM</td>
54
+				</tr>
55
+				<tr>
56
+					<td>John</td>
57
+					<td>Hood</td>
58
+					<td>33</td>
59
+					<td>$19.99</td>
60
+					<td>25%</td>
61
+					
62
+					<td>Dec 10, 2002 5:14 AM</td>
63
+				</tr>
64
+				<tr>
65
+					<td>Clark</td>
66
+					<td>Kent</td>
67
+					<td>18</td>
68
+					<td>$15.89</td>
69
+					<td>44%</td>
70
+					<td>Jan 12, 2003 11:14 AM</td>
71
+				</tr>
72
+				<tr>
73
+					<td>Bruce</td>
74
+					<td>Almighty</td>
75
+					<td>45</td>
76
+					<td>$153.19</td>
77
+					<td>44%</td>
78
+					
79
+					<td>Jan 18, 2001 9:12 AM</td>
80
+				</tr>
81
+				<tr>
82
+					<td>Bruce</td>
83
+					<td>Evans</td>
84
+					<td>22</td>
85
+					<td>$13.19</td>
86
+					<td>11%</td>
87
+					<td>Jan 18, 2007 9:12 AM</td>
88
+				</tr>
89
+			</tbody>
90
+		</table>
91
+	</div>
92
+	<h1>Javascript</h1>
93
+	<div id="javascript">
94
+		<pre class="javascript"></pre>
95
+	</div>
96
+	<h1>HTML</h1>
97
+	<div id="html">
98
+		<pre class="html"></pre>
99
+	</div>
100
+</div>
101
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
102
+<script type="text/javascript">
103
+_uacct = "UA-2189649-2";
104
+urchinTracker();
105
+</script>
106
+</body>
107
+</html>
108
+

+ 85 - 0
tracim/tracim/public/assets/tablesorter/docs/example-option-text-extraction.html Visa fil

1
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us">
4
+<head>
5
+	<title>jQuery plugin: Tablesorter 2.0 - Dealing with markup inside cells</title>
6
+	<link rel="stylesheet" href="css/jq.css" type="text/css" media="print, projection, screen" />
7
+	<link rel="stylesheet" href="../themes/blue/style.css" type="text/css" id="" media="print, projection, screen" />
8
+	<script type="text/javascript" src="../jquery-latest.js"></script>
9
+	
10
+	<script type="text/javascript" src="../jquery.tablesorter.js"></script>
11
+	<script type="text/javascript" src="../addons/pager/jquery.tablesorter.pager.js"></script>
12
+	<script type="text/javascript" src="js/chili/chili-1.8b.js"></script>
13
+	<script type="text/javascript" src="js/docs.js"></script>
14
+	<script type="text/javascript" src="js/examples.js"></script>
15
+<script type="text/javascript" id="js">$(document).ready(function() {
16
+	
17
+	// call the tablesorter plugin
18
+	$("table").tablesorter({
19
+		// define a custom text extraction function
20
+		textExtraction: function(node) {
21
+			// extract data from markup and return it 
22
+			return node.childNodes[0].childNodes[0].innerHTML;
23
+		}
24
+	});
25
+}); </script>
26
+</head>
27
+<body>
28
+<div id="banner">	
29
+	<h1>table<em>sorter</em></h1>
30
+	<h2>Dealing with markup inside cells</h2>
31
+	<h3>Flexible client-side table sorting</h3>
32
+	<a href="index.html">Back to documentation</a>
33
+</div>
34
+<div id="main">
35
+	<h1>Demo</h1>
36
+	<div id="demo">
37
+		<table cellspacing="1" class="tablesorter">
38
+				<thead>
39
+			<tr>
40
+				<th>First Name</th>
41
+				<th>Last Name</th>
42
+				<th>Age</th>
43
+				<th>Total</th>
44
+				<th>Discount</th>
45
+				<th>Date</th>
46
+
47
+			</tr>
48
+		</thead>
49
+		<tbody>
50
+			<tr>
51
+				<td><strong><em>Peter</em></strong></td>
52
+				<td><strong><em>Parker</em></strong></td>
53
+				<td><strong><em>28</em></strong></td>
54
+				<td><strong><em>$9.99</em></strong></td>
55
+				<td><strong><em>20%</em></strong></td>	
56
+				<td><strong><em>Jul 6, 2006 8:14 AM</em></strong></td>
57
+			</tr>
58
+			<tr>
59
+				<td><strong><em>John</em></strong></td>
60
+				<td><strong><em>Hood</em></strong></td>
61
+				<td><strong><em>33</em></strong></td>
62
+				<td><strong><em>$19.99</em></strong></td>
63
+				<td><strong><em>25%</em></strong></td>
64
+				<td><strong><em>Dec 10, 2002 5:14 AM</em></strong></td>
65
+			</tr>
66
+		</tbody>
67
+		</table>
68
+	</div>
69
+	<h1>Javascript</h1>
70
+	<div id="javascript">
71
+		<pre class="javascript"></pre>
72
+	</div>
73
+	<h1>HTML</h1>
74
+	<div id="html">
75
+		<pre class="html"></pre>
76
+	</div>
77
+</div>
78
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
79
+<script type="text/javascript">
80
+_uacct = "UA-2189649-2";
81
+urchinTracker();
82
+</script>
83
+</body>
84
+</html>
85
+

+ 118 - 0
tracim/tracim/public/assets/tablesorter/docs/example-options-headers.html Visa fil

1
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us">
4
+<head>
5
+	<title>jQuery plugin: Tablesorter 2.0 - Disable headers using options</title>
6
+	<link rel="stylesheet" href="css/jq.css" type="text/css" media="print, projection, screen" />
7
+	<link rel="stylesheet" href="../themes/blue/style.css" type="text/css" id="" media="print, projection, screen" />
8
+	<script type="text/javascript" src="../jquery-latest.js"></script>
9
+	
10
+	<script type="text/javascript" src="../jquery.tablesorter.js"></script>
11
+	<script type="text/javascript" src="../addons/pager/jquery.tablesorter.pager.js"></script>
12
+	<script type="text/javascript" src="js/chili/chili-1.8b.js"></script>
13
+	<script type="text/javascript" src="js/docs.js"></script>
14
+	<script type="text/javascript" src="js/examples.js"></script>
15
+<script type="text/javascript" id="js">$(document).ready(function() {
16
+	$("table").tablesorter({
17
+		// pass the headers argument and assing a object
18
+		headers: {
19
+			// assign the secound column (we start counting zero)
20
+			1: {
21
+				// disable it by setting the property sorter to false
22
+				sorter: false
23
+			},
24
+			// assign the third column (we start counting zero)
25
+			2: {
26
+				// disable it by setting the property sorter to false
27
+				sorter: false
28
+			}
29
+		}
30
+	});
31
+});</script>
32
+</head>
33
+<body>
34
+<div id="banner">	
35
+	<h1>table<em>sorter</em></h1>
36
+	<h2>Disable headers using options</h2>
37
+	<h3>Flexible client-side table sorting</h3>
38
+	<a href="index.html">Back to documentation</a>
39
+</div>
40
+<div id="main">
41
+	<h1>Demo</h1>
42
+	<div id="demo">
43
+		<table cellspacing="1" class="tablesorter">
44
+			<thead>
45
+				<tr>
46
+					<th>First Name</th>
47
+					<th>Last Name</th>
48
+					<th>Age</th>
49
+					<th>Total</th>
50
+					<th>Discount</th>
51
+					<th>Date</th>
52
+	
53
+				</tr>
54
+			</thead>
55
+			<tbody>
56
+				<tr>
57
+					<td>Peter</td>
58
+					<td>Parker</td>
59
+					<td>28</td>
60
+					<td>$9.99</td>
61
+					<td>20%</td>
62
+					
63
+					<td>Jul 6, 2006 8:14 AM</td>
64
+				</tr>
65
+				<tr>
66
+					<td>John</td>
67
+					<td>Hood</td>
68
+					<td>33</td>
69
+					<td>$19.99</td>
70
+					<td>25%</td>
71
+					
72
+					<td>Dec 10, 2002 5:14 AM</td>
73
+				</tr>
74
+				<tr>
75
+					<td>Clark</td>
76
+					<td>Kent</td>
77
+					<td>18</td>
78
+					<td>$15.89</td>
79
+					<td>44%</td>
80
+					<td>Jan 12, 2003 11:14 AM</td>
81
+				</tr>
82
+				<tr>
83
+					<td>Bruce</td>
84
+					<td>Almighty</td>
85
+					<td>45</td>
86
+					<td>$153.19</td>
87
+					<td>44%</td>
88
+					
89
+					<td>Jan 18, 2001 9:12 AM</td>
90
+				</tr>
91
+				<tr>
92
+					<td>Bruce</td>
93
+					<td>Evans</td>
94
+					<td>22</td>
95
+					<td>$13.19</td>
96
+					<td>11%</td>
97
+					<td>Jan 18, 2007 9:12 AM</td>
98
+				</tr>
99
+			</tbody>
100
+		</table>
101
+	</div>
102
+	<h1>Javascript</h1>
103
+	<div id="javascript">
104
+		<pre class="javascript"></pre>
105
+	</div>
106
+	<h1>HTML</h1>
107
+	<div id="html">
108
+		<pre class="html"></pre>
109
+	</div>
110
+</div>
111
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
112
+<script type="text/javascript">
113
+_uacct = "UA-2189649-2";
114
+urchinTracker();
115
+</script>
116
+</body>
117
+</html>
118
+

Filskillnaden har hållits tillbaka eftersom den är för stor
+ 329 - 0
tracim/tracim/public/assets/tablesorter/docs/example-pager.html


+ 112 - 0
tracim/tracim/public/assets/tablesorter/docs/example-parsers.html Visa fil

1
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us">
4
+<head>
5
+	<title>jQuery plugin: Tablesorter 2.0 - Writing custom parsers</title>
6
+	<link rel="stylesheet" href="css/jq.css" type="text/css" media="print, projection, screen" />
7
+	<link rel="stylesheet" href="../themes/blue/style.css" type="text/css" media="print, projection, screen" />
8
+	<script type="text/javascript" src="../jquery-latest.js"></script>
9
+	
10
+	<script type="text/javascript" src="../jquery.tablesorter.js"></script>
11
+	<script type="text/javascript" src="../addons/pager/jquery.tablesorter.pager.js"></script>
12
+	<script type="text/javascript" src="js/chili/chili-1.8b.js"></script>
13
+	<script type="text/javascript" src="js/docs.js"></script>
14
+	<script type="text/javascript" src="js/examples.js"></script>
15
+	<script type="text/javascript" id="js">
16
+	// add parser through the tablesorter addParser method
17
+	$.tablesorter.addParser({
18
+		// set a unique id
19
+		id: 'grades',
20
+		is: function(s) {
21
+			// return false so this parser is not auto detected
22
+			return false;
23
+		},
24
+		format: function(s) {
25
+			// format your data for normalization
26
+			return s.toLowerCase().replace(/good/,2).replace(/medium/,1).replace(/bad/,0);
27
+		},
28
+		// set type, either numeric or text
29
+		type: 'numeric'
30
+	});
31
+	
32
+	$(function() {
33
+		$("table").tablesorter({
34
+			headers: {
35
+				6: {
36
+					sorter:'grades'
37
+				}
38
+			}
39
+		});
40
+	}); 				
41
+	</script>
42
+</head>
43
+<body>
44
+<div id="banner">	
45
+	<h1>table<em>sorter</em></h1>
46
+	<h2>Writing custom parsers</h2>
47
+	<h3>Flexible client-side table sorting</h3>
48
+	<a href="index.html">Back to documentation</a>
49
+</div>
50
+<div id="main">
51
+	<h1>Demo</h1>
52
+	<div id="demo">
53
+	<table cellspacing="1" class="tablesorter">
54
+		<thead>
55
+			<tr>
56
+				<th>Name</th>
57
+				<th>Major</th>
58
+				<th>Gender</th>
59
+				<th>English</th>
60
+				<th>Japanese</th>
61
+				<th>Calculus</th>
62
+				<th>Overall grades</th>
63
+			</tr>
64
+		</thead>
65
+		<tbody>
66
+			<tr>
67
+				<td>Student01</td>
68
+				<td>Languages</td>
69
+				<td>male</td>
70
+				<td>80</td>
71
+				<td>70</td>
72
+				<td>75</td>
73
+				<td>bad</td>
74
+			</tr>
75
+			<tr>
76
+				<td>Student02</td>
77
+				<td>Mathematics</td>
78
+				<td>male</td>
79
+				<td>90</td>
80
+				<td>88</td>
81
+				<td>100</td>
82
+				<td>good</td>
83
+			</tr>
84
+			<tr>
85
+				<td>Student03</td>
86
+				<td>Languages</td>
87
+				<td>female</td>
88
+				<td>85</td>
89
+				<td>95</td>
90
+				<td>80</td>
91
+				<td>medium</td>
92
+			</tr>
93
+		</tbody>
94
+	</table>
95
+	</div>
96
+	<h1>Javascript</h1>
97
+	<div id="javascript">
98
+		<pre class="javascript"></pre>
99
+	</div>
100
+	<h1>HTML</h1>
101
+	<div id="html">
102
+		<pre class="html"></pre>
103
+	</div>
104
+</div>
105
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
106
+<script type="text/javascript">
107
+_uacct = "UA-2189649-2";
108
+urchinTracker();
109
+</script>
110
+</body>
111
+</html>
112
+

+ 113 - 0
tracim/tracim/public/assets/tablesorter/docs/example-trigger-sort.html Visa fil

1
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us">
4
+<head>
5
+	<title>jQuery plugin: Tablesorter 2.0 - Sort table using a link outside the table</title>
6
+	<link rel="stylesheet" href="css/jq.css" type="text/css" media="print, projection, screen" />
7
+	<link rel="stylesheet" href="../themes/blue/style.css" type="text/css" id="" media="print, projection, screen" />
8
+	<script type="text/javascript" src="../jquery-latest.js"></script>
9
+	
10
+	<script type="text/javascript" src="../jquery.tablesorter.js"></script>
11
+	<script type="text/javascript" src="../addons/pager/jquery.tablesorter.pager.js"></script>
12
+	<script type="text/javascript" src="js/chili/chili-1.8b.js"></script>
13
+	<script type="text/javascript" src="js/docs.js"></script>
14
+	<script type="text/javascript" src="js/examples.js"></script>
15
+	<script type="text/javascript" id="js">$(document).ready(function() {
16
+	$("table").tablesorter();
17
+	$("#trigger-link").click(function() {
18
+		// set sorting column and direction, this will sort on the first and third column the column index starts at zero
19
+		var sorting = [[0,0],[2,0]];
20
+		// sort on the first column
21
+		$("table").trigger("sorton",[sorting]);
22
+		// return false to stop default link action
23
+		return false;
24
+	});
25
+});</script>
26
+</head>
27
+<body>
28
+<div id="banner">	
29
+	<h1>table<em>sorter</em></h1>
30
+	<h2>Sort table using a link outside the table</h2>
31
+	<h3>Flexible client-side table sorting</h3>
32
+	<a href="index.html">Back to documentation</a>
33
+</div>
34
+<div id="main">
35
+	<h1>Demo</h1>
36
+	<div id="demo">
37
+		<table cellspacing="1" class="tablesorter">
38
+			<thead>
39
+				<tr>
40
+					<th>First Name</th>
41
+					<th>Last Name</th>
42
+					<th>Age</th>
43
+					<th>Total</th>
44
+					<th>Discount</th>
45
+					<th>Date</th>
46
+	
47
+				</tr>
48
+			</thead>
49
+			<tbody>
50
+				<tr>
51
+					<td>Peter</td>
52
+					<td>Parker</td>
53
+					<td>28</td>
54
+					<td>$9.99</td>
55
+					<td>20%</td>
56
+					
57
+					<td>Jul 6, 2006 8:14 AM</td>
58
+				</tr>
59
+				<tr>
60
+					<td>John</td>
61
+					<td>Hood</td>
62
+					<td>33</td>
63
+					<td>$19.99</td>
64
+					<td>25%</td>
65
+					
66
+					<td>Dec 10, 2002 5:14 AM</td>
67
+				</tr>
68
+				<tr>
69
+					<td>Clark</td>
70
+					<td>Kent</td>
71
+					<td>18</td>
72
+					<td>$15.89</td>
73
+					<td>44%</td>
74
+					<td>Jan 12, 2003 11:14 AM</td>
75
+				</tr>
76
+				<tr>
77
+					<td>Bruce</td>
78
+					<td>Almighty</td>
79
+					<td>45</td>
80
+					<td>$153.19</td>
81
+					<td>44%</td>
82
+					
83
+					<td>Jan 18, 2001 9:12 AM</td>
84
+				</tr>
85
+				<tr>
86
+					<td>Bruce</td>
87
+					<td>Evans</td>
88
+					<td>22</td>
89
+					<td>$13.19</td>
90
+					<td>11%</td>
91
+					<td>Jan 18, 2007 9:12 AM</td>
92
+				</tr>
93
+			</tbody></table>
94
+		<a href="#" id="trigger-link">Sort first and third columns</a>
95
+		<br/>
96
+		<br/>
97
+	</div>
98
+	<h1>Javascript</h1>
99
+	<div id="javascript">
100
+		<pre class="javascript"></pre>
101
+	</div>
102
+	<h1>HTML</h1>
103
+	<div id="html">
104
+		<pre class="html"></pre>
105
+	</div>
106
+</div>
107
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
108
+<script type="text/javascript">
109
+_uacct = "UA-2189649-2";
110
+urchinTracker();
111
+</script>
112
+</body>
113
+</html>

Filskillnaden har hållits tillbaka eftersom den är för stor
+ 336 - 0
tracim/tracim/public/assets/tablesorter/docs/example-triggers.html


+ 118 - 0
tracim/tracim/public/assets/tablesorter/docs/example-update-cell.html Visa fil

1
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us">
4
+<head>
5
+	<title>jQuery plugin: Tablesorter 2.0 - Appending table data with ajax</title>
6
+	<link rel="stylesheet" href="css/jq.css" type="text/css" media="print, projection, screen" />
7
+	<link rel="stylesheet" href="../themes/blue/style.css" type="text/css" id="" media="print, projection, screen" />
8
+	<script type="text/javascript" src="../jquery-latest.js"></script>
9
+	<script type="text/javascript" src="../jquery.tablesorter.js"></script>
10
+	<script type="text/javascript" src="js/chili/chili-1.8b.js"></script>
11
+	<script type="text/javascript" src="js/docs.js"></script>
12
+	<script type="text/javascript" src="js/examples.js"></script>
13
+	<script type="text/javascript" id="js">
14
+	$(document).ready(function() {
15
+	$("table").tablesorter();
16
+	$("table tbody td.discount").click(function() {
17
+		 	// randomize a number
18
+		 	var discount = '$' + Math.round(Math.random() * Math.random() * 100) + '.' + Math.round(Math.random() * Math.random() * 100);
19
+		 	$(this).text(discount);
20
+			$("table").trigger("updateCell",[this]);
21
+			// set sorting column and direction, this will sort on the first and third column
22
+			var sorting = [[3,1]];
23
+			// sort on the first column
24
+			$("table").trigger("sorton",[sorting]);
25
+			return false;
26
+		
27
+		
28
+	});
29
+}); 		
30
+	</script>
31
+</head>
32
+<body>
33
+<div id="banner">	
34
+	<h1>table<em>sorter</em></h1>
35
+	<h2>Updateing the table cache</h2>
36
+	<h3>Flexible client-side table sorting</h3>
37
+	<a href="index.html">Back to documentation</a>
38
+</div>
39
+<div id="main">
40
+	<h1>Demo</h1>
41
+	<div id="demo">
42
+		<table cellspacing="1" class="tablesorter">
43
+			<thead>
44
+				<tr>
45
+					<th>First Name</th>
46
+					<th>Last Name</th>
47
+					<th>Age</th>
48
+					<th>Total</th>
49
+					<th>Discount</th>
50
+					<th>Date</th>
51
+	
52
+				</tr>
53
+			</thead>
54
+			<tbody>
55
+				<tr>
56
+					<td>Peter</td>
57
+					<td>Parker</td>
58
+					<td>28</td>
59
+					<td class="discount">$9.99</td>
60
+					<td>20%</td>
61
+					
62
+					<td>Jul 6, 2006 8:14 AM</td>
63
+				</tr>
64
+				<tr>
65
+					<td>John</td>
66
+					<td>Hood</td>
67
+					<td>33</td>
68
+					<td class="discount">$19.99</td>
69
+					<td>25%</td>
70
+					
71
+					<td>Dec 10, 2002 5:14 AM</td>
72
+				</tr>
73
+				<tr>
74
+					<td>Clark</td>
75
+					<td>Kent</td>
76
+					<td>18</td>
77
+					<td class="discount">$15.89</td>
78
+					<td>44%</td>
79
+					<td>Jan 12, 2003 11:14 AM</td>
80
+				</tr>
81
+				<tr>
82
+					<td>Bruce</td>
83
+					<td>Almighty</td>
84
+					<td>45</td>
85
+					<td class="discount">$153.19</td>
86
+					<td>44%</td>
87
+					
88
+					<td>Jan 18, 2001 9:12 AM</td>
89
+				</tr>
90
+				<tr>
91
+					<td>Bruce</td>
92
+					<td>Evans</td>
93
+					<td>22</td>
94
+					<td class="discount">$13.19</td>
95
+					<td>11%</td>
96
+					<td>Jan 18, 2007 9:12 AM</td>
97
+				</tr>
98
+			</tbody>
99
+		</table>
100
+		<br/>
101
+		<br/>
102
+	</div>
103
+	<h1>Javascript</h1>
104
+	<div id="javascript">
105
+		<pre class="javascript"></pre>
106
+	</div>
107
+	<h1>HTML</h1>
108
+	<div id="html">
109
+		<pre class="html"></pre>
110
+	</div>
111
+</div>
112
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
113
+<script type="text/javascript">
114
+_uacct = "UA-2189649-2";
115
+urchinTracker();
116
+</script>
117
+</body>
118
+</html>

+ 383 - 0
tracim/tracim/public/assets/tablesorter/docs/example-widgets.html Visa fil

1
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us">
4
+<head>
5
+	<title>jQuery plugin: Tablesorter 2.0 - Writing custom widgets</title>
6
+	<link rel="stylesheet" href="css/jq.css" type="text/css" media="print, projection, screen" />
7
+	<link rel="stylesheet" href="../themes/blue/style.css" type="text/css" media="print, projection, screen" />
8
+	<script type="text/javascript" src="../jquery-latest.js"></script>
9
+	
10
+	<script type="text/javascript" src="../jquery.tablesorter.js"></script>
11
+	<script type="text/javascript" src="../addons/pager/jquery.tablesorter.pager.js"></script>
12
+	<script type="text/javascript" src="js/chili/chili-1.8b.js"></script>
13
+	<script type="text/javascript" src="js/docs.js"></script>
14
+	<script type="text/javascript">
15
+	$(function() {
16
+		// add new widget called repeatHeaders
17
+		$.tablesorter.addWidget({
18
+			// give the widget a id
19
+			id: "repeatHeaders",
20
+			// format is called when the on init and when a sorting has finished
21
+			format: function(table) {
22
+				// cache and collect all TH headers
23
+				if(!this.headers) {
24
+					var h = this.headers = []; 
25
+					$("thead th",table).each(function() {
26
+						h.push(
27
+							"<th>" + $(this).text() + "</th>"
28
+						);
29
+						
30
+					});
31
+				}
32
+				
33
+				// remove appended headers by classname.
34
+				$("tr.repated-header",table).remove();
35
+				
36
+				// loop all tr elements and insert a copy of the "headers"	
37
+				for(var i=0; i < table.tBodies[0].rows.length; i++) {
38
+					// insert a copy of the table head every 10th row
39
+					if((i%5) == 4) {
40
+						$("tbody tr:eq(" + i + ")",table).before(
41
+							$("<tr></tr>").addClass("repated-header").html(this.headers.join(""))
42
+						
43
+						);	
44
+					}
45
+				}
46
+				
47
+			}
48
+		});
49
+		
50
+		// call the tablesorter plugin and assign widgets with id "zebra" (Default widget in the core) and the newly created "repeatHeaders"
51
+		$("table").tablesorter({
52
+			widgets: ['zebra','repeatHeaders']
53
+		});
54
+
55
+	}); 		
56
+	</script>
57
+</head>
58
+<body>
59
+<div id="banner">	
60
+	<h1>table<em>sorter</em></h1>
61
+	<h2>Writing custom widgets</h2>
62
+	<h3>Flexible client-side table sorting</h3>
63
+	<a href="index.html">Back to documentation</a>
64
+</div>
65
+<div id="main">
66
+
67
+<h1>Javascript</h1>
68
+<pre class="javascript">
69
+// add new widget called repeatHeaders
70
+$.tablesorter.addWidget({
71
+	// give the widget a id
72
+	id: "repeatHeaders",
73
+	// format is called when the on init and when a sorting has finished
74
+	format: function(table) {
75
+		// cache and collect all TH headers
76
+		if(!this.headers) {
77
+			var h = this.headers = []; 
78
+			$("thead th",table).each(function() {
79
+				h.push(
80
+					"<th>" + $(this).text() + "</th>"
81
+				);
82
+				
83
+			});
84
+		}
85
+		
86
+		// remove appended headers by classname.
87
+		$("tr.repated-header",table).remove();
88
+		
89
+		// loop all tr elements and insert a copy of the "headers"	
90
+		for(var i=0; i < table.tBodies[0].rows.length; i++) {
91
+			// insert a copy of the table head every 10th row
92
+			if((i%5) == 4) {
93
+				$("tbody tr:eq(" + i + ")",table).before(
94
+					$("<tr></tr>").html(this.headers.join(""))
95
+				
96
+				);	
97
+			}
98
+		}
99
+	}
100
+});
101
+
102
+// call the tablesorter plugin and assign widgets with id "zebra" (Default widget in the core) and the newly created "repeatHeaders"
103
+$("table").tablesorter({
104
+	widgets: ['zebra','repeatHeaders']
105
+});
106
+</pre>
107
+
108
+<h1>Demo</h1>
109
+<table cellspacing="1" class="tablesorter">
110
+	<thead>
111
+		<tr>
112
+			<th>Name</th>
113
+			<th>Major</th>
114
+			<th>Sex</th>
115
+			<th>English</th>
116
+			<th>Japanese</th>
117
+			<th>Calculus</th>
118
+			<th>Geometry</th>
119
+
120
+		</tr>
121
+	</thead>
122
+	<tfoot>
123
+		<tr>
124
+			<th>Name</th>
125
+			<th>Major</th>
126
+			<th>Sex</th>
127
+			<th>English</th>
128
+			<th>Japanese</th>
129
+			<th>Calculus</th>
130
+			<th>Geometry</th>
131
+
132
+		</tr>
133
+	</tfoot>
134
+	<tbody>
135
+		<tr>
136
+			<td>Student01</td>
137
+			<td>Languages</td>
138
+			<td>male</td>
139
+
140
+			<td>80</td>
141
+			<td>70</td>
142
+			<td>75</td>
143
+			<td>80</td>
144
+		</tr>
145
+		<tr>
146
+			<td>Student02</td>
147
+
148
+			<td>Mathematics</td>
149
+			<td>male</td>
150
+			<td>90</td>
151
+			<td>88</td>
152
+			<td>100</td>
153
+			<td>90</td>
154
+
155
+		</tr>
156
+		<tr>
157
+			<td>Student03</td>
158
+			<td>Languages</td>
159
+			<td>female</td>
160
+			<td>85</td>
161
+			<td>95</td>
162
+
163
+			<td>80</td>
164
+			<td>85</td>
165
+		</tr>
166
+		<tr>
167
+			<td>Student04</td>
168
+			<td>Languages</td>
169
+			<td>male</td>
170
+
171
+			<td>60</td>
172
+			<td>55</td>
173
+			<td>100</td>
174
+			<td>100</td>
175
+		</tr>
176
+		<tr>
177
+			<td>Student05</td>
178
+
179
+			<td>Languages</td>
180
+			<td>female</td>
181
+			<td>68</td>
182
+			<td>80</td>
183
+			<td>95</td>
184
+			<td>80</td>
185
+
186
+		</tr>
187
+		<tr>
188
+			<td>Student06</td>
189
+			<td>Mathematics</td>
190
+			<td>male</td>
191
+			<td>100</td>
192
+			<td>99</td>
193
+
194
+			<td>100</td>
195
+			<td>90</td>
196
+		</tr>
197
+		<tr>
198
+			<td>Student07</td>
199
+			<td>Mathematics</td>
200
+			<td>male</td>
201
+
202
+			<td>85</td>
203
+			<td>68</td>
204
+			<td>90</td>
205
+			<td>90</td>
206
+		</tr>
207
+		<tr>
208
+			<td>Student08</td>
209
+
210
+			<td>Languages</td>
211
+			<td>male</td>
212
+			<td>100</td>
213
+			<td>90</td>
214
+			<td>90</td>
215
+			<td>85</td>
216
+
217
+		</tr>
218
+		<tr>
219
+			<td>Student09</td>
220
+			<td>Mathematics</td>
221
+			<td>male</td>
222
+			<td>80</td>
223
+			<td>50</td>
224
+
225
+			<td>65</td>
226
+			<td>75</td>
227
+		</tr>
228
+		<tr>
229
+			<td>Student10</td>
230
+			<td>Languages</td>
231
+			<td>male</td>
232
+
233
+			<td>85</td>
234
+			<td>100</td>
235
+			<td>100</td>
236
+			<td>90</td>
237
+		</tr>
238
+		<tr>
239
+			<td>Student11</td>
240
+
241
+			<td>Languages</td>
242
+			<td>male</td>
243
+			<td>86</td>
244
+			<td>85</td>
245
+			<td>100</td>
246
+			<td>100</td>
247
+
248
+		</tr>
249
+		<tr>
250
+			<td>Student12</td>
251
+			<td>Mathematics</td>
252
+			<td>female</td>
253
+			<td>100</td>
254
+			<td>75</td>
255
+
256
+			<td>70</td>
257
+			<td>85</td>
258
+		</tr>
259
+		<tr>
260
+			<td>Student13</td>
261
+			<td>Languages</td>
262
+			<td>female</td>
263
+
264
+			<td>100</td>
265
+			<td>80</td>
266
+			<td>100</td>
267
+			<td>90</td>
268
+		</tr>
269
+		<tr>
270
+			<td>Student14</td>
271
+
272
+			<td>Languages</td>
273
+			<td>female</td>
274
+			<td>50</td>
275
+			<td>45</td>
276
+			<td>55</td>
277
+			<td>90</td>
278
+
279
+		</tr>
280
+		<tr>
281
+			<td>Student15</td>
282
+			<td>Languages</td>
283
+			<td>male</td>
284
+			<td>95</td>
285
+			<td>35</td>
286
+
287
+			<td>100</td>
288
+			<td>90</td>
289
+		</tr>
290
+		<tr>
291
+			<td>Student16</td>
292
+			<td>Languages</td>
293
+			<td>female</td>
294
+
295
+			<td>100</td>
296
+			<td>50</td>
297
+			<td>30</td>
298
+			<td>70</td>
299
+		</tr>
300
+		<tr>
301
+			<td>Student17</td>
302
+
303
+			<td>Languages</td>
304
+			<td>female</td>
305
+			<td>80</td>
306
+			<td>100</td>
307
+			<td>55</td>
308
+			<td>65</td>
309
+
310
+		</tr>
311
+		<tr>
312
+			<td>Student18</td>
313
+			<td>Mathematics</td>
314
+			<td>male</td>
315
+			<td>30</td>
316
+			<td>49</td>
317
+
318
+			<td>55</td>
319
+			<td>75</td>
320
+		</tr>
321
+		<tr>
322
+			<td>Student19</td>
323
+			<td>Languages</td>
324
+			<td>male</td>
325
+
326
+			<td>68</td>
327
+			<td>90</td>
328
+			<td>88</td>
329
+			<td>70</td>
330
+		</tr>
331
+		<tr>
332
+			<td>Student20</td>
333
+
334
+			<td>Mathematics</td>
335
+			<td>male</td>
336
+			<td>40</td>
337
+			<td>45</td>
338
+			<td>40</td>
339
+			<td>80</td>
340
+
341
+		</tr>
342
+		<tr>
343
+			<td>Student21</td>
344
+			<td>Languages</td>
345
+			<td>male</td>
346
+			<td>50</td>
347
+			<td>45</td>
348
+
349
+			<td>100</td>
350
+			<td>100</td>
351
+		</tr>
352
+		<tr>
353
+			<td>Student22</td>
354
+			<td>Mathematics</td>
355
+			<td>male</td>
356
+
357
+			<td>100</td>
358
+			<td>99</td>
359
+			<td>100</td>
360
+			<td>90</td>
361
+		</tr>
362
+		<tr>
363
+			<td>Student23</td>
364
+
365
+			<td>Languages</td>
366
+			<td>female</td>
367
+			<td>85</td>
368
+			<td>80</td>
369
+			<td>80</td>
370
+			<td>80</td>
371
+
372
+		</tr>
373
+	</tbody>
374
+</table>
375
+</div>
376
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
377
+<script type="text/javascript">
378
+_uacct = "UA-2189649-2";
379
+urchinTracker();
380
+</script>
381
+</body>
382
+</html>
383
+

Binär
tracim/tracim/public/assets/tablesorter/docs/img/external.png Visa fil


+ 577 - 0
tracim/tracim/public/assets/tablesorter/docs/index.html Visa fil

1
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us">
4
+<head>
5
+	<title>jQuery plugin: Tablesorter 2.0</title>
6
+	<link rel="stylesheet" href="css/jq.css" type="text/css" media="print, projection, screen" />
7
+	<link rel="stylesheet" href="../themes/blue/style.css" type="text/css" media="print, projection, screen" />
8
+	<script type="text/javascript" src="../jquery-latest.js"></script>
9
+	<script type="text/javascript" src="../jquery.tablesorter.js"></script>
10
+	<script type="text/javascript" src="js/chili/chili-1.8b.js"></script>
11
+	<script type="text/javascript" src="js/docs.js"></script>
12
+	<script type="text/javascript">
13
+	$(function() {		
14
+		$("#tablesorter-demo").tablesorter({sortList:[[0,0],[2,1]], widgets: ['zebra']});
15
+		$("#options").tablesorter({sortList: [[0,0]], headers: { 3:{sorter: false}, 4:{sorter: false}}});
16
+	});	
17
+	</script>
18
+</head>
19
+<body>
20
+<div id="banner">	
21
+	<h1>table<em>sorter</em></h1>
22
+	<h2>Documentation</h2>
23
+	<h3>Flexible client-side table sorting</h3>
24
+	<a href="#"></a>
25
+</div>
26
+<div id="main">
27
+	<div class="digg">
28
+		<script src="http://images.del.icio.us/static/js/blogbadge.js"></script>
29
+	</div>
30
+	
31
+	<p>
32
+	  	<strong>Author:</strong> <a class="external" href="http://lovepeacenukes.com">Christian Bach</a><br />
33
+		<strong>Version:</strong> 2.0.5 (<a href="../changelog">changelog</a>)<br />
34
+		<strong>Licence:</strong> 
35
+		Dual licensed under <a class="external" href="http://www.opensource.org/licenses/mit-license.php">MIT</a>
36
+		or <a class="external" href="http://www.opensource.org/licenses/gpl-license.php">GPL</a> licenses.
37
+	</p>
38
+	
39
+	<p class="tip update">
40
+		<em>Update!</em> New version!, and the tablesorter docs are now available in russian, head over to <a class="external" href="http://tablesorter.ru/docs/">tablesorter.ru</a>
41
+	</p>
42
+	
43
+	<p class="tip">
44
+		<em>Helping out!</em> If you like tablesorter and you're feeling generous, take a look at my <a  class="external" href="http://www.amazon.com/gp/registry/wishlist/3VAOWCL63NEA6/ref=wl_web/">Amazon Wish List</a>
45
+	</p>
46
+
47
+
48
+	<p>Comments and love letters can be sent to: <span class="email">christian at tablesorter dot com</span>.</p>
49
+	
50
+	<p> </p>
51
+
52
+
53
+
54
+	<!--
55
+	<p class="tip">
56
+		<em>Help!</em> keep tablesorter.com up and running. If you like tablesorter, have a couple of bucks over or just feel like it. Please donate.</p>
57
+	</p>
58
+	
59
+	<form name="_xclick" action="https://www.paypal.com/cgi-bin/webscr" method="post">
60
+	<input type="hidden" name="cmd" value="_xclick">
61
+	<input type="hidden" name="business" value="christian.bach@polyester.se">
62
+	<input type="hidden" name="item_name" value="Tablesorter donation">
63
+	<input type="hidden" name="currency_code" value="USD">
64
+	<input type="hidden" name="amount" value="10.00">
65
+	<input type="image" src="https://www.paypal.com/en_US/i/btn/x-click-but04.gif" border="0" name="submit" alt="Make payments with PayPal - it's fast, free and secure!">
66
+	</form>
67
+	-->
68
+	
69
+	
70
+	
71
+	<a name="Contents"></a>
72
+	<h1>Contents</h1>
73
+	<ol>
74
+		<li><a href="#Introduction">Introduction</a></li>
75
+		<li><a href="#Demo">Demo</a></li>
76
+		<li><a href="#Getting-Started">Getting started</a></li>
77
+		
78
+		<li><a href="#Examples">Examples</a></li>
79
+		
80
+		<li><a href="#Configuration">Configuration</a></li>
81
+		<li><a href="#Download">Download</a></li>
82
+		<li><a href="#Compatibility">Compatibility</a></li>
83
+		<li><a href="#Support">Support</a></li>
84
+		<li><a href="#Credits">Credits</a></li>
85
+	</ol>
86
+
87
+	<a name="Introduction"></a>
88
+	<h1>Introduction</h1>
89
+	<p>
90
+		tablesorter is a <a class="external" href="http://jquery.com">jQuery</a> plugin for turning a
91
+	  	standard HTML table with THEAD and TBODY tags into a sortable table without page refreshes.  
92
+	  	tablesorter can successfully parse and sort many types of data including linked data in a cell.  	  	
93
+		It has many useful features including:
94
+	</p>
95
+  	
96
+  	<ul>
97
+  		<li>Multi-column sorting</li>
98
+  		<li>Parsers for sorting text, URIs, integers, currency, floats, IP addresses, dates (ISO, long and short formats), time.  <a href="example-parsers.html">Add your own easily</a></li>
99
+  		<!--
100
+		<li>Support for ROWSPAN and COLSPAN on TH elements</li>
101
+		-->
102
+  		<li>Support secondary "hidden" sorting (e.g., maintain alphabetical sort when sorting on other criteria)</li>
103
+  		<li>Extensibility via <a href="example-widgets.html">widget system</a></li>
104
+  		<li>Cross-browser: IE 6.0+, FF 2+, Safari 2.0+, Opera 9.0+</li>	
105
+		<li>Small code size</li>
106
+
107
+  	</ul>
108
+  
109
+	<a name="Demo"></a>
110
+	<h1>Demo</h1>
111
+
112
+	<table id="tablesorter-demo" class="tablesorter" border="0" cellpadding="0" cellspacing="1">
113
+		<thead>
114
+			<tr>
115
+				<th>First Name</th>
116
+				<th>Last Name</th>
117
+				<th>Age</th>
118
+				<th>Total</th>
119
+				<th>Discount</th>
120
+				<th>Difference</th>
121
+				<th>Date</th>
122
+			</tr>
123
+		</thead>
124
+		<tbody>
125
+			<tr>
126
+				<td>Peter</td>
127
+				<td>Parker</td>
128
+				<td>28</td>
129
+				<td>$9.99</td>
130
+				<td>20.9%</td>
131
+				<td>+12.1</td>
132
+				<td>Jul 6, 2006 8:14 AM</td>
133
+			</tr>
134
+			<tr>
135
+				<td>John</td>
136
+				<td>Hood</td>
137
+				<td>33</td>
138
+				<td>$19.99</td>
139
+				<td>25%</td>
140
+				<td>+12</td>
141
+				<td>Dec 10, 2002 5:14 AM</td>
142
+			</tr>
143
+			<tr>
144
+				<td>Clark</td>
145
+				<td>Kent</td>
146
+				<td>18</td>
147
+				<td>$15.89</td>
148
+				<td>44%</td>
149
+				<td>-26</td>
150
+				<td>Jan 12, 2003 11:14 AM</td>
151
+			</tr>
152
+			<tr>
153
+				<td>Bruce</td>
154
+				<td>Almighty</td>
155
+				<td>45</td>
156
+				<td>$153.19</td>
157
+				<td>44.7%</td>
158
+				<td>+77</td>
159
+				<td>Jan 18, 2001 9:12 AM</td>
160
+			</tr>
161
+			<tr>
162
+				<td>Bruce</td>
163
+				<td>Evans</td>
164
+				<td>22</td>
165
+				<td>$13.19</td>
166
+				<td>11%</td>
167
+				<td>-100.9</td>
168
+				<td>Jan 18, 2007 9:12 AM</td>
169
+			</tr>
170
+			<tr>
171
+				<td>Bruce</td>
172
+				<td>Evans</td>
173
+				<td>22</td>
174
+				<td>$13.19</td>
175
+				<td>11%</td>
176
+				<td>0</td>
177
+				<td>Jan 18, 2007 9:12 AM</td>
178
+			</tr>
179
+		</tbody>
180
+	</table>
181
+	
182
+	<p class="tip">
183
+		<em>TIP!</em> Sort multiple columns simultaneously by holding down the shift key and clicking a second, third or even fourth column header!
184
+	</p>	
185
+	
186
+	
187
+		<a name="Getting-Started"></a>
188
+	<h1>Getting started</h1>
189
+	<p>
190
+		To use the tablesorter plugin, include the <a class="external" href="http://jquery.com">jQuery</a>
191
+		library and the tablesorter plugin inside the <code>&lt;head&gt;</code> tag
192
+		of your HTML document:
193
+	</p>
194
+	
195
+<pre class="javascript">
196
+&lt;script type=&quot;text/javascript&quot; src=&quot;/path/to/jquery-latest.js&quot;&gt;&lt;/script&gt;
197
+&lt;script type=&quot;text/javascript&quot; src=&quot;/path/to/jquery.tablesorter.js&quot;&gt;&lt;/script&gt;
198
+</pre>
199
+
200
+
201
+	<p>tablesorter works on standard HTML tables.  You must include THEAD and TBODY tags:</p>
202
+	
203
+	<pre class="html">
204
+&lt;table id="myTable" class="tablesorter"&gt;
205
+&lt;thead&gt;
206
+&lt;tr&gt;
207
+	&lt;th&gt;Last Name&lt;/th&gt;
208
+	&lt;th&gt;First Name&lt;/th&gt;
209
+	&lt;th&gt;Email&lt;/th&gt;
210
+	&lt;th&gt;Due&lt;/th&gt;
211
+	&lt;th&gt;Web Site&lt;/th&gt;
212
+&lt;/tr&gt;
213
+&lt;/thead&gt;
214
+&lt;tbody&gt;
215
+&lt;tr&gt;
216
+	&lt;td&gt;Smith&lt;/td&gt;
217
+	&lt;td&gt;John&lt;/td&gt;
218
+	&lt;td&gt;jsmith@gmail.com&lt;/td&gt;
219
+	&lt;td&gt;$50.00&lt;/td&gt;
220
+	&lt;td&gt;http://www.jsmith.com&lt;/td&gt;
221
+&lt;/tr&gt;
222
+&lt;tr&gt;
223
+	&lt;td&gt;Bach&lt;/td&gt;
224
+	&lt;td&gt;Frank&lt;/td&gt;
225
+	&lt;td&gt;fbach@yahoo.com&lt;/td&gt;
226
+	&lt;td&gt;$50.00&lt;/td&gt;
227
+	&lt;td&gt;http://www.frank.com&lt;/td&gt;
228
+&lt;/tr&gt;
229
+&lt;tr&gt;
230
+	&lt;td&gt;Doe&lt;/td&gt;
231
+	&lt;td&gt;Jason&lt;/td&gt;
232
+	&lt;td&gt;jdoe@hotmail.com&lt;/td&gt;
233
+	&lt;td&gt;$100.00&lt;/td&gt;
234
+	&lt;td&gt;http://www.jdoe.com&lt;/td&gt;
235
+&lt;/tr&gt;
236
+&lt;tr&gt;
237
+	&lt;td&gt;Conway&lt;/td&gt;
238
+	&lt;td&gt;Tim&lt;/td&gt;
239
+	&lt;td&gt;tconway@earthlink.net&lt;/td&gt;
240
+	&lt;td&gt;$50.00&lt;/td&gt;
241
+	&lt;td&gt;http://www.timconway.com&lt;/td&gt;
242
+&lt;/tr&gt;
243
+&lt;/tbody&gt;
244
+&lt;/table&gt;
245
+	</pre>
246
+
247
+
248
+	<p>Start by telling tablesorter to sort your table when the document is loaded:</p>
249
+	
250
+	
251
+	
252
+	
253
+	<pre class="javascript">
254
+$(document).ready(function()
255
+	{
256
+		$("#myTable").tablesorter();
257
+	}
258
+);
259
+	</pre>
260
+	
261
+	<p>
262
+		Click on the headers and you'll see that your table is now sortable!  You can 
263
+		also pass in configuration options when you initialize the table.  This tells
264
+		tablesorter to sort on the first and second column in ascending order.
265
+	</p>
266
+
267
+
268
+
269
+	<pre class="javascript">
270
+$(document).ready(function()
271
+	{
272
+		$("#myTable").tablesorter( {sortList: [[0,0], [1,0]]} );
273
+	}
274
+);
275
+	</pre>
276
+	
277
+	<p class="tip">
278
+		<em>NOTE!</em> tablesorter will auto-detect most data types including numbers, dates, ip-adresses for more information see <a href="#Examples">Examples</a>
279
+	</p>
280
+	
281
+	
282
+	
283
+
284
+
285
+	<a name="Examples"></a>
286
+    <h1>Examples</h1>
287
+    <p>	
288
+		These examples will show what's possible with tablesorter.  You need Javascript enabled to 
289
+		run these samples, just like you and your users will need Javascript enabled to use tablesorter.
290
+	</p>
291
+	
292
+    <strong>Basic</strong>
293
+	<ul>
294
+		<li><a href="example-option-sort-list.html">Set a initial sorting order using options</a></li>
295
+		<li><a href="example-option-digits.html">Dealing with digits!</a></li>
296
+		<li><a href="example-options-headers.html">Disable header using options</a></li>
297
+		<li><a href="example-trigger-sort.html">Sort table using a link outside the table</a></li>	
298
+		<li><a href="example-option-sort-force.html">Force a default sorting order</a></li>
299
+		<li><a href="example-option-sort-key.html">Change the default multi-sorting key</a></li>	
300
+		<li><a href="example-attribute-sort.html">Sorting on a table cell attribute</a></li>	
301
+	</ul>
302
+	<strong>Metadata - setting inline options</strong>
303
+	<ul>
304
+		<li><a href="example-meta-sort-list.html">Set a initial sorting order using metadata</a></li>
305
+		<li><a href="example-meta-headers.html">Disable header using metadata</a></li>
306
+		<li><a href="example-meta-parsers.html">Setting column parser using metadata</a></li>
307
+	</ul>	
308
+	
309
+	<strong>Advanced</strong>
310
+	<ul>
311
+		<li><a href="example-triggers.html">Triggers sortEnd and sortStart(Displaying sorting progress)</a></li>		
312
+		<li><a href="example-ajax.html">Appending table data with ajax</a></li>
313
+		<li><a href="example-empty-table.html">Initializing tablesorter on a empty table</a></li>
314
+		<li><a href="example-option-text-extraction.html">Dealing with markup inside cells</a></li>
315
+		<li><a href="example-extending-defaults.html">Extending default options</a></li>
316
+		<li><a href="example-option-debug.html">Enableing debug mode</a></li>
317
+		<li><a href="example-parsers.html">Parser, writing your own</a></li>
318
+		<li><a href="example-widgets.html">Widgets, writing your own</a></li>
319
+	</ul>
320
+	
321
+	<strong>Companion plugins</strong>
322
+	<ul>
323
+		<li><a href="example-pager.html">Pager plugin</a></li>
324
+	</ul>	
325
+	
326
+	
327
+
328
+	
329
+
330
+
331
+	<a name="Configuration"></a>
332
+	<h1>Configuration</h1>
333
+
334
+	<p>
335
+		tablesorter has many options you can pass in at initialization to achieve different effects:
336
+	</p>
337
+	
338
+
339
+
340
+  <table id="options" class="tablesorter" border="0" cellpadding="0" cellspacing="1">
341
+    <thead>
342
+      <tr>
343
+        <th>Property</th>
344
+        <th>Type</th>
345
+        <th>Default</th>
346
+        <th>Description</th>
347
+        <th>Link</th>
348
+      </tr>
349
+    </thead>
350
+    <tbody>
351
+      <tr>
352
+        <td>sortList</td>
353
+        <td>Array</td>
354
+        <td>null</td>
355
+        <td>An array of instructions for per-column sorting and direction in the format: <code>[[columnIndex, sortDirection], ... ]</code> where columnIndex is a zero-based index for your columns left-to-right and sortDirection is 0 for Ascending and 1 for Descending.  A valid argument that sorts ascending first by column 1 and then column 2 looks like: <code>[[0,0],[1,0]]</code></td>
356
+      	<td><a href="example-option-sort-list.html">Example</a></td>
357
+      </tr>
358
+      <!-- 
359
+      <tr>
360
+        <td>sortInitialOrder</td>
361
+        <td>String</td>
362
+        <td>asc</td>
363
+        <td>When clicking the header for the first time, the direction it sorts.  Valid arguments are "asc" for Ascending or "desc" for Descending.</td>
364
+        <td><a href="example-option-sort-order.html">Example</a></td>
365
+      </tr>
366
+      -->
367
+      <tr>
368
+        <td>sortMultiSortKey</td>
369
+        <td>String</td>
370
+        <td>shiftKey</td>
371
+        <td>The key used to select more than one column for multi-column sorting.  Defaults to the shift key.  Other options might be ctrlKey, altKey. <br/>Reference: <a class="external" href="http://developer.mozilla.org/en/docs/DOM:event#Properties">http://developer.mozilla.org/en/docs/DOM:event#Properties</a></td>
372
+      
373
+      	<td><a href="example-option-sort-key.html">Example</a></td>
374
+      </tr>
375
+      <tr>
376
+        <td>textExtraction</td>
377
+        <td>String Or Function</td>
378
+        <td>simple</td>
379
+        <td>
380
+        	Defines which method is used to extract data from a table cell for sorting.  
381
+        	Built-in options include "simple" and "complex".  Use complex if you have data marked up 
382
+        	inside of a table cell like: <code>&lt;td&gt;&lt;strong&gt;&lt;em&gt;123 Main Street&lt;/em&gt;&lt;/strong&gt;&lt;/td&gt;</code>.  
383
+        	Complex can be slow in large tables so consider writing your own text extraction function "myTextExtraction" which you define like:
384
+<pre class="javascript">
385
+var myTextExtraction = function(node) 
386
+{ 
387
+	// extract data from markup and return it 
388
+	return node.childNodes[0].childNodes[0].innerHTML;
389
+}
390
+$(document).ready(function()
391
+	{
392
+		$("#myTable").tableSorter( {textExtraction: myTextExtraction} );
393
+	}
394
+);
395
+</pre>  
396
+
397
+			tablesorter will pass a jQuery object containing the contents of the current cell for you to parse and return.  Thanks to Josh Nathanson for the examples.
398
+		</td>
399
+		<td><a href="example-option-text-extraction.html">Example</a></td>
400
+	  </tr>
401
+      <tr>
402
+        <td>headers</td>
403
+        <td>Object</td>
404
+        <td>null</td>
405
+        <td>
406
+        	An object of instructions for per-column controls in the format: <code>headers: { 0: { option: setting }, ... }</code>  For example, to disable 
407
+        	sorting on the first two columns of a table: <code>headers: { 0: { sorter: false}, 1: {sorter: false} }</code>
408
+        </td>
409
+        <td><a href="example-options-headers.html">Example</a></td>
410
+      </tr>
411
+      <tr>
412
+        <td>sortForce</td>
413
+        <td>Array</td>
414
+        <td>null</td>
415
+        <td>Use to add an additional forced sort that will be appended to the dynamic selections by the user.  For example, can be used to sort people alphabetically after some other user-selected sort that results in rows with the same value like dates or money due.  It can help prevent data from appearing as though it has a random secondary sort.</td>
416
+        <td><a href="example-option-sort-force.html">Example</a></td>
417
+      </tr>
418
+      <tr>
419
+        <td>widthFixed</td>
420
+        <td>Boolean</td>
421
+        <td>false</td>
422
+        <td>Indicates if tablesorter should apply fixed widths to the table columns.  This is useful for the Pager companion.  Requires the <a href="#Download-Addons">jQuery dimension plugin</a> to work.</a></td>
423
+        <td><a href="example-pager.html">Example</a></td>
424
+      </tr>
425
+      <tr>
426
+        <td>cancelSelection</td>
427
+        <td>Boolean</td>
428
+        <td>true</td>
429
+        <td>Indicates if tablesorter should disable selection of text in the table header (TH).  Makes header behave more like a button.</td>
430
+		<td></td>
431
+      </tr>
432
+      <tr>
433
+        <td>cssHeader</td>
434
+        <td>String</td>
435
+        <td>"header"</td>
436
+        <td>The CSS style used to style the header in its unsorted state.  Example from the blue skin:
437
+<pre class="css">
438
+th.header {
439
+	background-image: url(../img/small.gif);	
440
+	cursor: pointer;
441
+	font-weight: bold;
442
+	background-repeat: no-repeat;
443
+	background-position: center left;
444
+	padding-left: 20px;
445
+	border-right: 1px solid #dad9c7;
446
+	margin-left: -1px;
447
+}
448
+</pre>        	
449
+        </td>
450
+		<td></td>
451
+      </tr>
452
+      <tr>
453
+        <td>cssAsc</td>
454
+        <td>String</td>
455
+        <td>"headerSortUp"</td>
456
+        <td>The CSS style used to style the header when sorting ascending.  Example from the blue skin:
457
+<pre class="css">
458
+th.headerSortUp {
459
+	background-image: url(../img/small_asc.gif);
460
+	background-color: #3399FF;
461
+}
462
+</pre>
463
+       </td>
464
+	   <td></td>
465
+      </tr>
466
+      <tr>
467
+        <td>cssDesc</td>
468
+        <td>String</td>
469
+        <td>"headerSortDown"</td>
470
+        <td>The CSS style used to style the header when sorting descending.  Example from the blue skin:
471
+<pre  class="css">
472
+th.headerSortDown {
473
+	background-image: url(../img/small_desc.gif);
474
+	background-color: #3399FF;
475
+}
476
+</pre>
477
+       </td>
478
+	   <td></td>
479
+      </tr>
480
+	  <tr>
481
+        <td>debug</td>
482
+        <td>Boolean</td>
483
+        <td>false</td>
484
+        <td>
485
+        	Boolean flag indicating if tablesorter should display debuging information usefull for development.
486
+       </td>
487
+	   <td><a href="example-option-debug.html">Example</a></td>
488
+      </tr>
489
+    </tbody>
490
+  </table>
491
+	
492
+	
493
+	
494
+<a name="Download"></a>
495
+	<h1>Download</h1>
496
+	
497
+	<p><strong>Full release</strong> - Plugin, Documentation, Add-ons, Themes <a href="../jquery.tablesorter.zip">jquery.tablesorter.zip</a></p>
498
+	
499
+	
500
+	<p><strong>Pick n choose</strong> - Place at least the required files in a directory on your webserver that is accessible to a web browser.  Record this location.</p>
501
+	
502
+	<strong id="Download-Required">Required:</strong>
503
+	<ul>
504
+		<li><a class="external" href="http://docs.jquery.com/Downloading_jQuery#Download_jQuery">jQuery</a> (1.2.1 or higher)</li>
505
+		<li><a href="../jquery.tablesorter.min.js">jquery.tablesorter.min.js</a> (12kb, Minified for production)</li>
506
+	</ul>  
507
+		
508
+	<strong id="Download-Addons">Optional/Add-Ons:</strong>
509
+	<ul>
510
+		<li><a class="external" href="https://raw.githubusercontent.com/jquery-archive/jquery-metadata/master/jquery.metadata.js">metadata.js</a> (3,7kb <strong>Required for setting <a href="#Examples">inline options</a></strong>)</li>
511
+		<!--
512
+		<li><a class="external" href="http://dev.jquery.com/browser/trunk/plugins/dimensions/jquery.dimensions.
513
+.js?format=raw">jquery.dimensions.pack.js</a> (5,1kb, <a href="http://dean.edwards.name/packer/" class="external">packed</a>, for production. <strong>Required: for the <a href="example-pager.html">tablesorter pagination plugin</a></strong>)</li>
514
+		-->
515
+		<li><a href="../jquery.tablesorter.js">jquery.tablesorter.js</a> (17,7kb, for development)</li>
516
+		<li><a href="../addons/pager/jquery.tablesorter.pager.js">jquery.tablesorter.pager.js</a> (3,6kb, <a href="example-pager.html">tablesorter pagination plugin</a>)</li>
517
+	</ul>  
518
+	
519
+	<strong id="Download-Widgets">Widgets:</strong>
520
+	<ul>
521
+		<li><a class="external" href="http://www.jdempster.com/category/code/jquery/tablesortercookiewidget/">Cookie Widget</a>, By <a class="external" href="http://www.jdempster.com/">James Dempster</a></li>
522
+	</ul> 
523
+	
524
+	<strong id="Download-Themes">Themes:</strong>
525
+	<ul>
526
+		<li><a href="../themes/green/green.zip">Green Skin</a> - Images and CSS styles for green themed headers</li>
527
+		<li><a href="../themes/blue/blue.zip">Blue Skin</a> - Images and CSS styles for blue themed headers (as seen in the examples)</li>
528
+	</ul>  	
529
+
530
+  <a name="Compatibility"></a>
531
+  <h1>Browser Compatibility</h1>
532
+
533
+    <p>tablesorter has been tested successfully in the following browsers with Javascript enabled:</p>
534
+    <ul>
535
+    	<li>Firefox 2+</li>
536
+    	<li>Internet Explorer 6+</li>
537
+    	<li>Safari 2+</li>
538
+    	<li>Opera 9+</li>
539
+    	<li>Konqueror</li>
540
+    </ul>
541
+    
542
+    <p><a class="external" href="http://docs.jquery.com/Browser_Compatibility">jQuery Browser Compatibility</a></p>
543
+    
544
+    
545
+
546
+
547
+<a name="Support"></a>
548
+  <h1>Support</h1>
549
+  <p>
550
+        Support is available through the
551
+        <a class="external" href="http://jquery.com/discuss/">jQuery Mailing List</a>.  
552
+  </p>      
553
+  <p>Access to the jQuery Mailing List is also available through <a class="external" href="http://www.nabble.com/JQuery-f15494.html">Nabble Forums</a>.</p>
554
+
555
+
556
+  <a name="Credits"></a>
557
+  <h1>Credits</h1>
558
+  <p>
559
+  	Written by <a class="external" href="http://lovepeacenukes.com">Christian Bach</a>.
560
+  </p>
561
+  <p>
562
+	Documentation written by <a class="external" href="http://www.ghidinelli.com">Brian Ghidinelli</a>, 
563
+  	based on <a class="external" href="http://malsup.com/jquery/">Mike Alsup's</a> great documention.
564
+  </p>
565
+  <p>
566
+	<a class="external" href="http://ejohn.org">John Resig</a> for the fantastic <a class="external" href="http://jquery.com">jQuery</a>		
567
+  </p>
568
+</div>
569
+
570
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
571
+<script type="text/javascript">
572
+_uacct = "UA-2189649-2";
573
+urchinTracker();
574
+</script>
575
+</body>
576
+</html>
577
+

+ 23 - 0
tracim/tracim/public/assets/tablesorter/docs/js/docs.js Visa fil

1
+/* Stop IE flicker */
2
+if ($.browser.msie == true) document.execCommand('BackgroundImageCache', false, true);
3
+ChiliBook.recipeFolder     = "js/chili/";
4
+ChiliBook.stylesheetFolder = "js/chili/"
5
+
6
+jQuery.fn.antispam = function() {
7
+  return this.each(function(){
8
+	var email = $(this).text().toLowerCase().replace(/\sdot/g,'.').replace(/\sat/g,'@').replace(/\s+/g,'');
9
+	var URI = "mailto:" + email;
10
+	$(this).hide().before(
11
+		$("<a></a>").attr("href",URI).addClass("external").text(email)
12
+	);
13
+  });
14
+};
15
+
16
+
17
+$(function() {
18
+	$("pre.javascript").chili();
19
+	$("pre.html").chili();
20
+	$("pre.css").chili();
21
+	$("a.external").each(function() {this.target = '_new'});	
22
+	$("span.email").antispam();
23
+});

+ 29 - 0
tracim/tracim/public/assets/tablesorter/docs/js/examples.js Visa fil

1
+$(function() {
2
+
3
+	// get javascript source
4
+	$("#javascript pre").text($("#js").html());
5
+	
6
+	if($("#demo").size() > 0) {
7
+		// old school chaining...
8
+		var html = $("#demo").html()
9
+				.toLowerCase()
10
+				.replace(/\n|\t|\r/g,'')
11
+				.replace(/<td/g,'\t\t\t<td')
12
+				.replace(/<\/td>/g,'</td>\n')
13
+				.replace(/<th/g,'\t\t\t<th')
14
+				.replace(/<\/th>/g,'</th>\n')
15
+				.replace(/<\/tr>/g,'\t\t</tr>')
16
+				.replace(/<tr>/g,'\n\t\t<tr>\n')
17
+				.replace(/<thead/g,'\n\t<thead>')
18
+				.replace(/<\/thead>/g,'\n\t</thead>')
19
+				.replace(/<tbody/g,'\n\t<tbody')
20
+				.replace(/<\/tbody>/g,'\n\t</tbody>')
21
+				.replace(/<\/table>/g,'\n</table>')
22
+				.replace(/-->/g,'-->\n');
23
+				
24
+		$("#html pre").text(html);
25
+	}
26
+	$("pre.javascript").chili();
27
+	$("pre.html").chili();
28
+	$("pre.css").chili();
29
+});

+ 154 - 0
tracim/tracim/public/assets/tablesorter/jquery-latest.js Visa fil

1
+/*!
2
+ * jQuery JavaScript Library v1.4.2
3
+ * http://jquery.com/
4
+ *
5
+ * Copyright 2010, John Resig
6
+ * Dual licensed under the MIT or GPL Version 2 licenses.
7
+ * http://jquery.org/license
8
+ *
9
+ * Includes Sizzle.js
10
+ * http://sizzlejs.com/
11
+ * Copyright 2010, The Dojo Foundation
12
+ * Released under the MIT, BSD, and GPL Licenses.
13
+ *
14
+ * Date: Sat Feb 13 22:33:48 2010 -0500
15
+ */
16
+(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o<i;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,j);return a}return i?
17
+e(a[0],b):w}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function na(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function oa(a){var b,d=[],f=[],e=arguments,j,i,o,k,n,r;i=c.data(this,"events");if(!(a.liveFired===this||!i||!i.live||a.button&&a.type==="click")){a.liveFired=this;var u=i.live.slice(0);for(k=0;k<u.length;k++){i=u[k];i.origType.replace(O,"")===a.type?f.push(i.selector):u.splice(k--,1)}j=c(a.target).closest(f,a.currentTarget);n=0;for(r=
18
+j.length;n<r;n++)for(k=0;k<u.length;k++){i=u[k];if(j[n].selector===i.selector){o=j[n].elem;f=null;if(i.preType==="mouseenter"||i.preType==="mouseleave")f=c(a.relatedTarget).closest(i.selector)[0];if(!f||f!==o)d.push({elem:o,handleObj:i})}}n=0;for(r=d.length;n<r;n++){j=d[n];a.currentTarget=j.elem;a.data=j.handleObj.data;a.handleObj=j.handleObj;if(j.handleObj.origHandler.apply(j.elem,e)===false){b=false;break}}return b}}function pa(a,b){return"live."+(a&&a!=="*"?a+".":"")+b.replace(/\./g,"`").replace(/ /g,
19
+"&")}function qa(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function ra(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var j in f)for(var i in f[j])c.event.add(this,j,f[j][i],f[j][i].data)}}})}function sa(a,b,d){var f,e,j;b=b&&b[0]?b[0].ownerDocument||b[0]:s;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===s&&!ta.test(a[0])&&(c.support.checkClone||!ua.test(a[0]))){e=
20
+true;if(j=c.fragments[a[0]])if(j!==1)f=j}if(!f){f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=j?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ra=A.jQuery,Sa=A.$,s=A.document,T,Ta=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,
21
+Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&&
22
+(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this,
23
+a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
24
+"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,
25
+function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(j in e){i=a[j];o=e[j];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){i=i&&(c.isPlainObject(i)||
26
+c.isArray(i))?i:c.isArray(o)?[]:{};a[j]=c.extend(f,i,o)}else if(o!==w)a[j]=o}return a};c.extend({noConflict:function(a){A.$=Sa;if(a)A.jQuery=Ra;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",
27
+L,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",L);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&ma()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,
28
+"isPrototypeOf"))return false;var b;for(b in a);return b===w||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;a=c.trim(a);if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+
29
+a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Va.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,j=a.length,i=j===w||c.isFunction(a);if(d)if(i)for(f in a){if(b.apply(a[f],
30
+d)===false)break}else for(;e<j;){if(b.apply(a[e++],d)===false)break}else if(i)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<j&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Wa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===
31
+a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,j=a.length;e<j;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,j=0,i=a.length;j<i;j++){e=b(a[j],j,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=w}else if(b&&
32
+!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=
33
+true;if(ya)c.inArray=function(a,b){return ya.call(b,a)};T=c(s);if(s.addEventListener)L=function(){s.removeEventListener("DOMContentLoaded",L,false);c.ready()};else if(s.attachEvent)L=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML="   <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
34
+var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,
35
+parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent=
36
+false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n=
37
+s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,
38
+applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando];
39
+else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,
40
+a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===
41
+w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i,
42
+cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className){for(var j=" "+e.className+" ",
43
+i=e.className,o=0,k=b.length;o<k;o++)if(j.indexOf(" "+b[o]+" ")<0)i+=" "+b[o];e.className=c.trim(i)}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(k){var n=c(this);n.removeClass(a.call(this,k,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var j=(" "+e.className+" ").replace(Aa," "),i=0,o=b.length;i<o;i++)j=j.replace(" "+b[i]+" ",
44
+" ");e.className=c.trim(j)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var j=c(this);j.toggleClass(a.call(this,e,j.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,j=0,i=c(this),o=b,k=a.split(ca);e=k[j++];){o=f?o:!i.hasClass(e);i[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=
45
+this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(Aa," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j<d;j++){var i=
46
+e[j];if(i.selected){a=c(i).val();if(b)return a;f.push(a)}}return f}if(Ba.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Za,"")}return w}var o=c.isFunction(a);return this.each(function(k){var n=c(this),r=a;if(this.nodeType===1){if(o)r=a.call(this,k,n.val());if(typeof r==="number")r+="";if(c.isArray(r)&&Ba.test(this.type))this.checked=c.inArray(n.val(),r)>=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected=
47
+c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");
48
+a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g,
49
+function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split(".");
50
+k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a),
51
+C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B<r.length;B++){u=r[B];if(d.guid===u.guid){if(i||k.test(u.namespace)){f==null&&r.splice(B--,1);n.remove&&n.remove.call(a,u)}if(f!=
52
+null)break}}if(r.length===0||f!=null&&r.length===1){if(!n.teardown||n.teardown.call(a,o)===false)Ca(a,e,z.handle);delete C[e]}}else for(var B=0;B<r.length;B++){u=r[B];if(i||k.test(u.namespace)){c.event.remove(a,n,u.handler,B);r.splice(B--,1)}}}if(c.isEmptyObject(C)){if(b=z.handle)b.elem=null;delete z.events;delete z.handle;c.isEmptyObject(z)&&c.removeData(a)}}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=
53
+e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&&
54
+f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;
55
+if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e<j;e++){var i=d[e];if(b||f.test(i.namespace)){a.handler=i.handler;a.data=i.data;a.handleObj=i;i=i.handler.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
56
+fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
57
+d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,a.origType,c.extend({},a,{handler:oa}))},remove:function(a){var b=true,d=a.origType.replace(O,"");c.each(c.data(this,
58
+"events").live||[],function(){if(d===this.origType.replace(O,""))return b=false});b&&c.event.remove(this,a.origType,oa)}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};var Ca=s.removeEventListener?function(a,b,d){a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=
59
+a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,
60
+isImmediatePropagationStopped:Y};var Da=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},Ea=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ea:Da,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ea:Da)}}});if(!c.support.submitBubbles)c.event.special.submit=
61
+{setup:function(){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length)return na("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13)return na("submit",this,arguments)})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};
62
+if(!c.support.changeBubbles){var da=/textarea|input|select/i,ea,Fa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",
63
+e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,
64
+"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,
65
+d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j<o;j++)c.event.add(this[j],d,i,f)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&
66
+!a.preventDefault)for(var d in a)this.unbind(d,a[d]);else{d=0;for(var f=this.length;d<f;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,f){return this.live(b,d,f,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},
67
+toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Ga={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e,j){var i,o=0,k,n,r=j||this.selector,
68
+u=j?this:c(this.context);if(c.isFunction(f)){e=f;f=w}for(d=(d||"").split(" ");(i=d[o++])!=null;){j=O.exec(i);k="";if(j){k=j[0];i=i.replace(O,"")}if(i==="hover")d.push("mouseenter"+k,"mouseleave"+k);else{n=i;if(i==="focus"||i==="blur"){d.push(Ga[i]+k);i+=k}else i=(Ga[i]||i)+k;b==="live"?u.each(function(){c.event.add(this,pa(i,r),{data:f,selector:r,handler:e,origType:i,origHandler:e,preType:n})}):u.unbind(pa(i,r),e)}}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),
69
+function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",l,m=0;g[m];m++){l=g[m];if(l.nodeType===3||l.nodeType===4)h+=l.nodeValue;else if(l.nodeType!==8)h+=a(l.childNodes)}return h}function b(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];
70
+if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=l;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}m[q]=y}}}function d(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=l;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(k.filter(h,[t]).length>0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
71
+e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift();
72
+t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D||
73
+g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};k.matches=function(g,h){return k(g,null,null,h)};k.find=function(g,h,l){var m,q;if(!g)return[];
74
+for(var p=0,v=n.order.length;p<v;p++){var t=n.order[p];if(q=n.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");m=n.find[t](q,h,l);if(m!=null){g=g.replace(n.match[t],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};k.filter=function(g,h,l,m){for(var q=g,p=[],v=h,t,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var H in n.filter)if((t=n.leftMatch[H].exec(g))!=null&&t[2]){var M=n.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-
75
+1)!=="\\"){if(v===p)p=[];if(n.preFilter[H])if(t=n.preFilter[H](t,v,l,p,m,S)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=v[U])!=null;U++)if(D){I=M(D,t,U,v);var Ha=m^!!I;if(l&&I!=null)if(Ha)y=true;else v[U]=false;else if(Ha){p.push(D);y=true}}if(I!==w){l||(v=p);g=g.replace(n.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)k.error(g);else break;q=g}return v};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var n=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
76
+CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
77
+relative:{"+":function(g,h){var l=typeof h==="string",m=l&&!/\W/.test(h);l=l&&!m;if(m)h=h.toLowerCase();m=0;for(var q=g.length,p;m<q;m++)if(p=g[m]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[m]=l||p&&p.nodeName.toLowerCase()===h?p||false:p===h}l&&k.filter(h,g,true)},">":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m<q;m++){var p=g[m];if(p){l=p.parentNode;g[m]=l.nodeName.toLowerCase()===h?l:false}}}else{m=0;for(q=g.length;m<q;m++)if(p=g[m])g[m]=
78
+l?p.parentNode:p.parentNode===h;l&&k.filter(h,g,true)}},"":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("parentNode",h,m,g,p,l)},"~":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,m,g,p,l)}},find:{ID:function(g,h,l){if(typeof h.getElementById!=="undefined"&&!l)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var l=[];
79
+h=h.getElementsByName(g[1]);for(var m=0,q=h.length;m<q;m++)h[m].getAttribute("name")===g[1]&&l.push(h[m]);return l.length===0?null:l}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,l,m,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var v;(v=h[p])!=null;p++)if(v)if(q^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
80
+CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m,
81
+g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
82
+text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
83
+setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return h<l[3]-0},gt:function(g,h,l){return h>l[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=
84
+h[3];l=0;for(m=h.length;l<m;l++)if(h[l]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+q)},CHILD:function(g,h){var l=h[1],m=g;switch(l){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(l==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":l=h[2];var q=h[3];if(l===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var v=0;for(m=p.firstChild;m;m=
85
+m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;p.sizcache=h}g=g.nodeIndex-q;return l===0?g===0:g%l===0&&g/l>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
86
+"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g,
87
+h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l<m;l++)h.push(g[l]);else for(l=0;g[l];l++)h.push(g[l]);return h}}var B;if(s.documentElement.compareDocumentPosition)B=function(g,h){if(!g.compareDocumentPosition||
88
+!h.compareDocumentPosition){if(g==h)i=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)i=true;return g};else if("sourceIndex"in s.documentElement)B=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)i=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)i=true;return g};else if(s.createRange)B=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)i=true;return g.ownerDocument?-1:1}var l=g.ownerDocument.createRange(),m=
89
+h.ownerDocument.createRange();l.setStart(g,0);l.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=l.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)i=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&&
90
+q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML="<a href='#'></a>";
91
+if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}();
92
+(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}:
93
+function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)k(g,h[q],l);return k.filter(m,l)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=a;c.isXMLDoc=x;c.contains=E})();var eb=/Until$/,fb=/^(?:parents|prevUntil|prevAll)/,
94
+gb=/,/;R=Array.prototype.slice;var Ia=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,j){return!!b.call(e,j,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Ua.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
95
+c.find(a,this[f],b);if(f>0)for(var j=d;j<b.length;j++)for(var i=0;i<d;i++)if(b[i]===b[j]){b.splice(j--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ia(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ia(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j=
96
+{},i;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){i=a[e];j[i]||(j[i]=c.expr.match.POS.test(i)?c(i,b||this.context):i)}for(;f&&f.ownerDocument&&f!==b;){for(i in j){e=j[i];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a===
97
+"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
98
+d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
99
+a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType===
100
+1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/<tbody/i,jb=/<|&#?\w+;/,ta=/<script|<object|<embed|<option|<style/i,ua=/checked\s*(?:[^=]|=\s*.checked.)/i,Ma=function(a,b,d){return hb.test(d)?
101
+a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
102
+c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
103
+wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
104
+prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
105
+this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
106
+return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja,
107
+""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var j=c(this),i=j.html();j.empty().append(function(){return a.call(this,e,i)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
108
+this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,b,f))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(u){return c.nodeName(u,"table")?u.getElementsByTagName("tbody")[0]||
109
+u.appendChild(u.ownerDocument.createElement("tbody")):u}var e,j,i=a[0],o=[],k;if(!c.support.checkClone&&arguments.length===3&&typeof i==="string"&&ua.test(i))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(i))return this.each(function(u){var z=c(this);a[0]=i.call(this,u,b?z.html():w);z.domManip(a,b,d)});if(this[0]){e=i&&i.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:sa(a,this,o);k=e.fragment;if(j=k.childNodes.length===
110
+1?(k=k.firstChild):k.firstChild){b=b&&c.nodeName(j,"tr");for(var n=0,r=this.length;n<r;n++)d.call(b?f(this[n],j):this[n],n>0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]);
111
+return this}else{e=0;for(var j=d.length;e<j;e++){var i=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["",
112
+""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]==="<table>"&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e=
113
+c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]?
114
+c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja=
115
+function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=
116
+Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,
117
+"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=
118
+a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=
119
+a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/<script(.|\s)*?\/script>/gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!==
120
+"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("<div />").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this},
121
+serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),
122
+function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,
123
+global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&
124
+e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)?
125
+"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===
126
+false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B=
127
+false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",
128
+c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E||
129
+d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x);
130
+g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===
131
+1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b===
132
+"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional;
133
+if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");
134
+this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(la[d])f=la[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],
135
+"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},
136
+animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var j=c.extend({},e),i,o=this.nodeType===1&&c(this).is(":hidden"),k=this;for(i in a){var n=i.replace(ia,ja);if(i!==n){a[n]=a[i];delete a[i];i=n}if(a[i]==="hide"&&o||a[i]==="show"&&!o)return j.complete.call(this);if((i==="height"||i==="width")&&this.style){j.display=c.css(this,"display");j.overflow=this.style.overflow}if(c.isArray(a[i])){(j.specialEasing=
137
+j.specialEasing||{})[i]=a[i][1];a[i]=a[i][0]}}if(j.overflow!=null)this.style.overflow="hidden";j.curAnim=c.extend({},a);c.each(a,function(r,u){var z=new c.fx(k,j,r);if(Ab.test(u))z[u==="toggle"?o?"show":"hide":u](a);else{var C=Bb.exec(u),B=z.cur(true)||0;if(C){u=parseFloat(C[2]);var E=C[3]||"px";if(E!=="px"){k.style[r]=(u||1)+E;B=(u||1)/z.cur(true)*B;k.style[r]=B+E}if(C[1])u=(C[1]==="-="?-1:1)*u+B;z.custom(B,u,E)}else z.custom(B,u,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);
138
+this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration===
139
+"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||
140
+c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;
141
+this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=
142
+this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,
143
+e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
144
+c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?
145
+function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=
146
+this[0];if(a)return this.each(function(r){c.offset.setOffset(this,a,r)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=b,e=b.ownerDocument,j,i=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var k=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==i;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;j=e?e.getComputedStyle(b,null):b.currentStyle;
147
+k-=b.scrollTop;n-=b.scrollLeft;if(b===d){k+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&j.overflow!=="visible"){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=j}if(f.position==="relative"||f.position==="static"){k+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&
148
+f.position==="fixed"){k+=Math.max(i.scrollTop,o.scrollTop);n+=Math.max(i.scrollLeft,o.scrollLeft)}return{top:k,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),d,f,e,j=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
149
+a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b);
150
+c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,
151
+d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-
152
+f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset":
153
+"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in
154
+e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);

+ 122 - 0
tracim/tracim/public/assets/tablesorter/jquery.metadata.js Visa fil

1
+/*
2
+ * Metadata - jQuery plugin for parsing metadata from elements
3
+ *
4
+ * Copyright (c) 2006 John Resig, Yehuda Katz, J�örn Zaefferer, Paul McLanahan
5
+ *
6
+ * Dual licensed under the MIT and GPL licenses:
7
+ *   http://www.opensource.org/licenses/mit-license.php
8
+ *   http://www.gnu.org/licenses/gpl.html
9
+ *
10
+ * Revision: $Id$
11
+ *
12
+ */
13
+
14
+/**
15
+ * Sets the type of metadata to use. Metadata is encoded in JSON, and each property
16
+ * in the JSON will become a property of the element itself.
17
+ *
18
+ * There are three supported types of metadata storage:
19
+ *
20
+ *   attr:  Inside an attribute. The name parameter indicates *which* attribute.
21
+ *          
22
+ *   class: Inside the class attribute, wrapped in curly braces: { }
23
+ *   
24
+ *   elem:  Inside a child element (e.g. a script tag). The
25
+ *          name parameter indicates *which* element.
26
+ *          
27
+ * The metadata for an element is loaded the first time the element is accessed via jQuery.
28
+ *
29
+ * As a result, you can define the metadata type, use $(expr) to load the metadata into the elements
30
+ * matched by expr, then redefine the metadata type and run another $(expr) for other elements.
31
+ * 
32
+ * @name $.metadata.setType
33
+ *
34
+ * @example <p id="one" class="some_class {item_id: 1, item_label: 'Label'}">This is a p</p>
35
+ * @before $.metadata.setType("class")
36
+ * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
37
+ * @desc Reads metadata from the class attribute
38
+ * 
39
+ * @example <p id="one" class="some_class" data="{item_id: 1, item_label: 'Label'}">This is a p</p>
40
+ * @before $.metadata.setType("attr", "data")
41
+ * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
42
+ * @desc Reads metadata from a "data" attribute
43
+ * 
44
+ * @example <p id="one" class="some_class"><script>{item_id: 1, item_label: 'Label'}</script>This is a p</p>
45
+ * @before $.metadata.setType("elem", "script")
46
+ * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
47
+ * @desc Reads metadata from a nested script element
48
+ * 
49
+ * @param String type The encoding type
50
+ * @param String name The name of the attribute to be used to get metadata (optional)
51
+ * @cat Plugins/Metadata
52
+ * @descr Sets the type of encoding to be used when loading metadata for the first time
53
+ * @type undefined
54
+ * @see metadata()
55
+ */
56
+
57
+(function($) {
58
+
59
+$.extend({
60
+	metadata : {
61
+		defaults : {
62
+			type: 'class',
63
+			name: 'metadata',
64
+			cre: /({.*})/,
65
+			single: 'metadata'
66
+		},
67
+		setType: function( type, name ){
68
+			this.defaults.type = type;
69
+			this.defaults.name = name;
70
+		},
71
+		get: function( elem, opts ){
72
+			var settings = $.extend({},this.defaults,opts);
73
+			// check for empty string in single property
74
+			if ( !settings.single.length ) settings.single = 'metadata';
75
+			
76
+			var data = $.data(elem, settings.single);
77
+			// returned cached data if it already exists
78
+			if ( data ) return data;
79
+			
80
+			data = "{}";
81
+			
82
+			if ( settings.type == "class" ) {
83
+				var m = settings.cre.exec( elem.className );
84
+				if ( m )
85
+					data = m[1];
86
+			} else if ( settings.type == "elem" ) {
87
+				if( !elem.getElementsByTagName )
88
+					return undefined;
89
+				var e = elem.getElementsByTagName(settings.name);
90
+				if ( e.length )
91
+					data = $.trim(e[0].innerHTML);
92
+			} else if ( elem.getAttribute != undefined ) {
93
+				var attr = elem.getAttribute( settings.name );
94
+				if ( attr )
95
+					data = attr;
96
+			}
97
+			
98
+			if ( data.indexOf( '{' ) <0 )
99
+			data = "{" + data + "}";
100
+			
101
+			data = eval("(" + data + ")");
102
+			
103
+			$.data( elem, settings.single, data );
104
+			return data;
105
+		}
106
+	}
107
+});
108
+
109
+/**
110
+ * Returns the metadata object for the first member of the jQuery object.
111
+ *
112
+ * @name metadata
113
+ * @descr Returns element's metadata object
114
+ * @param Object opts An object contianing settings to override the defaults
115
+ * @type jQuery
116
+ * @cat Plugins/Metadata
117
+ */
118
+$.fn.metadata = function( opts ){
119
+	return $.metadata.get( this[0], opts );
120
+};
121
+
122
+})(jQuery);

Filskillnaden har hållits tillbaka eftersom den är för stor
+ 1038 - 0
tracim/tracim/public/assets/tablesorter/jquery.tablesorter.js


Filskillnaden har hållits tillbaka eftersom den är för stor
+ 4 - 0
tracim/tracim/public/assets/tablesorter/jquery.tablesorter.min.js


+ 27 - 0
tracim/tracim/public/assets/tablesorter/package.json Visa fil

1
+{
2
+  "name": "tablesorter",
3
+  "version": "2.0.5",
4
+  "description": "Flexible client-side table sorting",
5
+  "main": "jquery.tablesorter.min.js",
6
+  "directories": {
7
+    "doc": "docs"
8
+  },
9
+  "scripts": {
10
+    "test": "echo \"Error: no test specified\" && exit 1"
11
+  },
12
+  "repository": {
13
+    "type": "git",
14
+    "url": "https://github.com/christianbach/tablesorter.git"
15
+  },
16
+  "keywords": [
17
+    "client-side",
18
+    "sort",
19
+    "table"
20
+  ],
21
+  "author": "Christian Bach",
22
+  "license": "MIT, GPL",
23
+  "bugs": {
24
+    "url": "https://github.com/christianbach/tablesorter/issues"
25
+  },
26
+  "homepage": "https://github.com/christianbach/tablesorter"
27
+}

Binär
tracim/tracim/public/assets/tablesorter/themes/blue/asc.gif Visa fil


Binär
tracim/tracim/public/assets/tablesorter/themes/blue/bg.gif Visa fil


Binär
tracim/tracim/public/assets/tablesorter/themes/blue/blue.zip Visa fil


Binär
tracim/tracim/public/assets/tablesorter/themes/blue/desc.gif Visa fil


+ 39 - 0
tracim/tracim/public/assets/tablesorter/themes/blue/style.css Visa fil

1
+/* tables */
2
+table.tablesorter {
3
+	font-family:arial;
4
+	background-color: #CDCDCD;
5
+	margin:10px 0pt 15px;
6
+	font-size: 8pt;
7
+	width: 100%;
8
+	text-align: left;
9
+}
10
+table.tablesorter thead tr th, table.tablesorter tfoot tr th {
11
+	background-color: #e6EEEE;
12
+	border: 1px solid #FFF;
13
+	font-size: 8pt;
14
+	padding: 4px;
15
+}
16
+table.tablesorter thead tr .header {
17
+	background-image: url(bg.gif);
18
+	background-repeat: no-repeat;
19
+	background-position: center right;
20
+	cursor: pointer;
21
+}
22
+table.tablesorter tbody td {
23
+	color: #3D3D3D;
24
+	padding: 4px;
25
+	background-color: #FFF;
26
+	vertical-align: top;
27
+}
28
+table.tablesorter tbody tr.odd td {
29
+	background-color:#F0F0F6;
30
+}
31
+table.tablesorter thead tr .headerSortUp {
32
+	background-image: url(asc.gif);
33
+}
34
+table.tablesorter thead tr .headerSortDown {
35
+	background-image: url(desc.gif);
36
+}
37
+table.tablesorter thead tr .headerSortDown, table.tablesorter thead tr .headerSortUp {
38
+background-color: #8dbdd8;
39
+}

Binär
tracim/tracim/public/assets/tablesorter/themes/green/asc.png Visa fil


Binär
tracim/tracim/public/assets/tablesorter/themes/green/bg.png Visa fil


Binär
tracim/tracim/public/assets/tablesorter/themes/green/desc.png Visa fil


Binär
tracim/tracim/public/assets/tablesorter/themes/green/green.zip Visa fil


+ 39 - 0
tracim/tracim/public/assets/tablesorter/themes/green/style.css Visa fil

1
+table.tablesorter {
2
+	font-size: 12px;
3
+	background-color: #4D4D4D;
4
+	width: 1024px;
5
+	border: 1px solid #000;
6
+}
7
+table.tablesorter th {
8
+	text-align: left;
9
+	padding: 5px;
10
+	background-color: #6E6E6E;
11
+}
12
+table.tablesorter td {
13
+	color: #FFF;
14
+	padding: 5px;
15
+}
16
+table.tablesorter .even {
17
+	background-color: #3D3D3D;
18
+}
19
+table.tablesorter .odd {
20
+	background-color: #6E6E6E;
21
+}
22
+table.tablesorter .header {
23
+	background-image: url(bg.png);
24
+	background-repeat: no-repeat;
25
+	border-left: 1px solid #FFF;
26
+	border-right: 1px solid #000;
27
+	border-top: 1px solid #FFF;
28
+	padding-left: 30px;
29
+	padding-top: 8px;
30
+	height: auto;
31
+}
32
+table.tablesorter .headerSortUp {
33
+	background-image: url(asc.png);
34
+	background-repeat: no-repeat;
35
+}
36
+table.tablesorter .headerSortDown {
37
+	background-image: url(desc.png);
38
+	background-repeat: no-repeat;
39
+}

Binär
tracim/tracim/public/assets/tablesorter/themes/tracim/asc.gif Visa fil


Binär
tracim/tracim/public/assets/tablesorter/themes/tracim/bg.gif Visa fil


Binär
tracim/tracim/public/assets/tablesorter/themes/tracim/desc.gif Visa fil


+ 21 - 0
tracim/tracim/public/assets/tablesorter/themes/tracim/style.css Visa fil

1
+/* tables */
2
+table.tablesorter {
3
+}
4
+table.tablesorter thead tr th, table.tablesorter tfoot tr th {
5
+    /*background-color: #e6EEEE;*/
6
+}
7
+table.tablesorter thead tr .header {
8
+    background-image: url(bg.gif);
9
+    background-repeat: no-repeat;
10
+    background-position: center right;
11
+    cursor: pointer;
12
+}
13
+table.tablesorter tbody td { }
14
+table.tablesorter tbody tr.odd td { }
15
+table.tablesorter thead tr .headerSortUp {
16
+    background-image: url(asc.gif);
17
+}
18
+table.tablesorter thead tr .headerSortDown { background-image: url(desc.gif); }
19
+table.tablesorter thead tr .headerSortDown, table.tablesorter thead tr .headerSortUp {
20
+background-color: #F5F5F5;
21
+}

+ 63 - 0
tracim/tracim/public/mail.html Visa fil

1
+<html>
2
+  <head>
3
+    <style>
4
+      a { color: #3465af;}
5
+      a.call-to-action {
6
+        background: #3465af;
7
+        padding: 3px 4px 5px 4px;
8
+        border: 1px solid #12438d;
9
+        font-weight: bold;
10
+        color: #FFF;
11
+        text-decoration: none;
12
+        margin-left: 5px;
13
+      }
14
+      a.call-to-action img { vertical-align: middle;}
15
+      th { vertical-align: top;}
16
+    </style>
17
+  </head>
18
+  <body style="font-family: Arial; font-size: 12px; width: 600px; margin: 0; padding: 0;">
19
+
20
+    <table style="width: 600px; cell-padding: 0; 	border-collapse: collapse; margin: 0">
21
+      <tr style="background-color: F5F5F5; border-bottom: 1px solid #CCC;" >
22
+        <td style="background-color: #666;">
23
+          <img src="http://team.trac.im/assets/img/logo.png" style="vertical-align: middle;"/>
24
+        </td>
25
+        <td style="padding: 0.5em; background-color: #666; text-align: left;">
26
+          <span style="font-size: 1.3em; color: #FFF; font-weight: bold;">
27
+          PROPOSITIONS D'AMELIORATIONS <br/>&mdash;
28
+            <span style="font-weight: bold; color: #999; font-weight: bold;">
29
+                discussion en cours
30
+                <img src="http://team.trac.im/assets/icons/16x16/status/status-open.png" style="vertical-align: middle;">
31
+            </span>
32
+          </span>
33
+          
34
+        </td>
35
+      </tr>
36
+    </table>
37
+
38
+    <p style="margin: 0; border: 1em solid #DDD; border-width: 0 0 0 0em; padding: 1em 1em 1em 1em;">
39
+      <span style="font-size: 1.5em; color: #666; font-weight: bold;">RIVALLAN JOEL</span> a ajouté un commentaire :
40
+    </p>
41
+    
42
+    <div style="margin: 0em; border: 2em solid #DDD; border-width: 0 0 0 4em; padding: 0.5em 2em 1em 1em;">
43
+        <p>Vous avez surement recu pas mal de mail qui n'étaient pas justifiés.</p>
44
+        <p>Le bug va être corrigé</p>
45
+    </div>
46
+    <div style="margin: 0em; border: 0em solid #DDD; border-width: 0 0 0 4em; padding: 0.5em 1em; text-align: right;">
47
+      <span style="text-align: right; font-size: 2em; padding-right: 0.5em;">
48
+            <a href="http://0qhz.mjt.lu/link/0qhz/giqlo4v/1/RLPzmqwO_rxRDpCNXhvzGQ/aHR0cDovL3RlYW0udHJhYy5pbS93b3Jrc3BhY2VzLzE2L2ZvbGRlcnMvMTU5OC9wYWdlcy8xNTk5" style="background-color: #5CB85C; border: 1px solid #4CAE4C; color: #FFF; text-decoration: none; font-weight: bold; padding: 4px; border-radius: 3px; padding: auto 3em;">
49
+              Répondre
50
+            </a>
51
+      </span>
52
+    </div>
53
+
54
+    <hr style="border: 0px solid #CCC; border-width: 1px 0 0 0; margin-top: 4em;">
55
+
56
+    <p style="color: #999; margin-left: 0.5em;">
57
+      Damien Accorsi, vous recevez cet email car vous êtes inscrit sur le site <i>Group de travail GSP</i>
58
+      et que vous êtes <i>Workspace Manager</i> de l'espace de travail <a href="http://0qhz.mjt.lu/link/0qhz/giqlo4v/2/3HkUQ_JlhyjU5CCeDm1wNA/aHR0cDovL3RlYW0udHJhYy5pbS93b3Jrc3BhY2VzLzE2">Groupe GSP</a>
59
+    </p>
60
+  
61
+<br/><img src="http://0qhz.mjt.lu/o/0qhz/31d45b8f/giqlo4ve.gif" height="1" width="1" alt="" border="0" />
62
+</body>
63
+</html>

+ 0 - 0
tracim/tracim/templates/admin/__init__.py Visa fil


+ 7 - 0
tracim/tracim/templates/admin/user_edit.mak Visa fil

1
+<%namespace name="TIM" file="tracim.templates.pod"/>
2
+<%namespace name="FORMS" file="tracim.templates.user_workspace_forms"/>
3
+
4
+<%def name="title()"></%def>
5
+
6
+${FORMS.USER_EDIT_FORM('user-edit-form',result.user, tg.url('/admin/users/{}?_method=PUT'.format(result.user.id)), tg.url('/admin/users/{}'.format(result.user.id)))}
7
+

tracim/tracim/templates/user_get_all.mak → tracim/tracim/templates/admin/user_getall.mak Visa fil

1
-<%inherit file="local:templates.master_authenticated"/>
1
+<%inherit file="local:templates.master_authenticated_left_treeview"/>
2
+<%namespace name="LEFT_MENU" file="tracim.templates.widgets.left_menu"/>
3
+
2
 <%namespace name="TIM" file="tracim.templates.pod"/>
4
 <%namespace name="TIM" file="tracim.templates.pod"/>
3
 <%namespace name="TOOLBAR" file="tracim.templates.user_toolbars"/>
5
 <%namespace name="TOOLBAR" file="tracim.templates.user_toolbars"/>
6
+<%namespace name="ROW" file="tracim.templates.widgets.row"/>
7
+<%namespace name="ICON" file="tracim.templates.widgets.icon"/>
8
+<%namespace name="BUTTON" file="tracim.templates.widgets.button"/>
9
+
10
+
11
+<%def name="title()">${_('Users')}</%def>
12
+
13
+<%def name="SIDEBAR_LEFT_CONTENT()">
14
+    ${LEFT_MENU.ADMIN('')}
15
+    ${LEFT_MENU.TREEVIEW('sidebar-left-menu', '__')}
16
+</%def>
4
 
17
 
5
-<%def name="title()">Users</%def>
18
+<%def name="TITLE_ROW()">
19
+    <div class="row-fluid">
20
+        <div>
21
+            ${ROW.TITLE_ROW(_('Users'), 'fa-user', 'col-md-offset-3 col-md-8', 't-user-color', _('manage users and associated workspaces'))}
22
+        </div>
23
+    </div>
24
+</%def>
6
 
25
 
7
 <div class="container-fluid">
26
 <div class="container-fluid">
8
     <div class="row-fluid">
27
     <div class="row-fluid">
9
-        ${TOOLBAR.USERS(fake_api.current_user)}
10
         <div>
28
         <div>
11
-            <div class="row">
12
-                <div class="col-sm-11">
13
-                    <h1>${TIM.ICO(32, 'apps/system-users')} ${_('Users')}</h1>
14
-                </div>
15
-            </div>
16
-            
17
             ## ADD A USER
29
             ## ADD A USER
18
             % if fake_api.current_user.profile.id>=2:
30
             % if fake_api.current_user.profile.id>=2:
19
                 ## FIXME: check if the current_user is a workspace manager (so he is also allowed to create user)
31
                 ## FIXME: check if the current_user is a workspace manager (so he is also allowed to create user)
20
                 ## In this case the user is a pod manager, so he is allowed to create users (and to delete them)
32
                 ## In this case the user is a pod manager, so he is allowed to create users (and to delete them)
21
                 <div class="row">
33
                 <div class="row">
22
                     <!-- #### CREATE A USER #### -->
34
                     <!-- #### CREATE A USER #### -->
23
-                    <div class="col-sm-11">
24
-                        <p><a data-toggle="collapse" data-target="#create-user-form"><b>${_('Create a user account...')}</b></a></p>
35
+                    <div class="col-md-offset-3 col-md-8">
36
+                        <p class="t-spacer-above">
37
+                            <a class="btn btn-success" data-toggle="collapse" data-target="#create-user-form"><b>${_('Create a user account...')}</b></a>
38
+                        </p>
25
                         <div id="create-user-form" class="collapse">
39
                         <div id="create-user-form" class="collapse">
26
-                            <div class="pod-inline-form col-sm-6" >
40
+                            <div class="pod-inline-form col-md-12" >
27
                                 <form role="form" method="POST" action="${tg.url('/admin/users')}">
41
                                 <form role="form" method="POST" action="${tg.url('/admin/users')}">
28
                                     <div class="form-group">
42
                                     <div class="form-group">
29
                                         <label for="user-name">${_('Name')}</label>
43
                                         <label for="user-name">${_('Name')}</label>
67
                                             });
81
                                             });
68
                                         });
82
                                         });
69
                                     </script>
83
                                     </script>
70
-
71
                                 </form>
84
                                 </form>
72
                                 <div style="clear: both;"></div>
85
                                 <div style="clear: both;"></div>
73
                             </div>
86
                             </div>
81
 
94
 
82
             ## LIST OF USERS
95
             ## LIST OF USERS
83
             <div class="row">
96
             <div class="row">
84
-                <div  class="col-sm-11">
97
+                <div class="col-md-offset-3 col-md-8 t-spacer-above">
85
                     % if result.user_nb<=0:
98
                     % if result.user_nb<=0:
86
                         ${TIM.NO_CONTENT_INFO(_('There are no workspace yet. Start by <a class="alert-link" data-toggle="collapse" data-target="#create-workspace-form">creating a workspace</a>.'))}
99
                         ${TIM.NO_CONTENT_INFO(_('There are no workspace yet. Start by <a class="alert-link" data-toggle="collapse" data-target="#create-workspace-form">creating a workspace</a>.'))}
87
                     % else:
100
                     % else:
97
                                 </tr>
110
                                 </tr>
98
                             </thead>
111
                             </thead>
99
                             % for user in result.users:
112
                             % for user in result.users:
100
-                                <tr>
113
+                                <tr class="${('t-less-visible', '')[user.enabled]}">
101
                                     % if user.enabled:
114
                                     % if user.enabled:
102
                                         <td>
115
                                         <td>
103
-                                            ${TIM.ICO_ACTION(16, 'status/item-enabled', _('User enabled. Click to disable this user'), tg.url('/admin/users/{}/disable'.format(user.id)), fake_api.current_user, 3)}
116
+                                            ${BUTTON.FA('fa-lightbulb-o fa-lg t-enabled-color', _('User enabled. Click to disable this user'), tg.url('/admin/users/{}/disable'.format(user.id)), fake_api.current_user, 3)}
104
                                         </td>
117
                                         </td>
105
                                         <td><a href="${tg.url('/admin/users/{}'.format(user.id))}"><b>${user.name}</b></a></td>
118
                                         <td><a href="${tg.url('/admin/users/{}'.format(user.id))}"><b>${user.name}</b></a></td>
106
                                         <td><a href="mailto:${user.email}">${user.email}</a></td>
119
                                         <td><a href="mailto:${user.email}">${user.email}</a></td>
107
                                         <td>
120
                                         <td>
108
-                                            <% icon = ('emblems/emblem-unreadable', 'emblems/emblem-checked')[user.profile.id>=2] %>
121
+                                            <% icon = ('fa-square-o fa-lg t-disabled-color', 'fa-check-square-o fa-lg t-enabled-color')[user.profile.id>=2] %>
109
                                             <% linked_profile = ('tracim-profile-manager', 'tracim-profile-user')[user.profile.id>=2] %>
122
                                             <% linked_profile = ('tracim-profile-manager', 'tracim-profile-user')[user.profile.id>=2] %>
110
-                                            ${TIM.ICO_ACTION(16, icon, '', tg.url('/admin/users/{}/profile/switch?new_role={}'.format(user.id, linked_profile)), fake_api.current_user, 3)}
123
+                                            <% linked_text = (_('Click to allow workspace creation'), _('Click to disallow workspace creation'))[user.profile.id>=2] %>
124
+                                            ${BUTTON.FA(icon, linked_text, tg.url('/admin/users/{}/profile/switch?new_role={}'.format(user.id, linked_profile)), fake_api.current_user, 3)}
111
                                         </td>
125
                                         </td>
112
                                         <td>
126
                                         <td>
113
-                                            <% icon = ('emblems/emblem-unreadable', 'emblems/emblem-checked')[user.profile.id>=3] %>
127
+                                            <% icon = ('fa-square-o fa-lg t-disabled-color', 'fa-check-square-o fa-lg t-enabled-color')[user.profile.id>=3] %>
114
                                             <% linked_profile = ('tracim-profile-admin', 'tracim-profile-manager')[user.profile.id>=3] %>
128
                                             <% linked_profile = ('tracim-profile-admin', 'tracim-profile-manager')[user.profile.id>=3] %>
115
-                                            ${TIM.ICO_ACTION(16, icon, '', tg.url('/admin/users/{}/profile/switch?new_role={}'.format(user.id, linked_profile)), fake_api.current_user, 3)}
129
+                                            <% linked_text = (_('Click to give super user privileges'), _('Click to remove super user privileges'))[user.profile.id>=3] %>
130
+                                            ${BUTTON.FA(icon, linked_text, tg.url('/admin/users/{}/profile/switch?new_role={}'.format(user.id, linked_profile)), fake_api.current_user, 3)}
116
                                         </td>
131
                                         </td>
117
                                     % else:
132
                                     % else:
118
                                         <td>
133
                                         <td>
119
-                                            ${TIM.ICO_ACTION(16, 'status/item-disabled', _('User disabled. Click to enable this user'), tg.url('/admin/users/{}/enable'.format(user.id)), fake_api.current_user, 3)}
134
+                                            ${BUTTON.FA('fa-lightbulb-o fa-lg t-disabled-color', _('User disabled. Click to enable this user'), tg.url('/admin/users/{}/enable'.format(user.id)), fake_api.current_user, 3)}
120
                                         </td>
135
                                         </td>
121
-                                        <td>${user.name}</td>
136
+                                        <td><a class="t-less-visible" href="${tg.url('/admin/users/{}'.format(user.id))}">${user.name}</a></td>
122
                                         <td>${user.email}</td>
137
                                         <td>${user.email}</td>
123
                                         <td>
138
                                         <td>
124
-                                            <% icon = ('emblems/emblem-unreadable-disabled', 'emblems/emblem-checked-disabled')[user.profile.id>=2] %>
125
-                                            ${TIM.ICO(16, icon)}
139
+                                            <% icon = ('fa-square-o fa-lg t-disabled-color', 'fa-check-square-o fa-lg t-disabled-color')[user.profile.id>=2] %>
140
+                                            ${ICON.FA(icon, _('User is disabled. No action allowed'))}
126
                                         </td>
141
                                         </td>
127
                                         <td>
142
                                         <td>
128
-                                            <% icon = ('emblems/emblem-unreadable-disabled', 'emblems/emblem-checked-disabled')[user.profile.id>=3] %>
143
+                                            <% icon = ('fa-square-o fa-lg t-disabled-color', 'fa-check-square-o fa-lg t-disabled-color')[user.profile.id>=3] %>
129
                                             <% linked_profile = ('tracim-profile-admin', 'tracim-profile-manager')[user.profile.id>=3] %>
144
                                             <% linked_profile = ('tracim-profile-admin', 'tracim-profile-manager')[user.profile.id>=3] %>
130
-                                            ${TIM.ICO(16, icon)}
145
+                                            ${ICON.FA(icon, _('User is disabled. No action allowed'))}
131
                                         </td>
146
                                         </td>
132
                                     % endif
147
                                     % endif
133
                                     <td>
148
                                     <td>
134
                                         % if False==user.has_password:
149
                                         % if False==user.has_password:
135
-                                            ${TIM.ICO_TOOLTIP(16, 'emblems/emblem-readonly', _('This user has no password.'))}
136
-                                            ${_('No password defined.')}
150
+                                            ${ICON.FA_TOOLTIP('fa-key t-less-visible', _('This user has no password.'))}
151
+                                            <span class="t-less-visible">${_('No password defined.')}</span>
137
 
152
 
138
                                         % endif
153
                                         % endif
139
                                     </td>
154
                                     </td>
144
                 </div>
159
                 </div>
145
             </div>
160
             </div>
146
             ## LIST OF USERS [END]
161
             ## LIST OF USERS [END]
147
-
148
-
149
         </div>
162
         </div>
150
     </div>
163
     </div>
151
 </div>
164
 </div>

+ 110 - 0
tracim/tracim/templates/admin/user_getone.mak Visa fil

1
+<%inherit file="local:templates.master_authenticated_left_treeview_right_toolbar"/>
2
+<%namespace name="TIM" file="tracim.templates.pod"/>
3
+<%namespace name="ROW" file="tracim.templates.widgets.row"/>
4
+<%namespace name="TABLE_ROW" file="tracim.templates.widgets.table_row"/>
5
+<%namespace name="ICON" file="tracim.templates.widgets.icon"/>
6
+<%namespace name="P" file="tracim.templates.widgets.paragraph"/>
7
+<%namespace name="LEFT_MENU" file="tracim.templates.widgets.left_menu"/>
8
+<%namespace name="BUTTON" file="tracim.templates.widgets.button"/>
9
+
10
+<%namespace name="TOOLBAR" file="tracim.templates.user_toolbars"/>
11
+<%namespace name="WIDGETS" file="tracim.templates.user_workspace_widgets"/>
12
+<%def name="title()">${_('User {}').format(result.user.name)}</%def>
13
+
14
+<%def name="SIDEBAR_LEFT_CONTENT()">
15
+    ## This is the default left sidebar implementation
16
+    ${LEFT_MENU.ADMIN('')}
17
+    ${LEFT_MENU.TREEVIEW('sidebar-left-menu', '__')}
18
+</%def>
19
+
20
+<%def name="SIDEBAR_RIGHT_CONTENT()">
21
+    ${TOOLBAR.USER(fake_api.current_user, result.user)}
22
+</%def>
23
+
24
+<%def name="TITLE_ROW()">
25
+    <div class="row-fluid">
26
+        <div>
27
+            <%
28
+                if result.user.profile.id>=3:
29
+                    subtitle = _('This user is an administrator.')
30
+                elif result.user.profile.id>=2:
31
+                    subtitle = _('This user can create workspaces.')
32
+                else:
33
+                    subtitle = _('This user a standard user.')
34
+            %>
35
+            ${ROW.TITLE_ROW(result.user.name, 'fa-user', 'col-md-offset-3 col-md-7', 't-user-color', subtitle)}
36
+        </div>
37
+    </div>
38
+</%def>
39
+
40
+<div class="container-fluid">
41
+    <div class="row-fluid">
42
+        <div>
43
+            <div class="row">
44
+                <div class="col-md-offset-3 col-sm-7" id='user-profile-global-info'>
45
+                    <div>
46
+                        % if not result.user.enabled:
47
+                            <div class="alert alert-warning" style="margin-top: 1em;">
48
+                                <i class="fa fa-lg fa-warning"></i> ${_('This user is disabled')}
49
+                            </div>
50
+                        % endif
51
+                        ## TODO - D.A. - 2015-05-14
52
+                        ## Add extra information like skype, phone, website...
53
+                        <h3 style="margin-top: 1em;">
54
+                            ${ICON.FA('fa-user t-less-visible')}
55
+                            ${_('Contact')}
56
+                        </h3>
57
+                        ${P.USER_CONTACT(result.user)}
58
+                    </div>
59
+                    <div style="margin-top: 4em;">
60
+                        <h3>
61
+                            ${ICON.FA('fa-bar-chart t-less-visible')}
62
+                            ${_('Global profile')}
63
+                        </h3>
64
+                        ${P.USER_PROFILE(result.user)}
65
+                    </div>
66
+                    <div style="margin-top: 4em;">
67
+                        <h3>
68
+                            ${ICON.FA('fa-group t-less-visible')}
69
+                            ${_('Roles')}
70
+                        </h3>
71
+                        % if len(result.user.roles)<=0:
72
+                            ${WIDGETS.EMPTY_CONTENT(_('This user is not member of any workspace.'))}
73
+                        % else:
74
+                            <table class="table">
75
+                                <thead>
76
+                                    <tr>
77
+                                        <th>#</th>
78
+                                        <th>${_('Workspace')}</th>
79
+                                        <th>${_('Role')} ${BUTTON.HELP_MODAL_DIALOG('user-role-definition', 'margin-left: 0.5em;')}</th>
80
+                                        <th>${_('Notifications')}</th>
81
+                                    </tr>
82
+                                </thead>
83
+                                % for role in result.user.roles:
84
+                                    ${TABLE_ROW.USER_ROLE_IN_WORKSPACE(role)}
85
+                                % endfor
86
+                            </table>
87
+                        % endif
88
+                    </div>
89
+                </div>
90
+            </div>
91
+        </div>
92
+    </div>
93
+</div>
94
+
95
+<div id="user-edit-modal-dialog" class="modal" tabindex="-1" role="dialog" aria-hidden="true">
96
+  <div class="modal-dialog modal-sm">
97
+    <div class="modal-content">
98
+    </div>
99
+  </div>
100
+</div>
101
+
102
+<div id="user-edit-password-modal-dialog" class="modal" tabindex="-1" role="dialog" aria-hidden="true">
103
+  <div class="modal-dialog modal-sm">
104
+    <div class="modal-content">
105
+    </div>
106
+  </div>
107
+</div>
108
+
109
+## HERE COME HELP MODAL DIALOGS
110
+${TIM.HELP_MODAL_DIALOG('user-role-definition')}

+ 6 - 0
tracim/tracim/templates/admin/user_password_edit.mak Visa fil

1
+<%namespace name="TIM" file="tracim.templates.pod"/>
2
+<%namespace name="FORMS" file="tracim.templates.widgets.forms"/>
3
+<%def name="title()"></%def>
4
+
5
+${FORMS.USER_PASSWORD_EDIT_FORM_NO_OLD('user-edit-form', result.user, tg.url('/admin/users/{}/password?_method=PUT'.format(result.user.id)))}
6
+

tracim/tracim/templates/workspace_get_all.mak → tracim/tracim/templates/admin/workspace_getall.mak Visa fil

1
-<%inherit file="local:templates.master_authenticated"/>
1
+<%inherit file="local:templates.master_authenticated_left_treeview"/>
2
+<%namespace name="LEFT_MENU" file="tracim.templates.widgets.left_menu"/>
3
+
2
 <%namespace name="TIM" file="tracim.templates.pod"/>
4
 <%namespace name="TIM" file="tracim.templates.pod"/>
3
-<%namespace name="TOOLBAR" file="tracim.templates.workspace_toolbars"/>
5
+<%namespace name="TOOLBAR" file="tracim.templates.workspace.toolbar"/>
6
+<%namespace name="ROW" file="tracim.templates.widgets.row"/>
7
+<%namespace name="ICON" file="tracim.templates.widgets.icon"/>
8
+<%namespace name="BUTTON" file="tracim.templates.widgets.button"/>
9
+
10
+<%def name="title()">${_('Workspaces')}</%def>
4
 
11
 
5
-<%def name="title()">Workspaces</%def>
12
+<%def name="SIDEBAR_LEFT_CONTENT()">
13
+    ${LEFT_MENU.ADMIN('')}
14
+    ${LEFT_MENU.TREEVIEW('sidebar-left-menu', '__')}
15
+</%def>
16
+
17
+<%def name="TITLE_ROW()">
18
+    <div class="row-fluid">
19
+        <div>
20
+            ${ROW.TITLE_ROW(_('Workspaces'), 'fa-bank', 'col-md-offset-3 col-md-8', 't-user-color', _('manage workspaces and subscribed users'))}
21
+        </div>
22
+    </div>
23
+</%def>
6
 
24
 
7
 <div class="container-fluid">
25
 <div class="container-fluid">
8
     <div class="row-fluid">
26
     <div class="row-fluid">
9
-        ${TOOLBAR.WORKSPACES(fake_api.current_user)}
10
         <div>
27
         <div>
11
-            <div class="row">
12
-                <div class="col-sm-11">
13
-                    <h1>${TIM.ICO(32, 'places/folder-remote')} ${_('Workspaces')}</h1>
14
-                </div>
15
-            </div>
16
-            
17
             ## ADD A WORKSPACE
28
             ## ADD A WORKSPACE
18
             % if fake_api.current_user.profile.id>=2:
29
             % if fake_api.current_user.profile.id>=2:
19
                 ## In this case the user is a pod manager, so he is allowed to create workspaces (and to delete them)
30
                 ## In this case the user is a pod manager, so he is allowed to create workspaces (and to delete them)
20
                 <div class="row">
31
                 <div class="row">
21
                     <!-- #### CREATE A WORKSPACE #### -->
32
                     <!-- #### CREATE A WORKSPACE #### -->
22
-                    <div class="col-sm-11">
23
-                        <p><a data-toggle="collapse" data-target="#create-workspace-form"><b>${_('Create a workspace...')}</b></a></p>
33
+                    <div class="col-md-offset-3 col-md-12">
34
+                        <p class="t-spacer-above">
35
+                            <a class="btn btn-success" data-toggle="collapse" data-target="#create-workspace-form"><b>${_('Create a workspace...')}</b></a>
36
+                        </p>
24
                         <div id="create-workspace-form" class="collapse">
37
                         <div id="create-workspace-form" class="collapse">
25
                             <div class="pod-inline-form col-sm-6" >
38
                             <div class="pod-inline-form col-sm-6" >
26
                                 <form role="form" method="POST" action="${tg.url('/admin/workspaces')}">
39
                                 <form role="form" method="POST" action="${tg.url('/admin/workspaces')}">
50
             % endif
63
             % endif
51
             ## ADD A WORKSPACE [END]
64
             ## ADD A WORKSPACE [END]
52
 
65
 
53
-
54
             ## LIST OF WORKSPACES
66
             ## LIST OF WORKSPACES
55
             <div class="row">
67
             <div class="row">
56
-                <div  class="col-sm-11">
68
+                <div class="col-md-offset-3 col-md-8 t-spacer-above">
57
                     % if result.workspace_nb<=0:
69
                     % if result.workspace_nb<=0:
58
                         ${TIM.NO_CONTENT_INFO(_('There are no workspace yet. Start by <a class="alert-link" data-toggle="collapse" data-target="#create-workspace-form">creating a workspace</a>.'))}
70
                         ${TIM.NO_CONTENT_INFO(_('There are no workspace yet. Start by <a class="alert-link" data-toggle="collapse" data-target="#create-workspace-form">creating a workspace</a>.'))}
59
                     % else:
71
                     % else:
79
                 </div>
91
                 </div>
80
             </div>
92
             </div>
81
             ## LIST OF WORKSPACES [END]
93
             ## LIST OF WORKSPACES [END]
82
-
83
-
84
         </div>
94
         </div>
85
     </div>
95
     </div>
86
 </div>
96
 </div>

+ 133 - 0
tracim/tracim/templates/admin/workspace_getone.mak Visa fil

1
+<%inherit file="local:templates.master_authenticated_left_treeview_right_toolbar"/>
2
+<%namespace name="BUTTON" file="tracim.templates.widgets.button"/>
3
+<%namespace name="ICON" file="tracim.templates.widgets.icon"/>
4
+<%namespace name="LEFT_MENU" file="tracim.templates.widgets.left_menu"/>
5
+<%namespace name="P" file="tracim.templates.widgets.paragraph"/>
6
+<%namespace name="ROW" file="tracim.templates.widgets.row"/>
7
+<%namespace name="TABLE_ROW" file="tracim.templates.widgets.table_row"/>
8
+<%namespace name="TIM" file="tracim.templates.pod"/>
9
+<%namespace name="TITLE" file="tracim.templates.widgets.title"/>
10
+
11
+<%namespace name="TOOLBAR" file="tracim.templates.workspace.toolbar"/>
12
+<%namespace name="WIDGETS" file="tracim.templates.user_workspace_widgets"/>
13
+<%def name="title()">${_('Workspace {}').format(result.workspace.label)}</%def>
14
+
15
+<%def name="SIDEBAR_LEFT_CONTENT()">
16
+    ## This is the default left sidebar implementation
17
+    ${LEFT_MENU.ADMIN('')}
18
+    ${LEFT_MENU.TREEVIEW('sidebar-left-menu', '__')}
19
+</%def>
20
+
21
+<%def name="SIDEBAR_RIGHT_CONTENT()">
22
+    ${TOOLBAR.WORKSPACE(fake_api.current_user, result.workspace)}
23
+</%def>
24
+
25
+<%def name="TITLE_ROW()">
26
+    <div class="row-fluid">
27
+        <div>
28
+            <%
29
+                subtitle = _('created on {}'.format(h.formatLongDateAndTime(result.workspace.created)))
30
+            %>
31
+            ${ROW.TITLE_ROW(_('Workspace {}').format(result.workspace.label), 'fa-bank', 'col-md-offset-3 col-md-7', 't-user-color', subtitle)}
32
+        </div>
33
+    </div>
34
+</%def>
35
+
36
+<div class="container-fluid">
37
+    <div class="row-fluid">
38
+        <div>
39
+            <div class="row">
40
+                <div class="col-sm-7 col-md-offset-3">
41
+                    ${TITLE.H3(_('Detail'), 'fa-align-justify', 'workspace-members')}
42
+                    % if result.workspace.description:
43
+                        <p>${result.workspace.description}</p>
44
+                    % else:
45
+                        <p class="t-less-visible">${_('No description available')}</p>
46
+                    % endif
47
+                </div>
48
+            </div>
49
+
50
+            <div class="row">
51
+                <div class="col-sm-7 col-md-offset-3">
52
+                    <div>
53
+                        <% potential_new_user_nb = sum(1 for user in fake_api.users if user.id not in (user.id for user in result.workspace.members)) %>
54
+                        % if potential_new_user_nb<=0:
55
+                            ${TITLE.H3(_('Members'), 'fa-user', 'workspace-members')}
56
+                        % else:
57
+                            ${TITLE.H3_WITH_BUTTON(fake_api.current_user, result.workspace, 'workspace-members', _('Members'), 'add-role-from-existing-user-form', _('add one...'), 'fa-user')}
58
+
59
+                            <div id="add-role-from-existing-user-form" class="collapse col-sm-9">
60
+                                <div class="pod-inline-form">
61
+                                    <form role="form" method="POST" action="${tg.url('/admin/workspaces/{}/roles'.format(result.workspace.id))}">
62
+                                        <div class="form-group">
63
+                                            <label for="user_id">${_('User')}</label>
64
+                                            <select name="user_id" id="user_id" class="form-control">
65
+                                                % for user in fake_api.users:
66
+                                                    % if user.id not in (user.id for user in result.workspace.members):
67
+                                                        <option value="${user.id}">${user.name}</option>
68
+                                                    % endif
69
+                                                % endfor
70
+                                            </select>
71
+                                        </div>
72
+
73
+                                        <div class="form-group">
74
+                                            <label>${_('Role')} ${BUTTON.HELP_MODAL_DIALOG('user-role-definition', 'margin-left: 0.5em;')}</label>
75
+                                            % for role in fake_api.role_types:
76
+                                            <div class="radio">
77
+                                              <label>
78
+                                                <% checked = ('', 'checked="checked"')[role.id==1]%>
79
+                                                <input type="radio" name="role_id" id="role-id-${role.id}" value="${role.id}" ${checked}>
80
+                                                <span style="${role.style}"><b>${role.label}</b></span>
81
+                                              </label>
82
+                                            </div>
83
+                                            % endfor
84
+                                        </div>
85
+
86
+                                        <span class="pull-right" style="margin-top: 0.5em;">
87
+                                            <button id="current-document-add-comment-save-button" type="submit" class="btn btn-small btn-success" title="Add first comment"><i class=" fa fa-check"></i> ${_('Validate')}</button>
88
+                                        </span>
89
+                                    </form>
90
+                                    <div style="clear: both;"></div>
91
+                                </div>
92
+                            </div>
93
+                            ## END OF ADD MEMBER FORM
94
+                        % endif
95
+
96
+                        % if result.workspace.member_nb<=0:
97
+                            ${WIDGETS.EMPTY_CONTENT(_('There are no user associated to the current workspace. <a class="alert-link" data-toggle="collapse" data-target="#add-role-from-existing-user-form">Add one</a>.'))}
98
+                        % else:
99
+                            <table class="table">
100
+                                <thead>
101
+                                    <tr>
102
+                                        <th>#</th>
103
+                                        <th>${_('User')}</th>
104
+                                        <th>${_('Role')} ${BUTTON.HELP_MODAL_DIALOG('user-role-definition', 'margin-left: 0.5em;')}</th>
105
+                                        <th>${_('Notifications')}</th>
106
+                                        <th></th>
107
+                                    </tr>
108
+                                </thead>
109
+                                % for member in result.workspace.members:
110
+                                    ${TABLE_ROW.SECURED_MEMBER_IN_WORKSPACE(fake_api.current_user, result.workspace, member, fake_api.role_types)}
111
+                                % endfor
112
+                            </table>
113
+                        % endif
114
+                    </div>
115
+                </div>
116
+            </div>
117
+        </div>
118
+    </div>
119
+</div>
120
+
121
+## HERE COME HELP MODAL DIALOGS
122
+${TIM.HELP_MODAL_DIALOG('user-role-definition')}
123
+
124
+
125
+
126
+## EDIT WORKSPACE DIALOG
127
+<div id="workspace-edit-modal-dialog" class="modal bs-example-modal-lg" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel" aria-hidden="true">
128
+  <div class="modal-dialog">
129
+    <div class="modal-content">
130
+    </div>
131
+  </div>
132
+</div>
133
+

+ 0 - 45
tracim/tracim/templates/dashboard.mak Visa fil

1
-<%inherit file="local:templates.master_authenticated"/>
2
-<%namespace name="TIM" file="tracim.templates.pod"/>
3
-
4
-<%def name="title()">
5
-    ${_('Dashboard')}
6
-</%def>
7
-
8
-<div class="container-fluid">
9
-    <div class="row-fluid">
10
-        <div>
11
-            <div class="row">
12
-                <h1 class="col-sm-6 col-sm-offset-3">${TIM.ICO(32, 'status/dialog-information')} ${_("Dashboard")}</h1>
13
-            </div>
14
-            <div class="row">
15
-                <div class="col-sm-5 col-sm-offset-3">
16
-                    <div class="well">
17
-                        <h2 style="margin-top: 0;">${_('What to do ?')}</h2>
18
-                        <h3>
19
-                            ${TIM.ICO(32, 'places/folder-remote')} <a href="${tg.url('/workspaces')}">${_('Go to my workspaces')}</a>
20
-                        </h3>
21
-                        <h3>
22
-                            ${TIM.ICO(32, 'actions/contact-new')} <a href="${tg.url('/user/me')}">${_('Go to my profile')}</a>
23
-                        </h3>
24
-                    </div>
25
-                </div>
26
-            </div>
27
-            % if fake_api.current_user.profile.id >= 2:
28
-                <div class="row">
29
-                    <div class="col-sm-5 col-sm-offset-3">
30
-                        <div class="well">
31
-                            <h2 style="margin-top: 0;">${_('You can also manage...')}</h2>
32
-                            <h3>
33
-                                ${TIM.ICO(32, 'apps/system-users')} <a href="${tg.url('/admin/users')}">${_('Users')}</a>
34
-                            </h3>
35
-                            <h3>
36
-                                ${TIM.ICO(32, 'places/folder-remote')} <a href="${tg.url('/admin/workspaces')}">${_('Workspaces')}</a>
37
-                            </h3>
38
-                        </div>
39
-                    </div>
40
-                </div>
41
-            % endif
42
-        </div>
43
-    </div>
44
-</div>
45
-

+ 0 - 0
tracim/tracim/templates/file/__init__.py Visa fil


tracim/tracim/templates/user_workspace_folder_file_edit.mak → tracim/tracim/templates/file/edit.mak Visa fil


+ 56 - 0
tracim/tracim/templates/file/forms.mak Visa fil

1
+<%namespace name="TIM" file="tracim.templates.pod"/>
2
+<%namespace name="BUTTON" file="tracim.templates.widgets.button"/>
3
+<%namespace name="ICON" file="tracim.templates.widgets.icon"/>
4
+<%namespace name="WIDGETS" file="tracim.templates.user_workspace_widgets"/>
5
+
6
+<%def name="NEW(dom_id, workspace_id, parent_id=None)">
7
+    <div id="{dom_id}">
8
+        <form role="form" method="POST" enctype="multipart/form-data" action="${tg.url('/workspaces/{}/folders/{}/files'.format(workspace_id, parent_id))}">
9
+            <div class="modal-header">
10
+                <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">${_('Close')}</span></button>
11
+                <h4 class="modal-title" >${ICON.FA('fa-paperclip')} ${_('New File')}</h4>
12
+            </div>
13
+            <div class="modal-body">
14
+                <div class="form-group">
15
+                    <label for="file-label">${_('Title (optionnal)')}</label>
16
+                    <input id="file-label" class="form-control" name="label" type="text" placeholder="${_('you can give a title to the file, otherwise, the filename will be used.')}">
17
+                </div>
18
+                <div class="form-group">
19
+                    <label for="file-object">${_('Select a file')}</label>
20
+                    <input id="file-object" name="file_data" type="file" placeholder="${_('choose a file')}">
21
+                </div>
22
+            </div>
23
+            <div class="modal-footer">
24
+                <span class="pull-right" style="margin-top: 0.5em;">
25
+                    <button id="file-save-button" type="submit" class="btn btn-small btn-success" title="${_('Validate')}"><i class="fa fa-check"></i> ${_('Validate')}</button>
26
+                </span>
27
+            </div>
28
+        </form>
29
+    </div>
30
+</%def>
31
+
32
+<%def name="NEW_FILE_REVISION_WITH_COMMENT_FORM(dom_id, workspace_id, folder_id, file_id=None)">
33
+    <div id="${dom_id}" class="collapse">
34
+        <div class="pod-inline-form" >
35
+            % if file_id:
36
+                <form role="form" method="POST" enctype="multipart/form-data" action="${tg.url('/workspaces/{}/folders/{}/files/{}?_method=PUT').format(workspace_id, folder_id, file_id)}">
37
+            % else:
38
+                <form role="form" method="POST" enctype="multipart/form-data" action="${tg.url('/workspaces/{}/folders/{}/files').format(workspace_id, folder_id)}">
39
+            % endif
40
+                <div class="form-group">
41
+                    <label for="file-object">${_('Select new file revision')}</label>
42
+                    <input id="file-object" name="file_data" type="file" placeholder="${_('choose a file')}">
43
+                </div>
44
+                <div class="form-group">
45
+                    <label for="file-label">${_('Your comment...')}</label>
46
+                    <textarea id="file-label" class="form-control pod-rich-textarea" name="comment" type="text" placeholder=""></textarea>
47
+                </div>
48
+                <span class="pull-right t-modal-form-submit-button">
49
+                    <button id="${dom_id}-submit-button" type="submit" class="btn btn-small btn-success" title="${_('Validate')}"><i class=" fa fa-check"></i> ${_('Validate')}</button>
50
+                </span>
51
+
52
+                <div style="clear: both;"></div>
53
+            </form>
54
+        </div>
55
+    </div>
56
+</%def>

+ 184 - 0
tracim/tracim/templates/file/getone.mak Visa fil

1
+<%inherit file="local:templates.master_authenticated_left_treeview_right_toolbar"/>
2
+<%namespace name="TIM" file="tracim.templates.pod"/>
3
+<%namespace name="TOOLBAR" file="tracim.templates.file.toolbar"/>
4
+<%namespace name="FORMS" file="tracim.templates.file.forms"/>
5
+
6
+<%namespace name="WIDGETS" file="tracim.templates.user_workspace_widgets"/>
7
+
8
+<%namespace name="BUTTON" file="tracim.templates.widgets.button"/>
9
+<%namespace name="TABLE_ROW" file="tracim.templates.widgets.table_row"/>
10
+<%namespace name="ICON" file="tracim.templates.widgets.icon"/>
11
+<%namespace name="P" file="tracim.templates.widgets.paragraph"/>
12
+
13
+
14
+
15
+
16
+<%def name="title()">${result.file.label}</%def>
17
+
18
+<%def name="SIDEBAR_LEFT_CONTENT()">
19
+    <h4>${_('Workspaces')}</h4>
20
+    ${WIDGETS.TREEVIEW('sidebar-left-menu', 'workspace_{}__item_{}'.format(result.file.workspace.id, result.file.id))}
21
+    <hr/>
22
+</%def>
23
+
24
+<%def name="SIDEBAR_RIGHT_CONTENT()">
25
+    ${TOOLBAR.SECURED_FILE(fake_api.current_user, result.file.workspace, result.file)}
26
+</%def>
27
+
28
+<%def name="REQUIRED_DIALOGS()">
29
+    ${TIM.MODAL_DIALOG('file-edit-modal-dialog', 'modal-lg')}
30
+    ${TIM.HELP_MODAL_DIALOG('content-wiki-page-definition')}
31
+</%def>
32
+
33
+############################################################################
34
+##
35
+## PAGE CONTENT BELOW
36
+##
37
+############################################################################
38
+
39
+<div class="row t-page-header-row">
40
+    <div class="col-sm-7 col-sm-offset-3 main">
41
+        <h1 class="page-header t-file-color-border">
42
+            <i class="fa fa-fw fa-lg fa-paperclip tracim-less-visible t-file-color"></i>
43
+            ${result.file.label}
44
+
45
+            <span class="pull-right">
46
+                ${WIDGETS.SECURED_SHOW_CHANGE_STATUS_FOR_FILE(fake_api.current_user, result.file.workspace, result.file)}
47
+            </span>
48
+        </h1>
49
+
50
+        <div style="margin: -1.5em auto -1.5em auto;" class="tracim-less-visible">
51
+          <p>${_('file created on {date} at {time} by <b>{author}</b>').format(date=h.date(result.file.created), time=h.time(result.file.created), author=result.file.owner.name)|n}</p>
52
+        </div>
53
+    </div>
54
+</div>
55
+
56
+% if result.file.selected_revision!='latest':
57
+    <div class="row alert alert-warning" role="alert">
58
+        <div class="col-sm-7 col-sm-offset-3">
59
+            <p>
60
+                <span class="pull-left">${ICON.FA_FW_2X('fa-warning')}</span>
61
+                ${_('You are reading <b>an old revision</b> of the current file. (the shown revision is r{}).').format(result.file.selected_revision)|n}
62
+            </p>
63
+            <a class="pull-right alert-link" href="${tg.url('/workspaces/{}/folders/{}/files/{}').format(result.file.workspace.id, result.file.parent.id, result.file.id)}">${_('Show latest revision')}</a>
64
+        </div>
65
+    </div>
66
+% endif
67
+
68
+% if result.file.status.id=='closed-deprecated':
69
+    <div class="row alert alert-warning" role="alert">
70
+        <div class="col-sm-7 col-sm-offset-3">
71
+            <p>
72
+                <span class="pull-left">${ICON.FA_FW_2X('fa-warning')}</span>
73
+                ${_('<b>This file is deprecated</b>')|n}
74
+            </p>
75
+        </div>
76
+    </div>
77
+% endif
78
+
79
+<div class="row">
80
+    <% download_url = tg.url('/workspaces/{}/folders/{}/files/{}/download?revision_id={}'.format(result.file.workspace.id, result.file.parent.id,result.file.id,result.file.selected_revision)) %>
81
+    <div class="col-sm-1 col-sm-offset-3">
82
+        <div class="t-half-spacer-above">
83
+            <img src="" style="width: 96px; border: 1px solid #999;"/>
84
+            <a style="margin-top: -116px; margin-left: 16px;" class="btn btn-default" tittle="${_('Download the file')}"
85
+                href="${download_url}" >
86
+                ${ICON.FA_FW('fa fa-download fa-2x')}
87
+            </a>
88
+        </div>
89
+    </div>
90
+    <div class="col-md-5">
91
+        <div class="t-half-spacer-above">
92
+            <table class="table table-hover table-condensed table-striped table-bordered">
93
+                <tr>
94
+                    <td class="tracim-title">${_('File')}</td>
95
+                    <td>
96
+                        <a href="${download_url}" tittle="${_('Download the file (last revision)')}">
97
+                            ${result.file.file.name}
98
+                            <span class="pull-right">
99
+                                ${ICON.FA_FW('fa fa-download')}
100
+                            </span>
101
+
102
+                        </a>
103
+                    </td>
104
+                </tr>
105
+                <tr>
106
+                    <td class="tracim-title">${_('Size')}</td>
107
+                    <td>${h.user_friendly_file_size(result.file.file.size)}</td>
108
+                </tr>
109
+                <tr>
110
+                    <td class="tracim-title">${_('Modified')}</td>
111
+                    <td>${h.format_short(result.file.created)|n} ${_('by {}').format(result.file.owner.name)}</td>
112
+                </tr>
113
+            </table>
114
+        </div>
115
+    </div>
116
+    <div class="col-md-1">
117
+        <div class="t-half-spacer-above">
118
+            % if result.file.status.id in ('closed-validated', 'closed-unvalidated'):
119
+                <span style="font-size: 1.5em;"><i class="pull-right fa fa-4x ${result.file.status.css} ${result.file.status.icon}"></i></span>
120
+            % endif
121
+        </div>
122
+    </div>
123
+</div>
124
+
125
+% if result.file.content.strip():  # only show desc if really a content
126
+    <div class="row">
127
+        <div class="col-md-7 col-sm-offset-3">
128
+            <div class="well">
129
+                ${result.file.content|n}
130
+            </div>
131
+        </div>
132
+    </div>
133
+% endif
134
+
135
+<div class="row">
136
+    <div class="col-md-7 col-sm-offset-3">
137
+        % if result.file.status.id!='open':
138
+            <p class="tracim-less-visible">${_('<b>Note</b>: You need to change status in case you want to upload a new version')|n}</p>
139
+        % else:
140
+            % if h.user_role(fake_api.current_user, result.file.workspace)<=1: # User must be a contributor to be allowed to upload files
141
+                ${WIDGETS.SECURED_SECTION_TITLE(fake_api.current_user, result.file.workspace, 'file-revisions', _('File revisions'))}
142
+                <p>${_('This file contains {} revision(s)').format(sum(1 for revision in result.file.revisions if revision.action.id=='revision'))}</p>
143
+            % else:
144
+                % if h.user_role(fake_api.current_user, result.file.workspace)>1:
145
+                    ${BUTTON.DATA_TARGET_AS_TEXT('new-file-revision', _('upload a new revision and/or comment...'), 'btn btn-success t-spacer-below')}
146
+                    ${FORMS.NEW_FILE_REVISION_WITH_COMMENT_FORM('new-file-revision', result.file.workspace.id, result.file.parent.id, result.file.id)}
147
+                % endif
148
+            % endif
149
+        % endif
150
+    </div>
151
+</div>
152
+
153
+<div class="row t-page-metadata-row t-spacer-above">
154
+    <div class="col-sm-7 col-sm-offset-3">
155
+        <div class="t-spacer-above">
156
+            <span id="associated-revisions" ></span>
157
+            <h4 class="anchored-title">${_('File revisions')}</h4>
158
+            <div>
159
+                <table class="table table-striped table-hover">
160
+                    % for revid, revision in reversed(list(enumerate(reversed(result.file.revisions)))):
161
+                        <% warning_or_not = ('', 'warning')[result.file.selected_revision==revision.id] %>
162
+                        <tr class="${warning_or_not}">
163
+## FIXME - 2015-07-22 - D.A. - Do we really need to show a rev. id ?!
164
+## <td><span class="label label-default">v${revid}</span></td>
165
+                            <td class="t-less-visible">
166
+                                <span class="label label-default">${ICON.FA_FW(revision.action.icon)}
167
+                                ${revision.action.label}</span>
168
+                            </td>
169
+                            <td>${h.date(revision.created)}</td>
170
+                            <td>${h.time(revision.created)}</td>
171
+                            <td>${revision.owner.name}</td>
172
+                            <td><a href="${tg.url('/workspaces/{}/folders/{}/files/{}?revision_id={}').format(result.file.workspace.id, result.file.parent.id, result.file.id, revision.id)}">${revision.label}</a></td>
173
+                            <td class="t-less-visible" title="${_('Currently shown')}">
174
+                                % if warning_or_not:
175
+                                    ${ICON.FA_FW('fa fa-caret-left')} ${_('shown').format(result.file.selected_revision)}
176
+                                % endif
177
+                            </td>
178
+                        </tr>
179
+                    % endfor
180
+                </table>
181
+            </div>
182
+        </div>
183
+    </div>
184
+<div/>

+ 5 - 0
tracim/tracim/templates/file/new.mak Visa fil

1
+<%namespace name="TIM" file="tracim.templates.pod"/>
2
+<%namespace name="FILE_FORMS" file="tracim.templates.file.forms"/>
3
+<%namespace name="ICON" file="tracim.templates.widgets.icon"/>
4
+
5
+${FILE_FORMS.NEW('form-file-new', result.item.workspace.id, result.item.parent.id)}

tracim/tracim/templates/file_toolbars.mak → tracim/tracim/templates/file/toolbar.mak Visa fil

1
 <%namespace name="TIM" file="tracim.templates.pod"/>
1
 <%namespace name="TIM" file="tracim.templates.pod"/>
2
+<%namespace name="ICON" file="tracim.templates.widgets.icon"/>
2
 
3
 
3
 <%def name="SECURED_FILE(user, workspace, file)">
4
 <%def name="SECURED_FILE(user, workspace, file)">
5
+    <% download_url = tg.url('/workspaces/{}/folders/{}/files/{}/download?revision_id={}'.format(result.file.workspace.id, result.file.parent.id,result.file.id,result.file.selected_revision)) %>
4
     <% edit_disabled = ('', 'disabled')[file.selected_revision!='latest' or file.status.id[:6]=='closed'] %>
6
     <% edit_disabled = ('', 'disabled')[file.selected_revision!='latest' or file.status.id[:6]=='closed'] %>
5
     <% delete_or_archive_disabled = ('', 'disabled')[file.selected_revision!='latest'] %> 
7
     <% delete_or_archive_disabled = ('', 'disabled')[file.selected_revision!='latest'] %> 
6
     % if h.user_role(user, workspace)>1:
8
     % if h.user_role(user, workspace)>1:
7
         <div class="btn-group btn-group-vertical">
9
         <div class="btn-group btn-group-vertical">
8
-            <a title="${_('Edit current file')}" class="btn btn-default ${edit_disabled}" data-toggle="modal" data-target="#file-edit-modal-dialog" data-remote="${tg.url('/workspaces/{}/folders/{}/files/{}/edit'.format(file.workspace.id, file.parent.id, file.id))}" >${TIM.ICO(32, 'apps/accessories-text-editor')}</a>
10
+            <a title="${_('Edit current file')}" class="btn btn-default ${edit_disabled}" data-toggle="modal" data-target="#file-edit-modal-dialog" data-remote="${tg.url('/workspaces/{}/folders/{}/files/{}/edit'.format(file.workspace.id, file.parent.id, file.id))}" >${ICON.FA_FW('fa fa-edit t-less-visible')} ${_('Edit')}</a>
9
         </div>
11
         </div>
10
         <p></p>
12
         <p></p>
11
     % endif
13
     % endif
12
     
14
     
13
     <div class="btn-group btn-group-vertical">
15
     <div class="btn-group btn-group-vertical">
14
-        <a href="#file-versions" role="button" class="btn btn-default" data-toggle="modal" title="${_('View versions of the file')}">${TIM.ICO(32, 'actions/gnome-document-open-recent')}</a>
16
+        <a href="download_url" role="button" class="btn btn-default" data-toggle="modal" title="${_('Download the file')}">${ICON.FA('fa fa-download t-less-visible')} ${_('Download')}</a>
17
+        <a href="#file-versions" role="button" class="btn btn-default" data-toggle="modal" title="${_('View versions of the file')}">${ICON.FA('fa fa-history t-less-visible')} ${_('Revisions')}</a>
15
 ## RESTORE LINKS IF REQUIRED        <a href="#file-associated-links" role="button" class="btn btn-default" data-toggle="modal" title="${_('View all links')}">${TIM.ICO(32, 'apps/internet-web-browser')}</a>
18
 ## RESTORE LINKS IF REQUIRED        <a href="#file-associated-links" role="button" class="btn btn-default" data-toggle="modal" title="${_('View all links')}">${TIM.ICO(32, 'apps/internet-web-browser')}</a>
16
     </div>
19
     </div>
17
     <p></p>
20
     <p></p>
20
         ## if the user can see the toolbar, it means he is the workspace manager.
23
         ## if the user can see the toolbar, it means he is the workspace manager.
21
         ## So now, we need to know if he alsa has right to delete workspaces
24
         ## So now, we need to know if he alsa has right to delete workspaces
22
         <div class="btn-group btn-group-vertical">
25
         <div class="btn-group btn-group-vertical">
23
-            <a title="${_('Archive file')}" class="btn btn-default ${delete_or_archive_disabled}" href="${tg.url('/workspaces/{}/folders/{}/files/{}/put_archive'.format(file.workspace.id, file.parent.id, file.id))}">${TIM.ICO(32, 'mimetypes/package-x-generic')}</a>
24
-            <a title="${_('Delete file')}" class="btn btn-default ${delete_or_archive_disabled}" href="${tg.url('/workspaces/{}/folders/{}/files/{}/put_delete'.format(file.workspace.id, file.parent.id, file.id))}">${TIM.ICO(32, 'status/user-trash-full')}</a>
26
+            <a title="${_('Archive file')}" class="btn btn-default ${delete_or_archive_disabled}" href="${tg.url('/workspaces/{}/folders/{}/files/{}/put_archive'.format(file.workspace.id, file.parent.id, file.id))}">${ICON.FA_FW('fa fa-archive t-less-visible')} ${_('Archive')}</a>
27
+            <a title="${_('Delete file')}" class="btn btn-default ${delete_or_archive_disabled}" href="${tg.url('/workspaces/{}/folders/{}/files/{}/put_delete'.format(file.workspace.id, file.parent.id, file.id))}">${ICON.FA_FW('fa fa-trash t-less-visible')} ${_('Delete')}</a>
25
         </div>
28
         </div>
26
     % endif
29
     % endif
27
 </%def>
30
 </%def>

+ 0 - 0
tracim/tracim/templates/folder/__init__.py Visa fil


tracim/tracim/templates/folder_edit.mak → tracim/tracim/templates/folder/edit.mak Visa fil

4
 <%def name="title()"></%def>
4
 <%def name="title()"></%def>
5
 
5
 
6
 ${FORMS.EDIT_FOLDER_FORM('edit-form', result.folder)}
6
 ${FORMS.EDIT_FOLDER_FORM('edit-form', result.folder)}
7
-

+ 82 - 0
tracim/tracim/templates/folder/forms.mak Visa fil

1
+<%namespace name="TIM" file="tracim.templates.pod"/>
2
+<%namespace name="BUTTON" file="tracim.templates.widgets.button"/>
3
+<%namespace name="ICON" file="tracim.templates.widgets.icon"/>
4
+<%namespace name="WIDGETS" file="tracim.templates.user_workspace_widgets"/>
5
+
6
+<%def name="NEW(dom_id, workspace_id, parent_id=None)">
7
+    <div id="{dom_id}">
8
+        <form role="form" method="POST" enctype="multipart/form-data" action="${tg.url('/workspaces/{workspace_id}/folders').format(workspace_id=workspace_id)}">
9
+            <input type="hidden" name="parent_id" value="${parent_id}">
10
+            <div class="modal-header">
11
+                <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">${_('Close')}</span></button>
12
+                <h4 class="modal-title" >${ICON.FA('fa-folder-open-o t-folder-color')} ${_('New Folder')}</h4>
13
+            </div>
14
+            <div class="modal-body">
15
+                <div class="form-group">
16
+                    <label for="folder-label">${_('Folder name')}</label>
17
+                    <input id="folder-label" class="form-control" name="label" type="text">
18
+                </div>
19
+                <div class="form-group">
20
+                    <p>${_('This folder may contain:')}</p>
21
+                    <p>
22
+                        <label><input id="content-folders" name="can_contain_folders" type="checkbox" checked> ${TIM.FA('fa-folder-open-o fa-fw t-folder-color')} ${_('sub-folders')}</label><br/>
23
+                        <label><input id="content-threads" name="can_contain_threads" type="checkbox" checked> ${TIM.FA('fa-comments-o fa-fw t-thread-color')} ${_('threads')}</label><br/>
24
+                        <label><input id="content-files" name="can_contain_files" type="checkbox" checked> ${TIM.FA('fa-paperclip fa-fw t-file-color')} ${_('files')}</label><br/>
25
+                        <label><input id="content-pages" name="can_contain_pages" type="checkbox" checked> ${TIM.FA('fa-file-text-o fa-fw t-page-color')} ${_('pages')}</label>
26
+## FIXME - D.A. - 2015-05-25
27
+## The help dialog is show below current dialog (so it is invisible)
28
+##                         ${BUTTON.HELP_MODAL_DIALOG('content-wiki-page-definition', 'margin-left: 0.5em;')}
29
+                    </p>
30
+                </div>
31
+            </div>
32
+            <div class="modal-footer">
33
+                <span class="pull-right" style="margin-top: 0.5em;">
34
+                    <button id="folder-save-button" type="submit" class="btn btn-small btn-success" title="${_('Create folder')}"><i class="fa fa-check"></i> ${_('Validate')}</button>
35
+                </span>
36
+            </div>
37
+        </form>
38
+    </div>
39
+</%def>
40
+
41
+<%def name="MOVE(dom_id, item, do_move_url, modal_title)">
42
+    <form role="form" method="POST" action="${do_move_url}">
43
+        <div class="modal-header">
44
+            <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">${_('Close')}</span></button>
45
+            <h4 class="modal-title">${TIM.FA('fa-arrows t-less-visible')} ${modal_title}</h4>
46
+        </div>
47
+        <div class="modal-body">
48
+            <div>
49
+                <ul class="nav nav-tabs" role="tablist">
50
+                    <li role="presentation" class="active"><a href="#move-to-same-workspace" aria-controls="move-to-same-workspace" role="tab" data-toggle="tab">${_('in current workspace...')}</a></li>
51
+                    <li role="presentation"><a href="#move-to-another-workspace" aria-controls="move-to-another-workspace" role="tab" data-toggle="tab">${_('to another workspace')}</a></li>
52
+                </ul>
53
+                <div class="tab-content">
54
+                    <div role="tabpanel" class="tab-pane active" id="move-to-same-workspace">
55
+                        <div class="t-half-spacer-above">
56
+                            <%
57
+                                selected_id = 'workspace_{}__folder_{}'.format(item.workspace.id, item.folder.id if item.folder else '')
58
+                                get_root_url = tg.url('/workspaces/treeview_root', dict(current_id=selected_id, all_workspaces=0, folder_allowed_content_types='folder', ignore_id=item.id))
59
+                                get_children_url = tg.url('/workspaces/treeview_children', dict(ignore_id=item.id, allowed_content_types='folder'))
60
+                            %>
61
+                            ${WIDGETS.TREEVIEW_DYNAMIC('move-item-treeview', selected_id, get_root_url, get_children_url, 'move_mode')}
62
+                        </div>
63
+                    </div>
64
+                    <div role="tabpanel" class="tab-pane" id="move-to-another-workspace">
65
+                        <div class="t-half-spacer-above">
66
+                            <%
67
+                                get_root_url = tg.url('/workspaces/treeview_root', dict(current_id=None, all_workspaces=1, folder_allowed_content_types='folder', ignore_id=item.id, ignore_workspace_id=item.workspace.id))
68
+                                get_children_url = tg.url('/workspaces/treeview_children', dict(ignore_id=item.id, allowed_content_types='folder'))
69
+                            %>
70
+                            ${WIDGETS.TREEVIEW_DYNAMIC('move-item-to-other-ws-treeview', None, get_root_url, get_children_url, 'move_mode', 'move-item-treeview-treeview-hidden-field')}
71
+                        </div>
72
+                    </div>
73
+                </div>
74
+            </div>
75
+        </div>
76
+        <div class="modal-footer">
77
+            <span class="pull-right t-modal-form-submit-button">
78
+                <button id="folder-save-button" type="submit" class="btn btn-small btn-success" title="${_('Validate')}"><i class="fa fa-check"></i> ${_('Validate')}</button>
79
+            </span>
80
+        </div>
81
+    </form>
82
+</%def>

+ 177 - 0
tracim/tracim/templates/folder/getone.mak Visa fil

1
+<%inherit file="local:templates.master_authenticated_left_treeview_right_toolbar"/>
2
+
3
+<%namespace name="TIM" file="tracim.templates.pod"/>
4
+<%namespace name="TOOLBAR" file="tracim.templates.folder.toolbar"/>
5
+<%namespace name="FORMS" file="tracim.templates.user_workspace_forms"/>
6
+<%namespace name="WIDGETS" file="tracim.templates.user_workspace_widgets"/>
7
+
8
+<%namespace name="BUTTON" file="tracim.templates.widgets.button"/>
9
+<%namespace name="TABLE_ROW" file="tracim.templates.widgets.table_row"/>
10
+<%namespace name="ICON" file="tracim.templates.widgets.icon"/>
11
+<%namespace name="P" file="tracim.templates.widgets.paragraph"/>
12
+
13
+<%def name="title()">${result.folder.label}</%def>
14
+
15
+<%def name="SIDEBAR_LEFT_CONTENT()">
16
+    <h4>${_('Workspaces')}</h4>
17
+    ${WIDGETS.TREEVIEW('sidebar-left-menu', 'workspace_{}__item_{}'.format(result.folder.workspace.id, result.folder.id))}
18
+</%def>
19
+
20
+<%def name="SIDEBAR_RIGHT_CONTENT()">
21
+    ${TOOLBAR.SECURED_FOLDER(fake_api.current_user, result.folder.workspace, result.folder)}
22
+</%def>
23
+
24
+<%def name="REQUIRED_DIALOGS()">
25
+    ${TIM.HELP_MODAL_DIALOG('content-wiki-page-definition')}
26
+    ${TIM.MODAL_DIALOG('folder-edit-modal-dialog')}
27
+    ${TIM.MODAL_DIALOG('folder-move-modal-dialog')}
28
+    ${TIM.MODAL_DIALOG('folder-new-modal-dialog')}
29
+    ${TIM.MODAL_DIALOG('file-new-modal-dialog')}
30
+    ${TIM.MODAL_DIALOG('page-new-modal-dialog')}
31
+    ${TIM.MODAL_DIALOG('thread-new-modal-dialog')}
32
+    ## TODO-DYNAMIC-CONTENT-HERE
33
+</%def>
34
+
35
+############################################################################
36
+##
37
+## PAGE CONTENT BELOW
38
+##
39
+############################################################################
40
+
41
+<div class="row t-page-header-row">
42
+    <div class="col-sm-7 col-sm-offset-3 main">
43
+        <h1 class="page-header t-folder-color-border">
44
+            <i class="fa fa-fw fa-lg fa-folder-open tracim-less-visible" style="color: #CCCC00"></i>
45
+            ${result.folder.label}
46
+        </h1>
47
+
48
+        <div style="margin: -1.5em auto -1.5em auto;" class="tracim-less-visible">
49
+          <p>${_('folder created on {date} at {time} by <b>{author}</b>').format(date=h.date(result.folder.created), time=h.time(result.folder.created), author=result.folder.owner.name)|n}</p>
50
+        </div>
51
+    </div>
52
+</div>
53
+
54
+<div class="row">
55
+    <div class="col-sm-7 col-sm-offset-3">
56
+
57
+        <% user_role = h.user_role(fake_api.current_user, result.folder.workspace) %>
58
+
59
+        <div class="t-spacer-above">
60
+            % if user_role > 1:
61
+                <div class="btn-group" role="group">
62
+                    <button type="button" class="btn btn-success dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
63
+                        <i class="fa fa-plus"></i> ${_('New ...')}
64
+                        <span class="caret"></span>
65
+                    </button>
66
+                    <ul class="dropdown-menu" role="menu">
67
+                        % for content_type in result.folder.allowed_content_types:
68
+                            % if content_type.id != 'folder' or user_role > 2:
69
+                                ## Only show 'new folder' to content managers
70
+                                <%
71
+                                    new_form_content_url = tg.url('/workspaces/{}/folders/{}/{}s/new'.format(result.folder.workspace.id, result.folder.id, content_type.id), params={'workspace_id': result.folder.workspace.id, 'parent_id': result.folder.id})
72
+                                    modal_dialog_id = '{content_type}-new-modal-dialog'.format(content_type=content_type.id)
73
+                                    icon_classes = content_type.icon+' '+content_type.color
74
+                                %>
75
+                                <li>${BUTTON.DATA_TARGET_AS_TEXT_AND_ICON_MODAL_WITH_REMOTE_CONTENT(modal_dialog_id, content_type.label, new_form_content_url, icon_classes)}</li>
76
+                            % endif
77
+                        % endfor
78
+                    </ul>
79
+                </div>
80
+            % endif
81
+
82
+            % if len(fake_api.sub_items) > 0:
83
+                ## INFO - D.A. - 2015-05-25
84
+                ## We hide filtering/search buttons if no content yet.
85
+                ## This make the interface more easy to use
86
+                <div class="btn-group" role="group" aria-label="...">
87
+                    ${BUTTON.TEXT('', 'btn btn-default disabled', _('hide...'))}
88
+                    % for content_type in result.folder.allowed_content_types:
89
+                        ${BUTTON.TEXT('toggle-{type}-visibility'.format(type=content_type.id), 'btn btn-default t-active-color disabled-has-priority', content_type.label)}
90
+                    % endfor
91
+                </div>
92
+
93
+                <div class="btn-group pull-right" role="group" aria-label="...">
94
+                    <input id="filtering"  type="text" class="form-control t-bg-grey" placeholder="${_('search...')}" aria-describedby="basic-addon1">
95
+                </div>
96
+            % endif
97
+        </div>
98
+
99
+        <div class="t-spacer-above">
100
+            % if user_role > 1:
101
+                ## TODO - D.A. - 2015-05-25 - Remove this part of code which becomes useless
102
+                % if result.folder.allowed_content.page:
103
+                    ${FORMS.NEW_PAGE_FORM('page-new', result.folder.workspace.id, result.folder.id)}
104
+                % endif
105
+                % if result.folder.allowed_content.thread:
106
+                    ${FORMS.NEW_THREAD_FORM('thread-new', result.folder.workspace.id, result.folder.id)}
107
+                % endif
108
+                % if result.folder.allowed_content.file:
109
+                    ## FIXME${FORMS.NEW_FILE_FORM('file-new', result.folder.workspace.id, result.folder.id)}
110
+                    ## FIXME${FORMS.NEW_FILE_FORM('file-new', result.folder.workspace.id, result.folder.id)}
111
+                % endif
112
+                % if user_role > 2 and result.folder.allowed_content.folder:
113
+                    ## FIXME${FORMS.NEW_FOLDER_FORM('folder-new', result.folder.workspace.id, result.folder.id)}
114
+                % endif
115
+            % endif
116
+
117
+            % if len(fake_api.sub_items) <= 0:
118
+                ${P.EMPTY_CONTENT(_('This folder has not yet content.'))}
119
+            % else:
120
+                <table class="table table-striped table-hover tablesorter" id="current-folder-content-list">
121
+                    <thead>
122
+                        <tr>
123
+                            <th>${_('Type')}</th>
124
+                            <th>${_('Title')}</th>
125
+                            <th>${_('Status')}</th>
126
+                            <th>${_('Remarques')}</th>
127
+                        </tr>
128
+                    </thead>
129
+                    <tbody>
130
+                        % for content in fake_api.sub_items:
131
+                            ${TABLE_ROW.CONTENT(content)}
132
+                        % endfor
133
+                    </tbody>
134
+                </table>
135
+            % endif
136
+        </div>
137
+    </div>
138
+</div>
139
+<script>
140
+    $(document).ready(function() {
141
+        $("#current-folder-content-list").DataTable({
142
+            sDom: '',
143
+            pageLength: -1
144
+        });
145
+    });
146
+
147
+    $(document).ready(function() {
148
+        $("#toggle-file-visibility").click(function() {
149
+            $('.t-table-row-file').toggle();
150
+            $('#toggle-file-visibility').toggleClass('t-active-color');
151
+            $('#toggle-file-visibility').toggleClass('t-inactive-color');
152
+        });
153
+        $("#toggle-thread-visibility").click(function() {
154
+            $('.t-table-row-thread').toggle();
155
+            $('#toggle-thread-visibility').toggleClass('t-active-color');
156
+            $('#toggle-thread-visibility').toggleClass('t-inactive-color');
157
+        });
158
+        $("#toggle-folder-visibility").click(function() {
159
+            $('.t-table-row-folder').toggle();
160
+            $('#toggle-folder-visibility').toggleClass('t-active-color');
161
+            $('#toggle-folder-visibility').toggleClass('t-inactive-color');
162
+        });
163
+        $("#toggle-page-visibility").click(function() {
164
+            $('.t-table-row-page').toggle();
165
+            $('#toggle-page-visibility').toggleClass('t-active-color');
166
+            $('#toggle-page-visibility').toggleClass('t-inactive-color');
167
+        });
168
+    });
169
+
170
+    $(document).ready(function() {
171
+        $("#filtering").on('keyup click', function() {
172
+            $("#current-folder-content-list").DataTable().search(
173
+                $("#filtering").val()
174
+            ).draw();
175
+        });
176
+    });
177
+</script>

tracim/tracim/templates/item_location_edit.mak → tracim/tracim/templates/folder/move.mak Visa fil

1
 <%namespace name="TIM" file="tracim.templates.pod"/>
1
 <%namespace name="TIM" file="tracim.templates.pod"/>
2
-<%namespace name="FORMS" file="tracim.templates.user_workspace_forms"/>
2
+<%namespace name="FORMS" file="tracim.templates.folder.forms"/>
3
 
3
 
4
 <%def name="title()"></%def>
4
 <%def name="title()"></%def>
5
 
5
 
6
 <% do_move_url = tg.url('/workspaces/{}/folders/{}/location/{}?_method=PUT').format(result.item.workspace.id, result.item.id, result.item.id) %>
6
 <% do_move_url = tg.url('/workspaces/{}/folders/{}/location/{}?_method=PUT').format(result.item.workspace.id, result.item.id, result.item.id) %>
7
-${FORMS.ITEM_MOVE_FORM('move-form', result.item, do_move_url, _('Move folder'))}
7
+${FORMS.MOVE('move-form', result.item, do_move_url, _('Move folder'))}
8
 
8
 

+ 6 - 0
tracim/tracim/templates/folder/new.mak Visa fil

1
+<%namespace name="TIM" file="tracim.templates.pod"/>
2
+<%namespace name="FOLDER_FORMS" file="tracim.templates.folder.forms"/>
3
+<%namespace name="ICON" file="tracim.templates.widgets.icon"/>
4
+
5
+${FOLDER_FORMS.NEW('form-folder-new', result.item.workspace.id, result.item.parent.id)}
6
+

tracim/tracim/templates/folder_toolbars.mak → tracim/tracim/templates/folder/toolbar.mak Visa fil

1
 <%namespace name="TIM" file="tracim.templates.pod"/>
1
 <%namespace name="TIM" file="tracim.templates.pod"/>
2
 
2
 
3
 <%def name="SECURED_FOLDER(user, workspace, folder)">
3
 <%def name="SECURED_FOLDER(user, workspace, folder)">
4
+##    <div style="width: 100%; text-align: center;">
5
+##        <a href="" title="Add to favorites" ><i class="fa fa-3x fa-fw fa-star-o tracim-less-visible"></i></a>
6
+##        <a href="" title="Subscribe to email notifications" ><i class="fa fa-3x fa-fw fa-envelope-o tracim-less-visible"></i></a>
7
+##        <hr/>
8
+##        <a href="" title="Remove from favorites" ><i class="fa fa-3x fa-fw fa-star"></i></a>
9
+##        <a href="" title="Unsubscribe" ><i class="fa fa-3x fa-fw fa-envelope"></i></a>
10
+##        <hr/>
11
+##        <a href="" class="btn btn-success" style="text-align: center;">
12
+##            <i class="fa fa-4x fa-fw fa-eye"></i><br/>
13
+##            <span style="color: #FFF">${_('mark read')}</span>
14
+##        </a>
15
+##        <hr/>
16
+##        <a href="" class="btn btn-default" style="text-align: center;">
17
+##            <i class="fa fa-4x fa-fw fa-eye-slash tracim-less-visible"></i><br/>
18
+##            <span class="tracim-less-visible">${_('mark unread')}</span>
19
+##        </a>
20
+##    </div>
21
+##    <p></p>
22
+##    <hr/>
23
+
4
     <% edit_disabled = ('', 'disabled')[folder.selected_revision!='latest' or folder.status.id[:6]=='closed'] %>
24
     <% edit_disabled = ('', 'disabled')[folder.selected_revision!='latest' or folder.status.id[:6]=='closed'] %>
5
     <%
25
     <%
6
         ## FIXME - This control should be based on the user role
26
         ## FIXME - This control should be based on the user role
11
     % if h.user_role(user, workspace)>2:
31
     % if h.user_role(user, workspace)>2:
12
         <div class="btn-group btn-group-vertical">
32
         <div class="btn-group btn-group-vertical">
13
             ## This action is allowed for content managers only
33
             ## This action is allowed for content managers only
14
-            <a title="${_('Edit current folder')}" class="btn btn-default ${edit_disabled}" data-toggle="modal" data-target="#folder-edit-modal-dialog" data-remote="${tg.url('/workspaces/{}/folders/{}/edit'.format(folder.workspace.id, folder.id))}" >${TIM.ICO(32, 'apps/accessories-text-editor')}</a>
34
+            <a title="${_('Edit current folder')}" class="btn btn-default ${edit_disabled}" data-toggle="modal" data-target="#folder-edit-modal-dialog" data-remote="${tg.url('/workspaces/{}/folders/{}/edit'.format(folder.workspace.id, folder.id))}" ><i class="fa fa-edit fa-fw tracim-less-visible"></i> ${_('Edit')}</a>
15
         </div>
35
         </div>
16
         <p></p>
36
         <p></p>
17
     % endif
37
     % endif
19
     % if user.profile.id>=3 or h.user_role(user, workspace)>=4:
39
     % if user.profile.id>=3 or h.user_role(user, workspace)>=4:
20
         <div class="btn-group btn-group-vertical">
40
         <div class="btn-group btn-group-vertical">
21
             ## This action is allowed for content managers only
41
             ## This action is allowed for content managers only
22
-            <a title="${_('Move current folder')}" class="btn btn-default ${move_disabled}" data-toggle="modal" data-target="#folder-move-modal-dialog" data-remote="${tg.url('/workspaces/{}/folders/{}/location/{}/edit'.format(folder.workspace.id, folder.id, folder.id))}" >${TIM.ICO(32, 'actions/item-move')}</a>
42
+            <a title="${_('Move current folder')}" class="btn btn-default ${move_disabled}" data-toggle="modal" data-target="#folder-move-modal-dialog" data-remote="${tg.url('/workspaces/{}/folders/{}/location/{}/edit'.format(folder.workspace.id, folder.id, folder.id))}" ><i class="fa fa-arrows fa-fw tracim-less-visible"></i> ${_('Move')}</a>
23
         </div>
43
         </div>
24
         <p></p>
44
         <p></p>
25
     % endif
45
     % endif
28
         ## if the user can see the toolbar, it means he is the workspace manager.
48
         ## if the user can see the toolbar, it means he is the workspace manager.
29
         ## So now, we need to know if he alsa has right to delete workspaces
49
         ## So now, we need to know if he alsa has right to delete workspaces
30
         <div class="btn-group btn-group-vertical">
50
         <div class="btn-group btn-group-vertical">
31
-            <a title="${_('Archive thread')}" class="btn btn-default ${delete_or_archive_disabled}" href="${tg.url('/workspaces/{}/folders/{}/put_archive'.format(folder.workspace.id, folder.id))}">${TIM.ICO(32, 'mimetypes/package-x-generic')}</a>
32
-            <a title="${_('Delete thread')}" class="btn btn-default ${delete_or_archive_disabled}" href="${tg.url('/workspaces/{}/folders/{}/put_delete'.format(folder.workspace.id, folder.id))}">${TIM.ICO(32, 'status/user-trash-full')}</a>
51
+            <a title="${_('Archive thread')}" class="btn btn-default ${delete_or_archive_disabled}" href="${tg.url('/workspaces/{}/folders/{}/put_archive'.format(folder.workspace.id, folder.id))}"><i class="fa fa-archive fa-fw tracim-less-visible"></i> ${_('Archive')}</a>
52
+            <a title="${_('Delete thread')}" class="btn btn-default ${delete_or_archive_disabled}" href="${tg.url('/workspaces/{}/folders/{}/put_delete'.format(folder.workspace.id, folder.id))}"><i class="fa fa-trash-o fa-fw tracim-less-visible"></i> ${_('Delete')}</a>
33
         </div>
53
         </div>
34
         <p></p>
54
         <p></p>
35
     % endif
55
     % endif

+ 173 - 0
tracim/tracim/templates/home.mak Visa fil

1
+<%inherit file="local:templates.master_authenticated_left_treeview_right_toolbar"/>
2
+<%namespace name="TIM" file="tracim.templates.pod"/>
3
+<%namespace name="ROW" file="tracim.templates.widgets.row"/>
4
+<%namespace name="TABLE_ROW" file="tracim.templates.widgets.table_row"/>
5
+<%namespace name="LEFT_MENU" file="tracim.templates.widgets.left_menu"/>
6
+<%namespace name="P" file="tracim.templates.widgets.paragraph"/>
7
+<%namespace name="TOOLBAR" file="tracim.templates.user_toolbars"/>
8
+
9
+<%def name="title()">
10
+    ${_('Dashboard')}
11
+</%def>
12
+
13
+<%def name="TITLE_ROW()">
14
+    <div class="row-fluid">
15
+        <div>
16
+            ${ROW.TITLE_ROW(_('My Dashboard'), 'fa-home', 'col-md-offset-3 col-md-7', 't-user-color', _('Welcome to your home, {username}.').format(username=fake_api.current_user.name))}
17
+        </div>
18
+    </div>
19
+</%def>
20
+
21
+<%def name="SIDEBAR_RIGHT_CONTENT()">
22
+    ${TOOLBAR.USER_ME(fake_api.current_user)}
23
+</%def>
24
+
25
+
26
+<%def name="SIDEBAR_LEFT_CONTENT()">
27
+    ## This is the default left sidebar implementation
28
+    % if fake_api.current_user.profile.id>2:
29
+        ${LEFT_MENU.ADMIN('')}
30
+    % endif
31
+    ${LEFT_MENU.TREEVIEW('sidebar-left-menu', '__')}
32
+</%def>
33
+
34
+<%def name="REQUIRED_DIALOGS()">
35
+    ${TIM.MODAL_DIALOG('user-edit-modal-dialog')}
36
+    ${TIM.MODAL_DIALOG('user-edit-password-modal-dialog')}
37
+</%def>
38
+
39
+<div class="container-fluid">
40
+    <div class="row-fluid">
41
+        <div>
42
+            <div class="row">
43
+                <div class="col-md-offset-3 col-sm-7">
44
+                    <div class="row t-spacer-above">
45
+##                        <div class="col-sm-6">
46
+##                            <div class="panel panel-default">
47
+##                              <div class="panel-heading">
48
+##                                <h3 class="panel-title"><i class="fa fa-eye-slash"></i> ${_('Unread content')}</h3>
49
+##                              </div>
50
+##                              <div class="panel-body">
51
+##                                Panel content
52
+##                              </div>
53
+##                            </div>
54
+##                        </div>
55
+
56
+                        <div class="col-sm-6">
57
+                            <div class="panel panel-default">
58
+                                <div class="panel-heading">
59
+                                    <h3 class="panel-title"><i class="fa fa-line-chart"></i> ${_('Recent activity')}</h3>
60
+                                </div>
61
+                                % if fake_api.last_actives.nb <= 0:
62
+                                    ${P.EMPTY_CONTENT(_('There\'s no activity yet.'))}
63
+                                % else:
64
+                                    <table class="table table-hover">
65
+                                        % for item in fake_api.last_actives.contents:
66
+                                            <tr>
67
+                                                <td>
68
+                                                    <i class="${item.type.icon} fa-fw ${item.type.color}"></i>
69
+                                                    <a href="${item.url}">${item.label}</a>
70
+                                                    <br/>
71
+                                                    <span class="t-less-visible">${item.workspace.label}</span>
72
+                                                </td>
73
+                                                <td title="${_('Last activity: {datetime}').format(datetime=item.last_activity.label)}">
74
+                                                    ${item.last_activity.delta}
75
+                                                </td>
76
+                                            </tr>
77
+                                        % endfor
78
+                                    </table>
79
+                                % endif
80
+                            </div>
81
+                        </div>
82
+
83
+##                        <div class="col-sm-6">
84
+##                            <div class="panel panel-default">
85
+##                                <div class="panel-heading">
86
+##                                    <h3 class="panel-title"><i class="fa fa-thumbs-down"></i> ${_('Still open after...')}</h3>
87
+##                                </div>
88
+##                                % if fake_api.oldest_opens.nb <= 0:
89
+##                                    ${P.EMPTY_CONTENT(_('Nothing to close.'))}
90
+##                                % else:
91
+##                                    <table class="table table-hover">
92
+##                                        % for item in fake_api.oldest_opens.contents:
93
+##                                            <tr>
94
+##                                                <td>
95
+##                                                    <i class="${item.type.icon} fa-fw ${item.type.color}"></i>
96
+##                                                    <a href="${item.url}">${item.label}</a>
97
+##                                                </td>
98
+##                                                <td title="${_('Last activity: {datetime}').format(datetime=item.last_activity.label)}">
99
+##                                                    ${item.last_activity.delta}
100
+##                                                </td>
101
+##                                            </tr>
102
+##                                        % endfor
103
+##                                    </table>
104
+##                                % endif
105
+##                            </div>
106
+##                        </div>
107
+
108
+
109
+##                        <div class="col-sm-6">
110
+##                            <div class="panel panel-default">
111
+##                                <div class="panel-heading">
112
+##                                    <h3 class="panel-title"><i class="fa fa-star"></i> ${_('Favorites')}</h3>
113
+##                                </div>
114
+##
115
+##                                last_active_contents
116
+##
117
+##                                    % if fake_api.favorites.nb <= 0:
118
+##                                        ${P.EMPTY_CONTENT(_('You did not set any favorite yet.'))}
119
+##                                    % else:
120
+##                                        <table class="table table-hover">
121
+##                                            % for item in fake_api.favorites.contents:
122
+##                                                <tr>
123
+##                                                    <td>
124
+##                                                        <i class="${item.type.icon} fa-fw ${item.type.color}"></i>
125
+##                                                        <a href="${item.url}">${item.label}</a>
126
+##                                                    </td>
127
+##                                                    <td class="text-right">
128
+##                                                        <i class="${item.status.icon} fa-fw ${item.status.css}" title="${item.status.label}"></i>
129
+##                                                    </td>
130
+##                                                </tr>
131
+##                                            % endfor
132
+##                                        </table>
133
+##                                    % endif
134
+####                                </div>
135
+##                            </div>
136
+##                        </div>
137
+                    </div>
138
+
139
+                    ## Workspace list and notifications
140
+                    <div class="row">
141
+                        <div class="col-sm-12">
142
+                            <div class="panel panel-default">
143
+                                <div class="panel-heading">
144
+                                    <h3 class="panel-title"><i class="fa fa-bank"></i> ${_('Your workspaces')}</h3>
145
+                                </div>
146
+                                <div class="panel-body">
147
+
148
+                                    % if len(fake_api.current_user.roles)<=0:
149
+                                        ${P.EMPTY_CONTENT(_('I\'m not member of any workspace.'))}
150
+                                    % else:
151
+                                        <table class="table">
152
+                                            <thead>
153
+                                                <tr>
154
+                                                    <th>${_('Workspace')}</th>
155
+                                                    <th>${_('Role')}</th>
156
+                                                    <th>${_('Email Notifications')}</th>
157
+                                                </tr>
158
+                                            </thead>
159
+                                            % for role in fake_api.current_user.roles:
160
+                                                ${TABLE_ROW.USER_ROLE_IN_WORKSPACE(role, show_id=False, enable_link='/user/me/workspaces/{workspace}/enable_notifications?next_url=/home', disable_link='/user/me/workspaces/{workspace}/disable_notifications?next_url=/home')}
161
+                                            % endfor
162
+                                        </table>
163
+                                    % endif
164
+                                </div>
165
+                            </div>
166
+                        </div>
167
+                    </div>
168
+                </div>
169
+            </div>
170
+        </div>
171
+    </div>
172
+</div>
173
+

+ 0 - 1
tracim/tracim/templates/master_anonymous.mak Visa fil

82
                     <span class="icon-bar"></span>
82
                     <span class="icon-bar"></span>
83
                 </button>
83
                 </button>
84
                 <a class="navbar-brand" href="${tg.url('/')}">
84
                 <a class="navbar-brand" href="${tg.url('/')}">
85
-##                  <img src="${tg.url('/assets/img/tracim.png')}" class="pull-left" style="height: 48px; margin: -13px 0.5em 0 -13px;"/>
86
                   <img src="${tg.url('/assets/img/logo.png')}" class="pull-left" style="margin: -13px 0.5em 0 -13px;"/>
85
                   <img src="${tg.url('/assets/img/logo.png')}" class="pull-left" style="margin: -13px 0.5em 0 -13px;"/>
87
                 </a>
86
                 </a>
88
             </div>
87
             </div>

+ 53 - 44
tracim/tracim/templates/master_authenticated.mak Visa fil

2
 <!DOCTYPE html>
2
 <!DOCTYPE html>
3
 <html>
3
 <html>
4
     <head>
4
     <head>
5
-	    ${self.meta()}
5
+        ${self.meta()}
6
         <meta charset="utf-8">
6
         <meta charset="utf-8">
7
-	    <title>${self.title()}</title>
7
+        <title>${self.title()}</title>
8
         <meta http-equiv="X-UA-Compatible" content="IE=edge">
8
         <meta http-equiv="X-UA-Compatible" content="IE=edge">
9
         <meta name="viewport" content="width=device-width, initial-scale=1">
9
         <meta name="viewport" content="width=device-width, initial-scale=1">
10
         <meta name="description" content="">
10
         <meta name="description" content="">
67
 
67
 
68
 <%def name="main_menu()">
68
 <%def name="main_menu()">
69
     <div class="navbar navbar-fixed-top" role="navigation">
69
     <div class="navbar navbar-fixed-top" role="navigation">
70
+        ${TIM.FLASH_MSG('col-sm-7 col-sm-offset-3')}
71
+##
72
+##         <div class="row" id="flashgordon">
73
+##             <div class="col-sm-7 col-sm-offset-3" style="z-index: 10001; padding: 0; position: absolute; top: 0;">
74
+##                 <div class="alert alert-info" style="margin-top: 1em; ">
75
+##                     <button type="button" class="close" data-dismiss="alert">×</button>
76
+##                     <div id="flash">
77
+##                         <img src="/assets/icons/32x32/status/flash-ok.png">
78
+##                         Statut de Fichier mis(e) à jour
79
+##                     </div>
80
+##                 </div>
81
+##
82
+##                 <script>
83
+##                     window.setTimeout(function() {
84
+##                         $("#flashgordon").fadeTo(5000, 0.5);
85
+##                     }, 5000);
86
+##                 </script>
87
+##             </div>
88
+##         </div>
89
+
90
+
91
+
70
         <div class="container-fluid">
92
         <div class="container-fluid">
71
             <div class="navbar-header">
93
             <div class="navbar-header">
72
                 <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
94
                 <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
80
                   <img src="${tg.url('/assets/img/logo.png')}" class="pull-left" style="height: 48px; margin: -13px 0.5em 0 -13px;"/>
102
                   <img src="${tg.url('/assets/img/logo.png')}" class="pull-left" style="height: 48px; margin: -13px 0.5em 0 -13px;"/>
81
                 </a>
103
                 </a>
82
             </div>
104
             </div>
105
+
83
             <div class="navbar-collapse collapse">
106
             <div class="navbar-collapse collapse">
84
                 % if request.identity:
107
                 % if request.identity:
85
                     <ul class="nav navbar-nav navbar-left">
108
                     <ul class="nav navbar-nav navbar-left">
86
-                        <li><a href="${tg.url('/dashboard')}">${TIM.ICO(16, 'places/user-desktop')} ${_('Dashboard')}</a></li>
87
-                        <li><a href="${tg.url('/workspaces')}">${TIM.ICO(16, 'places/folder-remote')} ${_('Workspace')}</a></li>
109
+                        <li class="active"><a href="${tg.url('/home')}">${TIM.FA('fa-home fa-lg')} ${_('My Home')}</a></li>
110
+                    </ul>
111
+                % endif
112
+
113
+                <ul class="nav navbar-nav navbar-right">
114
+
115
+                    % if request.identity:
116
+
117
+                        <form id="search-form" class="navbar-form navbar-left" role="search" action="${tg.url('/search?')}">
118
+                            <div class="form-group">
119
+                                <input type="text" class="form-control" placeholder="${_('Search for...')}" name="keywords" value="${','.join(search.keywords) if search else ''}">
120
+                                <i class="fa fa-search t-less-visible" style="margin-left: -2em;" onclick="$('#search-form').submit()"></i>
121
+                            </div>
122
+                            ## <button type="submit" class="btn btn-default">${_('Search')}</button>
123
+                        </form>
88
 
124
 
89
-                        % if fake_api.current_user.profile.id>=2:
125
+                        % if fake_api.current_user.profile.id>=8: #2:
90
                             <li class="dropdown">
126
                             <li class="dropdown">
91
-                              <a href="#" class="dropdown-toggle" data-toggle="dropdown">${TIM.ICO(16, 'categories/preferences-system')} ${_('Admin')} <b class="caret"></b></a>
127
+                              <a href="#" class="dropdown-toggle" data-toggle="dropdown">${TIM.FA('fa-lg fa-cogs')} ${_('Admin')} <b class="caret"></b></a>
92
                               <ul class="dropdown-menu">
128
                               <ul class="dropdown-menu">
93
-                                <li><a href="${tg.url('/admin/users')}">${TIM.ICO(16, 'apps/system-users')} ${_('Users')}</a></li>
94
-                                <li><a href="${tg.url('/admin/workspaces')}">${TIM.ICO(16, 'places/folder-remote')} ${_('Workspaces')}</a></li>
129
+                                <li><a href="${tg.url('/admin/users')}">${TIM.FA('fa-users tracim-less-visible')} ${_('Users')}</a></li>
130
+                                <li><a href="${tg.url('/admin/workspaces')}">${TIM.FA('fa-bank tracim-less-visible')} ${_('Workspaces')}</a></li>
95
 ## TODO - D.A. - 2014-10-20 - Restore global configuration screen
131
 ## TODO - D.A. - 2014-10-20 - Restore global configuration screen
96
 ##                                <li class="divider" role="presentation"></li>
132
 ##                                <li class="divider" role="presentation"></li>
97
 ##                                <li><a href="${tg.url('/admin/configuration')}">${TIM.ICO(16, 'categories/preferences-system')} ${_('Global configuration')}</a></li>
133
 ##                                <li><a href="${tg.url('/admin/configuration')}">${TIM.ICO(16, 'categories/preferences-system')} ${_('Global configuration')}</a></li>
99
                             </li>
135
                             </li>
100
                         % endif
136
                         % endif
101
 
137
 
102
-                        % if h.is_debug_mode():
138
+                        % if False and h.is_debug_mode():
103
                             <li class="dropdown text-danger" >
139
                             <li class="dropdown text-danger" >
104
-                                <a href="#" class="dropdown-toggle" data-toggle="dropdown">${TIM.ICO(16, 'status/dialog-warning')} Debug <b class="caret"></b></a>
140
+                                <a href="#" class="dropdown-toggle" data-toggle="dropdown">${TIM.FA('fa-warning t-orange')} Debug <b class="caret"></b></a>
105
                                 <ul class="dropdown-menu">
141
                                 <ul class="dropdown-menu">
106
                                     <li><a class="text-danger" href=""><strong>${_('you MUST desactivate debug in production')}</strong></a></li>
142
                                     <li><a class="text-danger" href=""><strong>${_('you MUST desactivate debug in production')}</strong></a></li>
107
                                     <li class="divider" role="presentation"></li>
143
                                     <li class="divider" role="presentation"></li>
108
-                                    <li><a href="${tg.url('/debug/environ')}">${TIM.ICO(16, 'apps/internet-web-browser')} request.environ</a></li>
109
-                                    <li><a href="${tg.url('/debug/identity')}">${TIM.ICO(16, 'actions/contact-new')} request.identity</a></li>
144
+                                    <li><a href="${tg.url('/debug/environ')}">${TIM.FA('fa-globe fa-fw t-less-visible')} request.environ</a></li>
145
+                                    <li><a href="${tg.url('/debug/identity')}">${TIM.FA('fa-user fa-fw t-less-visible')} request.identity</a></li>
110
                                     <li class="divider" role="presentation"></li>
146
                                     <li class="divider" role="presentation"></li>
111
-                                    <li><a href="${tg.url('/debug/iconset-fa')}">${TIM.ICO(16, 'mimetypes/image-x-generic')} Icon set - Font Awesome</a></li>
112
-                                    <li><a href="${tg.url('/debug/iconset-tango')}">${TIM.ICO(16, 'mimetypes/image-x-generic')} Icon set - Tango Icons</a></li>
147
+                                    <li><a href="${tg.url('/debug/iconset-fa')}">${TIM.FA('fa-file-image-o t-less-visible')} Icon set - Font Awesome</a></li>
148
+                                    <li><a href="${tg.url('/debug/iconset-tango')}">${TIM.FA('fa-file-image-o t-less-visible')} Icon set - Tango Icons</a></li>
113
                                 </ul>
149
                                 </ul>
114
                             </li>
150
                             </li>
115
                         % endif
151
                         % endif
116
-                        
117
-                        <form class="navbar-form navbar-left" role="search" action="${tg.url('/search?')}">
118
-                            <div class="form-group">
119
-                                <input type="text" class="form-control" placeholder="${_('Search for...')}" name="keywords" value="${','.join(search.keywords) if search else ''}">
120
-                            </div>
121
-                            <button type="submit" class="btn btn-default">${_('Search')}</button>
122
-                        </form>
123
-                    </ul>
124
-                % endif
125
-
126
-                <ul class="nav navbar-nav navbar-right">
127
-
128
-                    % if request.identity:
129
-## TODO - D.A. - 2014-10-19 - RESTORE SEARCH FEATURE
130
-##                        <li>
131
-##                            <form class="navbar-form navbar-right" action="${tg.url('/search')}">
132
-##                                <input type="text" name="keywords" class="form-control" placeholder="${_('Search...')}" value="${context.get('search_string', '')}">
133
-##                                <button type="submit" class="btn btn-default">
134
-##                                    ${TIM.ICO(16, 'actions/system-search')}
135
-##                                </button>
136
-##                            </form>
137
-##                        </li>
138
                         <li class="dropdown">
152
                         <li class="dropdown">
139
                             <a href="#" class="dropdown-toggle" data-toggle="dropdown">
153
                             <a href="#" class="dropdown-toggle" data-toggle="dropdown">
140
-                              ${TIM.ICO(16, 'categories/applications-system')} ${fake_api.current_user.name}
154
+                                ${TIM.FA('fa-lg fa-user')} ${fake_api.current_user.name}
155
+
141
                             </a>
156
                             </a>
142
                             <ul class="dropdown-menu pull-right">
157
                             <ul class="dropdown-menu pull-right">
143
                                 <li>
158
                                 <li>
144
-                                  <a href="${tg.url('/user/me')}">${TIM.ICO(16, 'actions/contact-new')|n} ${_('My account')}</a>
145
-                                </li>
146
-                                <li class="divider" role="presentation"></li>
147
-                                <li>
148
-                                  <a href="${tg.url('/logout_handler')}">
149
-                                  ${TIM.ICO(16, 'status/status-locked')|n} ${_('Logout')}</a>
159
+                                  <a href="${tg.url('/logout_handler')}">${TIM.FA('fa-sign-out fa-fw t-orange')} ${_('Logout')}</a>
150
                                 </li>
160
                                 </li>
151
                             </ul>
161
                             </ul>
152
                         </li>
162
                         </li>
171
         </div>
181
         </div>
172
     </div>
182
     </div>
173
 </%def>
183
 </%def>
174
-
175
 </html>
184
 </html>

+ 98 - 0
tracim/tracim/templates/master_authenticated_left_treeview.mak Visa fil

1
+<%inherit file="local:templates.master_authenticated"/>
2
+<%namespace name="TIM" file="tracim.templates.pod"/>
3
+<%namespace name="LEFT_MENU" file="tracim.templates.widgets.left_menu"/>
4
+
5
+<%def name="SIDEBAR_LEFT_CONTENT()">
6
+    ## This is the default left sidebar implementation
7
+    % if fake_api.current_user.profile.id>2:
8
+        ${LEFT_MENU.ADMIN('')}
9
+    % endif
10
+    ${LEFT_MENU.TREEVIEW('sidebar-left-menu', '__')}
11
+</%def>
12
+
13
+<%def name="SIDEBAR_RIGHT_CONTENT()">
14
+    ## This is the default right sidebar implementation
15
+    <div id="sidebar-right" class="col-sm-1 col-md-1 col-sm-offset-11 sidebar">
16
+        <div class="btn-group btn-group-vertical">
17
+        </div>
18
+        <p></p>
19
+    </div> <!-- # End of side bar right -->
20
+</%def>
21
+<%def name="REQUIRED_DIALOGS()"></%def>
22
+<%def name="FOOTER_CONTENT_LIKE_SCRIPTS_AND_CSS()"></%def>
23
+
24
+<%def name="content_wrapper()">
25
+    <div class="container-fluid">
26
+        <div class="row-fluid">
27
+        
28
+            ## SIDEBAR LEFT
29
+            <div id="sidebar-left" class="fixed-width-sidebar col-sm-3 sidebar" >
30
+                <div class="btn-group" style="position: absolute; right: 2px; top: 4px; ">
31
+                    <button id="toggle-left-sidebar-width" type="button" class="btn btn-link"><i class="fa fa-angle-double-right"></i></button>
32
+                </div>
33
+                ${self.SIDEBAR_LEFT_CONTENT()}
34
+            </div>
35
+            ## SIDEBAR LEFT [END]
36
+
37
+            ## SIDEBAR RIGHT
38
+            <div id="sidebar-right" class="col-sm-1 col-md-1 col-sm-offset-11 sidebar">
39
+                ${self.SIDEBAR_RIGHT_CONTENT()}
40
+            </div> <!-- # End of side bar right -->
41
+            ## SIDEBAR RIGHT [END]
42
+
43
+            <div>
44
+                ${self.TITLE_ROW()}
45
+                ${TIM.FLASH_MSG('col-sm-8 col-sm-offset-3')}
46
+                ${self.body()}
47
+            </div>
48
+        </div>
49
+    </div>
50
+    ${self.REQUIRED_DIALOGS()}
51
+    
52
+    ###########################################
53
+    ##
54
+    ## GENERIC STUFF LIKE SCRIPTS
55
+    ##
56
+    ###########################################
57
+    <script src="${tg.url('/assets/js/jquery.min.js')}"></script>
58
+    <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
59
+    <script src="${tg.url('/assets/js/ie10-viewport-bug-workaround.js')}"></script>
60
+    <script>
61
+        $(function () {
62
+            $('#toggle-left-sidebar-width').click( function() {
63
+              sidebar = $('#sidebar-left');
64
+              buttonIcon = $('> i', this);
65
+              if (sidebar.hasClass('fixed-width-sidebar')) {
66
+                sidebar.removeClass('fixed-width-sidebar')
67
+                sidebar.removeClass('col-sm-3');
68
+                
69
+                buttonIcon.removeClass('fa-angle-double-right');
70
+                buttonIcon.addClass('fa-angle-double-left');
71
+              } else {
72
+                sidebar.addClass('fixed-width-sidebar')
73
+                sidebar.addClass('col-sm-3');
74
+                buttonIcon.removeClass('fa-angle-double-left');
75
+                buttonIcon.addClass('fa-angle-double-right');
76
+              }
77
+            });
78
+
79
+            $('#current-page-breadcrumb-toggle-button').click( function() {
80
+              $('#current-page-breadcrumb').toggle();
81
+            });
82
+        });
83
+    </script>
84
+    <!-- TinyMCE ================================================== -->
85
+    <script src="${tg.url('/assets/tinymce/js/tinymce/tinymce.min.js')}"></script>
86
+    ${TIM.TINYMCE_INIT_SCRIPT('.pod-rich-textarea')}
87
+
88
+    <!-- JSTree ================================================== -->
89
+    <link rel="stylesheet" href="${tg.url('/assets/jstree/themes/default/style.min.css')}" />
90
+    <link rel="stylesheet" href="${tg.url('/assets/jstree/themes/tracim/style.css')}" />
91
+    <script src="${tg.url('/assets/jstree/jstree.min.js')}"></script>
92
+
93
+
94
+##    <link rel="stylesheet" href="${tg.url('/assets/tablesorter/themes/blue/style.css')}" />
95
+    <script src="${tg.url('/assets/tablesorter/jquery.tablesorter.min.js')}"></script>
96
+
97
+</%def>
98
+

+ 15 - 14
tracim/tracim/templates/master_authenticated_left_treeview_right_toolbar.mak Visa fil

1
 <%inherit file="local:templates.master_authenticated"/>
1
 <%inherit file="local:templates.master_authenticated"/>
2
 <%namespace name="TIM" file="tracim.templates.pod"/>
2
 <%namespace name="TIM" file="tracim.templates.pod"/>
3
 
3
 
4
+<%def name="TITLE_ROW()"></%def>
4
 <%def name="SIDEBAR_LEFT_CONTENT()"></%def>
5
 <%def name="SIDEBAR_LEFT_CONTENT()"></%def>
5
 <%def name="SIDEBAR_RIGHT_CONTENT()"></%def>
6
 <%def name="SIDEBAR_RIGHT_CONTENT()"></%def>
6
 <%def name="REQUIRED_DIALOGS()"></%def>
7
 <%def name="REQUIRED_DIALOGS()"></%def>
11
         <div class="row-fluid">
12
         <div class="row-fluid">
12
         
13
         
13
             ## SIDEBAR LEFT
14
             ## SIDEBAR LEFT
14
-            <div id="sidebar-left" class="fixed-width-sidebar col-sm-2 sidebar" >
15
+            <div id="sidebar-left" class="fixed-width-sidebar col-sm-3 sidebar" >
15
                 <div class="btn-group" style="position: absolute; right: 2px; top: 4px; ">
16
                 <div class="btn-group" style="position: absolute; right: 2px; top: 4px; ">
16
                     <button id="toggle-left-sidebar-width" type="button" class="btn btn-link"><i class="fa fa-angle-double-right"></i></button>
17
                     <button id="toggle-left-sidebar-width" type="button" class="btn btn-link"><i class="fa fa-angle-double-right"></i></button>
17
                 </div>
18
                 </div>
20
             ## SIDEBAR LEFT [END]
21
             ## SIDEBAR LEFT [END]
21
 
22
 
22
             ## SIDEBAR RIGHT
23
             ## SIDEBAR RIGHT
23
-            <div id="sidebar-right" class="col-sm-1 col-md-1 col-sm-offset-11 sidebar" style="background-color: #FFF;">
24
+            <div id="sidebar-right" class="col-sm-2 col-md-2 col-sm-offset-10 sidebar">
24
                 ${self.SIDEBAR_RIGHT_CONTENT()}
25
                 ${self.SIDEBAR_RIGHT_CONTENT()}
25
             </div> <!-- # End of side bar right -->
26
             </div> <!-- # End of side bar right -->
26
             ## SIDEBAR RIGHT [END]
27
             ## SIDEBAR RIGHT [END]
27
             
28
             
28
-        <div>
29
-            ${TIM.FLASH_MSG('col-sm-9 col-sm-offset-2')}
30
-            
31
-            <div class="row">
32
-                <div class="col-sm-9 col-sm-offset-2 main">
33
-                    ## BODY
34
-                    ${self.body()}
35
-                    ## BODY [END]
36
-                </div>
29
+            <div>
30
+                ${self.TITLE_ROW()}
31
+                ${self.body()}
37
             </div>
32
             </div>
38
         </div>
33
         </div>
39
     </div>
34
     </div>
54
               buttonIcon = $('> i', this);
49
               buttonIcon = $('> i', this);
55
               if (sidebar.hasClass('fixed-width-sidebar')) {
50
               if (sidebar.hasClass('fixed-width-sidebar')) {
56
                 sidebar.removeClass('fixed-width-sidebar')
51
                 sidebar.removeClass('fixed-width-sidebar')
57
-                sidebar.removeClass('col-sm-2');
52
+                sidebar.removeClass('col-sm-3');
58
                 
53
                 
59
                 buttonIcon.removeClass('fa-angle-double-right');
54
                 buttonIcon.removeClass('fa-angle-double-right');
60
                 buttonIcon.addClass('fa-angle-double-left');
55
                 buttonIcon.addClass('fa-angle-double-left');
61
               } else {
56
               } else {
62
                 sidebar.addClass('fixed-width-sidebar')
57
                 sidebar.addClass('fixed-width-sidebar')
63
-                sidebar.addClass('col-sm-2');
58
+                sidebar.addClass('col-sm-3');
64
                 buttonIcon.removeClass('fa-angle-double-left');
59
                 buttonIcon.removeClass('fa-angle-double-left');
65
                 buttonIcon.addClass('fa-angle-double-right');
60
                 buttonIcon.addClass('fa-angle-double-right');
66
               }
61
               }
75
     <script src="${tg.url('/assets/tinymce/js/tinymce/tinymce.min.js')}"></script>
70
     <script src="${tg.url('/assets/tinymce/js/tinymce/tinymce.min.js')}"></script>
76
     ${TIM.TINYMCE_INIT_SCRIPT('.pod-rich-textarea')}
71
     ${TIM.TINYMCE_INIT_SCRIPT('.pod-rich-textarea')}
77
 
72
 
78
-
79
     <!-- JSTree ================================================== -->
73
     <!-- JSTree ================================================== -->
80
     <link rel="stylesheet" href="${tg.url('/assets/jstree/themes/default/style.min.css')}" />
74
     <link rel="stylesheet" href="${tg.url('/assets/jstree/themes/default/style.min.css')}" />
75
+    <link rel="stylesheet" href="${tg.url('/assets/jstree/themes/tracim/style.css')}" />
81
     <script src="${tg.url('/assets/jstree/jstree.min.js')}"></script>
76
     <script src="${tg.url('/assets/jstree/jstree.min.js')}"></script>
82
 
77
 
78
+##     <link rel="stylesheet" href="${tg.url('/assets/tablesorter/themes/tracim/style.css')}"/>
79
+##    <script src="${tg.url('/assets/tablesorter/jquery.tablesorter.min.js')}"></script>
80
+
81
+
82
+    <link rel="stylesheet" href="//cdn.datatables.net/1.10.7/css/jquery.dataTables.min.css"/>
83
+    <script src="//cdn.datatables.net/1.10.7/js/jquery.dataTables.min.js"></script>
83
 </%def>
84
 </%def>
84
 
85
 

+ 0 - 0
tracim/tracim/templates/page/__init__.py Visa fil


Vissa filer visades inte eftersom för många filer har ändrats