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

+ 34 - 11
tracim/tracim/controllers/__init__.py View File

@@ -115,6 +115,9 @@ class TIMRestController(RestController, BaseController):
115 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 121
     def _before(self, *args, **kw):
119 122
         """
120 123
         Instantiate the current workspace in tg.tmpl_context
@@ -135,6 +138,25 @@ class TIMRestControllerWithBreadcrumb(TIMRestController):
135 138
         """
136 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 161
 class TIMWorkspaceContentRestController(TIMRestControllerWithBreadcrumb):
140 162
     """
@@ -197,17 +219,19 @@ class TIMWorkspaceContentRestController(TIMRestControllerWithBreadcrumb):
197 219
         """
198 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 236
     @tg.require(current_user_is_contributor())
213 237
     @tg.expose()
@@ -220,7 +244,7 @@ class TIMWorkspaceContentRestController(TIMRestControllerWithBreadcrumb):
220 244
         """
221 245
 
222 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 249
         item_id = int(item_id)
226 250
         user = tmpl_context.current_user
@@ -232,7 +256,6 @@ class TIMWorkspaceContentRestController(TIMRestControllerWithBreadcrumb):
232 256
         dictified_item = Context(self._get_one_context).toDict(item, 'item')
233 257
         return DictLikeClass(result = dictified_item)
234 258
 
235
-
236 259
     @tg.require(current_user_is_contributor())
237 260
     @tg.expose()
238 261
     def put(self, item_id, label='',content=''):

+ 25 - 24
tracim/tracim/controllers/admin/user.py View File

@@ -181,7 +181,7 @@ class UserPasswordAdminRestController(TIMRestController):
181 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 185
     def edit(self):
186 186
         current_user = tmpl_context.current_user
187 187
         api = UserApi(current_user)
@@ -189,32 +189,27 @@ class UserPasswordAdminRestController(TIMRestController):
189 189
         return DictLikeClass(result = dictified_user)
190 190
 
191 191
     @tg.expose()
192
-    def put(self, current_password, new_password1, new_password2):
192
+    def put(self, new_password1, new_password2, next_url=''):
193 193
         # FIXME - Manage
194 194
         current_user = tmpl_context.current_user
195 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 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 204
         if new_password1!=new_password2:
210 205
             tg.flash(_('New passwords do not match.'), CST.STATUS_ERROR)
211
-            tg.redirect(redirect_url)
206
+            tg.redirect(next_url)
212 207
 
213 208
         user.password = new_password1
214 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 215
 class UserRestController(TIMRestController):
@@ -232,7 +227,7 @@ class UserRestController(TIMRestController):
232 227
 
233 228
 
234 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 231
     def get_all(self, *args, **kw):
237 232
         current_user = tmpl_context.current_user
238 233
         api = UserApi(current_user)
@@ -285,7 +280,7 @@ class UserRestController(TIMRestController):
285 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 284
     def get_one(self, user_id):
290 285
         current_user = tmpl_context.current_user
291 286
         api = UserApi(current_user )
@@ -302,7 +297,7 @@ class UserRestController(TIMRestController):
302 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 301
     def edit(self, id):
307 302
         current_user = tmpl_context.current_user
308 303
         api = UserApi(current_user)
@@ -313,20 +308,22 @@ class UserRestController(TIMRestController):
313 308
         return DictLikeClass(result = dictified_user)
314 309
 
315 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 313
         api = UserApi(tmpl_context.current_user)
319 314
 
320 315
         user = api.get_one(int(user_id))
321 316
         api.update(user, name, email, True)
322 317
 
323 318
         tg.flash(_('User {} updated.').format(user.get_display_name()), CST.STATUS_OK)
319
+        if next_url:
320
+            tg.redirect(next_url)
324 321
         tg.redirect(self.url())
325
-        return
322
+
326 323
 
327 324
     @tg.require(predicates.in_group(Group.TIM_ADMIN_GROUPNAME))
328 325
     @tg.expose()
329
-    def enable(self, id):
326
+    def enable(self, id, next_url=None):
330 327
         current_user = tmpl_context.current_user
331 328
         api = UserApi(current_user)
332 329
 
@@ -334,12 +331,14 @@ class UserRestController(TIMRestController):
334 331
         user.is_active = True
335 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 337
         tg.redirect(self.url())
339 338
 
340 339
     @tg.require(predicates.in_group(Group.TIM_ADMIN_GROUPNAME))
341 340
     @tg.expose()
342
-    def disable(self, id):
341
+    def disable(self, id, next_url=None):
343 342
         id = int(id)
344 343
         current_user = tmpl_context.current_user
345 344
         api = UserApi(current_user)
@@ -350,8 +349,10 @@ class UserRestController(TIMRestController):
350 349
             user = api.get_one(id)
351 350
             user.is_active = False
352 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 356
         tg.redirect(self.url())
356 357
 
357 358
 

+ 4 - 5
tracim/tracim/controllers/admin/workspace.py View File

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

+ 81 - 50
tracim/tracim/controllers/content.py View File

@@ -30,6 +30,7 @@ from tracim.model.serializers import Context, CTX, DictLikeClass
30 30
 from tracim.model.data import ActionDescription
31 31
 from tracim.model.data import Content
32 32
 from tracim.model.data import ContentType
33
+from tracim.model.data import UserRoleInWorkspace
33 34
 from tracim.model.data import Workspace
34 35
 
35 36
 class UserWorkspaceFolderThreadCommentRestController(TIMRestController):
@@ -136,6 +137,9 @@ class UserWorkspaceFolderFileRestController(TIMWorkspaceContentRestController):
136 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 143
     @property
140 144
     def _std_url(self):
141 145
         return tg.url('/workspaces/{}/folders/{}/files/{}')
@@ -160,13 +164,8 @@ class UserWorkspaceFolderFileRestController(TIMWorkspaceContentRestController):
160 164
     def _get_all_context(self) -> str:
161 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 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 169
     def get_one(self, file_id, revision_id=None):
171 170
         file_id = int(file_id)
172 171
         user = tmpl_context.current_user
@@ -324,6 +323,9 @@ class UserWorkspaceFolderPageRestController(TIMWorkspaceContentRestController):
324 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 329
     @property
328 330
     def _std_url(self):
329 331
         return tg.url('/workspaces/{}/folders/{}/pages/{}')
@@ -348,13 +350,8 @@ class UserWorkspaceFolderPageRestController(TIMWorkspaceContentRestController):
348 350
     def _get_all_context(self) -> str:
349 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 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 355
     def get_one(self, page_id, revision_id=None):
359 356
         page_id = int(page_id)
360 357
         user = tmpl_context.current_user
@@ -442,30 +439,29 @@ class UserWorkspaceFolderThreadRestController(TIMWorkspaceContentRestController)
442 439
     """
443 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 448
     def _before(self, *args, **kw):
449 449
         TIMRestPathContextSetup.current_user()
450 450
         TIMRestPathContextSetup.current_workspace()
451 451
         TIMRestPathContextSetup.current_folder()
452 452
 
453
-
454 453
     @property
455 454
     def _std_url(self):
456 455
         return tg.url('/workspaces/{}/folders/{}/threads/{}')
457 456
 
458
-
459 457
     @property
460 458
     def _err_url(self):
461 459
         return self._std_url
462 460
 
463
-
464 461
     @property
465 462
     def _parent_url(self):
466 463
         return tg.url('/workspaces/{}/folders/{}')
467 464
 
468
-
469 465
     @property
470 466
     def _item_type(self):
471 467
         return ContentType.Thread
@@ -480,20 +476,13 @@ class UserWorkspaceFolderThreadRestController(TIMWorkspaceContentRestController)
480 476
     def _get_one_context(self) -> str:
481 477
         return CTX.THREAD
482 478
 
483
-
484 479
     @property
485 480
     def _get_all_context(self) -> str:
486 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 483
     @tg.require(current_user_is_contributor())
495 484
     @tg.expose()
496
-    def post(self, label='', content=''):
485
+    def post(self, label='', content='', parent_id=None):
497 486
         """
498 487
         Creates a new thread. Actually, on POST, the content will be included in a user comment instead of being the thread description
499 488
         :param label:
@@ -520,7 +509,7 @@ class UserWorkspaceFolderThreadRestController(TIMWorkspaceContentRestController)
520 509
 
521 510
 
522 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 513
     def get_one(self, thread_id):
525 514
         thread_id = int(thread_id)
526 515
         user = tmpl_context.current_user
@@ -556,7 +545,7 @@ class ItemLocationController(TIMWorkspaceContentRestController, BaseController):
556 545
 
557 546
 
558 547
     @tg.require(current_user_is_content_manager())
559
-    @tg.expose('tracim.templates.item_location_edit')
548
+    @tg.expose('tracim.templates.folder.move')
560 549
     def edit(self, item_id):
561 550
         """
562 551
         Show the edit form (do not really edit the data)
@@ -577,17 +566,12 @@ class ItemLocationController(TIMWorkspaceContentRestController, BaseController):
577 566
         dictified_item = Context(CTX.DEFAULT).toDict(item, 'item')
578 567
         return DictLikeClass(result = dictified_item, fake_api=fake_api)
579 568
 
580
-
581
-
582
-
583
-
584
-
585 569
     @tg.require(current_user_is_content_manager())
586 570
     @tg.expose()
587 571
     def put(self, item_id, folder_id='0'):
588 572
         """
589 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 575
         :return:
592 576
         """
593 577
         # TODO - SECURE THIS
@@ -595,21 +579,57 @@ class ItemLocationController(TIMWorkspaceContentRestController, BaseController):
595 579
         item_id = int(item_id)
596 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 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 629
 class UserWorkspaceFolderRestController(TIMRestControllerWithBreadcrumb):
612 630
 
631
+    TEMPLATE_NEW = 'mako:tracim.templates.folder.new'
632
+
613 633
     location = ItemLocationController()
614 634
 
615 635
     files = UserWorkspaceFolderFileRestController()
@@ -622,7 +642,7 @@ class UserWorkspaceFolderRestController(TIMRestControllerWithBreadcrumb):
622 642
 
623 643
 
624 644
     @tg.require(current_user_is_content_manager())
625
-    @tg.expose('tracim.templates.folder_edit')
645
+    @tg.expose('tracim.templates.folder.edit')
626 646
     def edit(self, folder_id):
627 647
         """
628 648
         Show the edit form (do not really edit the data)
@@ -643,7 +663,7 @@ class UserWorkspaceFolderRestController(TIMRestControllerWithBreadcrumb):
643 663
 
644 664
 
645 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 667
     def get_one(self, folder_id):
648 668
         folder_id = int(folder_id)
649 669
         user = tmpl_context.current_user
@@ -663,15 +683,24 @@ class UserWorkspaceFolderRestController(TIMRestControllerWithBreadcrumb):
663 683
         fake_api_threads = self.threads.get_all_fake(workspace, folder).result
664 684
 
665 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 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 705
         dictified_folder = Context(CTX.FOLDER).toDict(folder, 'folder')
677 706
         return DictLikeClass(result = dictified_folder, fake_api=fake_api)
@@ -759,7 +788,9 @@ class UserWorkspaceFolderRestController(TIMRestControllerWithBreadcrumb):
759 788
                 file = True if can_contain_files=='on' else False,
760 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 794
             api.set_allowed_content(folder, subcontent)
764 795
             api.save(folder)
765 796
 

+ 36 - 6
tracim/tracim/controllers/root.py View File

@@ -15,6 +15,7 @@ from tg.i18n import ugettext as _
15 15
 from tracim.lib import CST
16 16
 from tracim.lib.base import logger
17 17
 from tracim.lib.user import UserStaticApi
18
+from tracim.lib.content import ContentApi
18 19
 
19 20
 from tracim.controllers import StandardController
20 21
 from tracim.controllers.admin import AdminController
@@ -24,6 +25,7 @@ from tracim.controllers.help import HelpController
24 25
 from tracim.controllers.user import UserRestController
25 26
 from tracim.controllers.workspace import UserWorkspaceRestController
26 27
 
28
+from tracim.model.data import ContentType
27 29
 from tracim.model.serializers import DictLikeClass
28 30
 from tracim.model.serializers import CTX
29 31
 from tracim.model.serializers import Context
@@ -65,7 +67,7 @@ class RootController(StandardController):
65 67
                 logger.info(self, 'Will redirect to {}'.format(came_from))
66 68
                 redirect(url(came_from))
67 69
             else:
68
-                redirect(self.url(None, self.dashboard.__name__))
70
+                redirect(self.url(None, self.home.__name__))
69 71
 
70 72
         login_counter = request.environ.get('repoze.who.logins', 0)
71 73
         if login_counter > 0:
@@ -90,7 +92,7 @@ class RootController(StandardController):
90 92
 
91 93
 
92 94
     @expose()
93
-    def post_login(self, came_from=lurl('/dashboard')):
95
+    def post_login(self, came_from=lurl('/home')):
94 96
         """
95 97
         Redirect the user to the initially requested page on successful
96 98
         authentication or redirect her back to the login page if login failed.
@@ -115,17 +117,45 @@ class RootController(StandardController):
115 117
         
116 118
 
117 119
     @require(predicates.not_anonymous())
118
-    @expose('tracim.templates.dashboard')
119
-    def dashboard(self):
120
+    @expose('tracim.templates.home')
121
+    def home(self):
120 122
         user = tmpl_context.current_user
121 123
 
122 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 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 157
     @require(predicates.not_anonymous())
128
-    @expose('tracim.templates.search')
158
+    @expose('tracim.templates.search.display')
129 159
     def search(self, keywords = ''):
130 160
         from tracim.lib.content import ContentApi
131 161
 

+ 17 - 9
tracim/tracim/controllers/user.py View File

@@ -45,23 +45,29 @@ class UserWorkspaceRestController(TIMRestController):
45 45
         user = tmpl_context.current_user
46 46
 
47 47
     @tg.expose()
48
-    def enable_notifications(self, workspace_id):
48
+    def enable_notifications(self, workspace_id, next_url=None):
49 49
         workspace_id = int(workspace_id)
50 50
         api = WorkspaceApi(tg.tmpl_context.current_user)
51 51
 
52 52
         workspace = api.get_one(workspace_id)
53 53
         api.enable_notifications(tg.tmpl_context.current_user, workspace)
54 54
         tg.flash(_('Notification enabled for workspace {}').format(workspace.label))
55
+
56
+        if next_url:
57
+            tg.redirect(tg.url(next_url))
55 58
         tg.redirect(self.parent_controller.url(None, 'me'))
56 59
 
57 60
     @tg.expose()
58
-    def disable_notifications(self, workspace_id):
61
+    def disable_notifications(self, workspace_id, next_url=None):
59 62
         workspace_id = int(workspace_id)
60 63
         api = WorkspaceApi(tg.tmpl_context.current_user)
61 64
 
62 65
         workspace = api.get_one(workspace_id)
63 66
         api.disable_notifications(tg.tmpl_context.current_user, workspace)
64 67
         tg.flash(_('Notification disabled for workspace {}').format(workspace.label))
68
+
69
+        if next_url:
70
+            tg.redirect(tg.url(next_url))
65 71
         tg.redirect(self.parent_controller.url(None, 'me'))
66 72
 
67 73
 
@@ -95,7 +101,7 @@ class UserPasswordRestController(TIMRestController):
95 101
         # FIXME - Allow only self password or operation for managers
96 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 106
         if not current_password or not new_password1 or not new_password2:
101 107
             tg.flash(_('Empty password is not allowed.'))
@@ -150,19 +156,20 @@ class UserRestController(TIMRestController):
150 156
         fake_api_content = DictLikeClass(current_user=current_user_content)
151 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 161
     @tg.expose('tracim.templates.user_edit_me')
156
-    def edit(self, id):
162
+    def edit(self, id, next_url=None):
157 163
         id = tmpl_context.current_user.user_id
158 164
         current_user = tmpl_context.current_user
159 165
         assert id==current_user.user_id
160 166
 
161 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 173
         user_id = tmpl_context.current_user.user_id
167 174
         current_user = tmpl_context.current_user
168 175
         assert user_id==current_user.user_id
@@ -170,5 +177,6 @@ class UserRestController(TIMRestController):
170 177
         api = UserApi(tmpl_context.current_user)
171 178
         api.update(current_user, name, email, True)
172 179
         tg.flash(_('profile updated.'))
180
+        if next_url:
181
+            tg.redirect(tg.url(next_url))
173 182
         tg.redirect(self.url())
174
-        return

+ 30 - 18
tracim/tracim/controllers/workspace.py View File

@@ -37,21 +37,11 @@ class UserWorkspaceRestController(TIMRestController):
37 37
         return 'workspace_id'
38 38
 
39 39
 
40
-    @tg.expose('tracim.templates.user_workspace_get_all')
40
+    @tg.expose()
41 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 45
     def get_one(self, workspace_id):
56 46
         user = tmpl_context.current_user
57 47
 
@@ -63,20 +53,36 @@ class UserWorkspaceRestController(TIMRestController):
63 53
 
64 54
         dictified_current_user = Context(CTX.CURRENT_USER).toDict(user)
65 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 63
         dictified_workspace = Context(CTX.WORKSPACE).toDict(workspace, 'workspace')
68 64
 
69 65
         return DictLikeClass(result = dictified_workspace, fake_api=fake_api)
70 66
 
71 67
 
72 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 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 80
         if not current_id:
77 81
             # Default case is to return list of workspaces
82
+            print('ignore : ', ignored_ids)
78 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 86
             dictified_workspaces = Context(CTX.MENU_API).toDict(workspaces, 'd')
81 87
             return dictified_workspaces
82 88
 
@@ -179,7 +185,9 @@ class UserWorkspaceRestController(TIMRestController):
179 185
 
180 186
 
181 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 192
         id must be "#" or something like "workspace_3__document_8"
185 193
         """
@@ -189,7 +197,11 @@ class UserWorkspaceRestController(TIMRestController):
189 197
         ignore_item_ids = [int(ignore_id)] if ignore_id else []
190 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 205
         contents = ContentApi(tmpl_context.current_user).get_child_folders(content, workspace, [], ignore_item_ids, viewable_content_types)
194 206
         # This allow to show contents and folders group by type
195 207
         sorted_contents = ContentApi.sort_content(contents)

+ 62 - 5
tracim/tracim/lib/content.py View File

@@ -11,6 +11,7 @@ import sqlalchemy
11 11
 from sqlalchemy.orm import aliased
12 12
 from sqlalchemy.orm import joinedload
13 13
 from sqlalchemy.orm.attributes import get_history
14
+from sqlalchemy import desc
14 15
 from sqlalchemy import not_
15 16
 from sqlalchemy import or_
16 17
 from tracim.lib import cmp_to_key
@@ -99,8 +100,8 @@ class ContentApi(object):
99 100
         breadcrumb = []
100 101
 
101 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 106
         if item_id:
106 107
             breadcrumb_folder_items = []
@@ -112,7 +113,7 @@ class ContentApi(object):
112 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 115
             while current_item:
115
-                breadcrumb_item = BreadcrumbItem(ContentType.icon(current_item.type),
116
+                breadcrumb_item = BreadcrumbItem(ContentType.get_icon(current_item.type),
116 117
                                                  current_item.label,
117 118
                                                  next_url,
118 119
                                                  is_active)
@@ -302,6 +303,38 @@ class ContentApi(object):
302 303
 
303 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 338
     def set_allowed_content(self, folder: Content, allowed_content_dict:dict):
306 339
         """
307 340
         :param folder: the given folder instance
@@ -326,14 +359,30 @@ class ContentApi(object):
326 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 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 368
                 raise ValueError('the item should stay in the same workspace')
333 369
 
334 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 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 387
     def update_content(self, item: Content, new_label: str, new_content: str=None) -> Content:
339 388
         if item.label==new_label and item.description==new_content:
@@ -442,3 +491,11 @@ class ContentApi(object):
442 491
 
443 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 View File

@@ -5,10 +5,12 @@
5 5
 #from webhelpers import date, feedgenerator, html, number, misc, text
6 6
 
7 7
 import datetime
8
+
9
+from babel.dates import format_date, format_time
8 10
 from markupsafe import Markup
9 11
 
10 12
 import tg
11
-
13
+from tg.i18n import ugettext as _
12 14
 from tracim.config.app_cfg import CFG
13 15
 
14 16
 from tracim.lib import app_globals as plag
@@ -25,10 +27,23 @@ from tracim.model.data import UserRoleInWorkspace
25 27
 from tracim.model.data import Workspace
26 28
 
27 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 48
 def format_short(datetime_object):
34 49
     return datetime_object.strftime(format = plag.Globals.SHORT_DATE_FORMAT.__str__())

+ 12 - 2
tracim/tracim/lib/workspace.py View File

@@ -68,8 +68,18 @@ class WorkspaceApi(object):
68 68
     def get_all(self):
69 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 83
         workspaces.sort(key=lambda workspace: workspace.label.lower())
74 84
         return workspaces
75 85
 

+ 8 - 0
tracim/tracim/model/auth.py View File

@@ -211,6 +211,14 @@ class User(DeclarativeBase):
211 211
         else:
212 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 223
 class Permission(DeclarativeBase):
216 224
     """

+ 150 - 37
tracim/tracim/model/data.py View File

@@ -1,5 +1,9 @@
1 1
 # -*- coding: utf-8 -*-
2 2
 
3
+import tg
4
+from datetime import datetime
5
+from babel.dates import format_timedelta
6
+
3 7
 from bs4 import BeautifulSoup
4 8
 import datetime as datetime_root
5 9
 import json
@@ -61,6 +65,19 @@ class Workspace(DeclarativeBase):
61 65
         """ this method is for interoperability with Content class"""
62 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 81
 class UserRoleInWorkspace(DeclarativeBase):
65 82
 
66 83
     __tablename__ = 'user_workspace'
@@ -93,6 +110,17 @@ class UserRoleInWorkspace(DeclarativeBase):
93 110
     STYLE[4] = 'color: #ea983d;'
94 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 125
     @property
98 126
     def style(self):
@@ -113,6 +141,7 @@ class UserRoleInWorkspace(DeclarativeBase):
113 141
 class RoleType(object):
114 142
     def __init__(self, role_id):
115 143
         self.role_type_id = role_id
144
+        self.icon = UserRoleInWorkspace.ICON[role_id]
116 145
         self.role_label = UserRoleInWorkspace.LABEL[role_id]
117 146
         self.css_style = UserRoleInWorkspace.STYLE[role_id]
118 147
 
@@ -142,27 +171,27 @@ class ActionDescription(object):
142 171
     UNDELETION = 'undeletion'
143 172
 
144 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 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 197
     def __init__(self, id):
@@ -214,10 +243,10 @@ class ContentStatus(object):
214 243
                     'closed-deprecated': l_('deprecated')}
215 244
 
216 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 252
     _CSS = {
@@ -268,14 +297,34 @@ class ContentType(object):
268 297
 
269 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 330
     _ORDER_WEIGHT = {
@@ -286,6 +335,16 @@ class ContentType(object):
286 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 348
     _DELETE_LABEL = {
290 349
         'dashboard': '',
291 350
         'workspace': l_('Delete this workspace'),
@@ -297,7 +356,7 @@ class ContentType(object):
297 356
     }
298 357
 
299 358
     @classmethod
300
-    def icon(cls, type: str):
359
+    def get_icon(cls, type: str):
301 360
         assert(type in ContentType._ICONS) # DYN_REMOVE
302 361
         return ContentType._ICONS[type]
303 362
 
@@ -343,6 +402,24 @@ class ContentType(object):
343 402
         # Make this code dynamic loading data types
344 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 424
 class Content(DeclarativeBase):
348 425
 
@@ -381,11 +458,11 @@ class Content(DeclarativeBase):
381 458
     parent = relationship('Content', remote_side=[content_id], backref='children')
382 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 462
         for child in self.children:
387 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 467
     @hybrid_property
391 468
     def properties(self):
@@ -400,6 +477,20 @@ class Content(DeclarativeBase):
400 477
         self._properties = json.dumps(properties_struct)
401 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 494
     def extract_links_from_content(self, other_content: str=None) -> [LinkItem]:
404 495
         """
405 496
         parse html content and extract links. By default, it works on the description property
@@ -427,7 +518,7 @@ class Content(DeclarativeBase):
427 518
 
428 519
     def get_child_nb(self, content_type: ContentType, content_status = ''):
429 520
         child_nb = 0
430
-        for child in self.valid_children:
521
+        for child in self.get_valid_children():
431 522
             if child.type == content_type or content_type == ContentType.Any:
432 523
                 if not content_status:
433 524
                     child_nb = child_nb+1
@@ -441,10 +532,19 @@ class Content(DeclarativeBase):
441 532
     def get_status(self) -> ContentStatus:
442 533
         return ContentStatus(self.status, self.type.__str__())
443 534
 
444
-
445 535
     def get_last_action(self) -> ActionDescription:
446 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 549
     def get_comments(self):
450 550
         children = []
@@ -466,7 +566,6 @@ class Content(DeclarativeBase):
466 566
 
467 567
         return last_comment
468 568
 
469
-
470 569
     def get_previous_revision(self) -> 'ContentRevisionRO':
471 570
         rev_ids = [revision.revision_id for revision in self.revisions]
472 571
         rev_ids.sort()
@@ -485,6 +584,20 @@ class Content(DeclarativeBase):
485 584
         # see http://stackoverflow.com/questions/12618567/problems-running-beautifulsoup4-within-apache-mod-python-django
486 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 602
 class ContentChecker(object):
490 603
 

+ 147 - 37
tracim/tracim/model/serializers.py View File

@@ -2,7 +2,12 @@
2 2
 import types
3 3
 
4 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 9
 import tg
10
+from tg.i18n import ugettext as _
6 11
 from tg.util import LazyString
7 12
 from tracim.lib.base import logger
8 13
 from tracim.lib.utils import exec_time_monitor
@@ -58,12 +63,14 @@ class CTX(object):
58 63
     """ constants that are used for serialization / dictification of models"""
59 64
     ADMIN_WORKSPACE = 'ADMIN_WORKSPACE'
60 65
     ADMIN_WORKSPACES = 'ADMIN_WORKSPACES'
66
+    CONTENT_LIST = 'CONTENT_LIST'
61 67
     CURRENT_USER = 'CURRENT_USER'
62 68
     DEFAULT = 'DEFAULT' # default context. This will allow to define a serialization method to be used by default
63 69
     EMAIL_NOTIFICATION = 'EMAIL_NOTIFICATION'
64 70
     FILE = 'FILE'
65 71
     FILES = 'FILES'
66 72
     FOLDER = 'FOLDER'
73
+    FOLDER_CONTENT_LIST = 'FOLDER_CONTENT_LIST'
67 74
     FOLDERS = 'FOLDERS'
68 75
     MENU_API = 'MENU_API'
69 76
     MENU_API_BUILD_FROM_TREE_ITEM = 'MENU_API_BUILD_FROM_TREE_ITEM'
@@ -265,7 +272,7 @@ def serialize_item(content: Content, context: Context):
265 272
     result = DictLikeClass(
266 273
         id = content.content_id,
267 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 276
         status = context.toDict(content.get_status()),
270 277
         folder = context.toDict(DictLikeClass(id = content.parent.content_id if content.parent else None)),
271 278
         workspace = context.toDict(content.workspace),
@@ -362,7 +369,7 @@ def serialize_node_for_page(content: Content, context: Context):
362 369
             content = data_container.description,
363 370
             created = data_container.created,
364 371
             label = data_container.label,
365
-            icon = ContentType.icon(content.type),
372
+            icon = ContentType.get_icon(content.type),
366 373
             owner = context.toDict(data_container.owner),
367 374
             status = context.toDict(data_container.get_status()),
368 375
             links = context.toDict(content.extract_links_from_content(data_container.description)),
@@ -394,7 +401,7 @@ def serialize_node_for_page(item: Content, context: Context):
394 401
         return DictLikeClass(
395 402
             content = item.description,
396 403
             created = item.created,
397
-            icon = ContentType.icon(item.type),
404
+            icon = ContentType.get_icon(item.type),
398 405
             id = item.content_id,
399 406
             label = item.label,
400 407
             links = context.toDict(item.extract_links_from_content(item.description)),
@@ -411,7 +418,8 @@ def serialize_node_for_page(item: Content, context: Context):
411 418
         return DictLikeClass(
412 419
             content = item.description,
413 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 423
             id = item.content_id,
416 424
             label = item.label,
417 425
             owner = context.toDict(item.owner),
@@ -432,10 +440,12 @@ def serialize_node_for_thread_list(content: Content, context: Context):
432 440
     if content.type==ContentType.Thread:
433 441
         return DictLikeClass(
434 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 451
     if content.type==ContentType.Folder:
@@ -514,32 +524,27 @@ def serialize_content_for_workspace_and_folder(content: Content, context: Contex
514 524
 
515 525
     result = None
516 526
     if content.type==ContentType.Folder:
527
+        allowed_content = DictLikeClass(content.properties['allowed_content']),
528
+
517 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 550
     elif content.type==ContentType.Page:
@@ -558,7 +563,102 @@ def serialize_content_for_workspace_and_folder(content: Content, context: Contex
558 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 663
 @pod_serializer(Content, CTX.SEARCH)
564 664
 def serialize_content_for_search_result(content: Content, context: Context):
@@ -587,22 +687,25 @@ def serialize_content_for_search_result(content: Content, context: Context):
587 687
         if comments:
588 688
             last_comment_datetime = max(last_comment_datetime, max(comment.updated for comment in comments))
589 689
 
690
+        content_type = ContentType(content.type)
590 691
         result = DictLikeClass(
591 692
             id = content.content_id,
693
+            type = DictLikeClass(content_type.toDict()),
592 694
             parent = context.toDict(content.parent),
593 695
             workspace = context.toDict(content.workspace),
594
-            type = content.type,
595 696
 
596 697
             content = data_container.description,
597 698
             content_raw = data_container.description_as_raw_text(),
598 699
 
599 700
             created = data_container.created,
701
+            created_as_delta = data_container.created_as_delta(),
600 702
             label = data_container.label,
601
-            icon = ContentType.icon(content.type),
703
+            icon = ContentType.get_icon(content.type),
602 704
             owner = context.toDict(data_container.owner),
603 705
             status = context.toDict(data_container.get_status()),
604 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 711
         if content.type==ContentType.File:
@@ -663,6 +766,7 @@ def serialize_role_list_for_select_field_in_workspace(role_type: RoleType, conte
663 766
     """
664 767
     result = DictLikeClass()
665 768
     result['id'] = role_type.role_type_id
769
+    result['icon'] = role_type.icon
666 770
     result['label'] = role_type.role_label
667 771
     result['style'] = role_type.css_style
668 772
     return result
@@ -738,11 +842,14 @@ def serialize_role_in_workspace(role: UserRoleInWorkspace, context: Context):
738 842
     """
739 843
     result = DictLikeClass()
740 844
     result['id'] = role.user_id
845
+    result['icon'] = role.icon
741 846
     result['name'] = role.user.display_name
742 847
     result['role'] = role.role
743 848
     result['style'] = role.style
744 849
     result['role_description'] = role.role_as_label()
745 850
     result['email'] = role.user.email
851
+    result['user'] = role.user
852
+    result['notifications_subscribed'] = role.do_notify
746 853
     return result
747 854
 
748 855
 
@@ -757,9 +864,11 @@ def serialize_role_in_list_for_user(role: UserRoleInWorkspace, context: Context)
757 864
     """
758 865
     result = DictLikeClass()
759 866
     result['id'] = role.role
867
+    result['icon'] = role.icon
760 868
     result['label'] = role.role_as_label()
761 869
     result['style'] = RoleType(role.role).css_style
762 870
     result['workspace'] =  context.toDict(role.workspace)
871
+    result['user'] = role.user
763 872
     result['notifications_subscribed'] = role.do_notify
764 873
 
765 874
     # result['workspace_name'] = role.workspace.label
@@ -816,6 +925,7 @@ def serialize_workspace_complete(workspace: pmd.Workspace, context: Context):
816 925
     result['created'] = workspace.created
817 926
     result['members'] = context.toDict(workspace.roles)
818 927
     result['member_nb'] = len(workspace.roles)
928
+    result['allowed_content_types'] = context.toDict(workspace.get_allowed_content_types())
819 929
 
820 930
     return result
821 931
 

+ 158 - 9
tracim/tracim/public/assets/css/dashboard.css View File

@@ -23,13 +23,18 @@ body {
23 23
  */
24 24
 .navbar-fixed-top {
25 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 34
 .navbar-fixed-top-transparent {
31 35
   border: 0;
32 36
   background-color: #f5f5f5;
37
+    background-color: #555;
33 38
   background-color: transparent;
34 39
 }
35 40
 
@@ -37,6 +42,10 @@ body {
37 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 50
  * Sidebar
42 51
  */
@@ -56,16 +65,21 @@ body {
56 65
     padding: 20px;
57 66
     overflow-x: hidden;
58 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 72
     border-right: 1px solid #CCC;
61
-    
73
+
62 74
   }
63 75
 }
64 76
 
65 77
 #sidebar-right {
66 78
   overflow-x: visible;
67 79
   overflow-y: auto;
68
-  
80
+    background-color: #F5F5F5;
81
+    border-left: 1px solid #CCC;
82
+
69 83
 }
70 84
 
71 85
 /* Sidebar navigation */
@@ -117,8 +131,8 @@ body {
117 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,8 +169,12 @@ iframe { border: 5px solid #b3e7ff; }
155 169
 .tracim-status-selected { background-color: #EEE; }
156 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 179
 #tracim-footer-separator { margin-bottom: 30px; }
162 180
 .pod-footer {
@@ -201,3 +219,134 @@ table.first_column_headers tr td:first-child {
201 219
     margin-top: -1em;
202 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
+}

File diff suppressed because it is too large
+ 4 - 0
tracim/tracim/public/assets/js/jquery.tablesorter.min.js


BIN
tracim/tracim/public/assets/jstree/themes/default/32px.png View File


+ 37 - 0
tracim/tracim/public/assets/jstree/themes/tracim/style.css View File

@@ -0,0 +1,37 @@
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 View File

@@ -0,0 +1,21 @@
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 View File

@@ -0,0 +1,90 @@
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 View File

@@ -0,0 +1,25 @@
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 View File

@@ -0,0 +1,184 @@
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 View File

@@ -0,0 +1,26 @@
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 View File

@@ -0,0 +1,26 @@
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 View File

@@ -0,0 +1,41 @@
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 View File

@@ -0,0 +1,43 @@
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 View File

@@ -0,0 +1,29 @@
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 View File

@@ -0,0 +1,119 @@
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 View File

@@ -0,0 +1,70 @@
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 View File

@@ -0,0 +1,75 @@
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 View File

@@ -0,0 +1,109 @@
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 View File

@@ -0,0 +1,108 @@
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 View File

@@ -0,0 +1,107 @@
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 View File

@@ -0,0 +1,107 @@
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 View File

@@ -0,0 +1,116 @@
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 View File

@@ -0,0 +1,106 @@
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 View File

@@ -0,0 +1,107 @@
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 View File

@@ -0,0 +1,108 @@
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 View File

@@ -0,0 +1,108 @@
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 View File

@@ -0,0 +1,108 @@
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 View File

@@ -0,0 +1,85 @@
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 View File

@@ -0,0 +1,118 @@
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
+

File diff suppressed because it is too large
+ 329 - 0
tracim/tracim/public/assets/tablesorter/docs/example-pager.html


+ 112 - 0
tracim/tracim/public/assets/tablesorter/docs/example-parsers.html View File

@@ -0,0 +1,112 @@
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 View File

@@ -0,0 +1,113 @@
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>

File diff suppressed because it is too large
+ 336 - 0
tracim/tracim/public/assets/tablesorter/docs/example-triggers.html


+ 118 - 0
tracim/tracim/public/assets/tablesorter/docs/example-update-cell.html View File

@@ -0,0 +1,118 @@
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 View File

@@ -0,0 +1,383 @@
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
tracim/tracim/public/assets/tablesorter/docs/img/external.png View File


+ 577 - 0
tracim/tracim/public/assets/tablesorter/docs/index.html View File

@@ -0,0 +1,577 @@
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 View File

@@ -0,0 +1,23 @@
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 View File

@@ -0,0 +1,29 @@
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 View File

@@ -0,0 +1,154 @@
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 View File

@@ -0,0 +1,122 @@
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);

File diff suppressed because it is too large
+ 1038 - 0
tracim/tracim/public/assets/tablesorter/jquery.tablesorter.js


File diff suppressed because it is too large
+ 4 - 0
tracim/tracim/public/assets/tablesorter/jquery.tablesorter.min.js


+ 27 - 0
tracim/tracim/public/assets/tablesorter/package.json View File

@@ -0,0 +1,27 @@
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
tracim/tracim/public/assets/tablesorter/themes/blue/asc.gif View File


BIN
tracim/tracim/public/assets/tablesorter/themes/blue/bg.gif View File


BIN
tracim/tracim/public/assets/tablesorter/themes/blue/blue.zip View File


BIN
tracim/tracim/public/assets/tablesorter/themes/blue/desc.gif View File


+ 39 - 0
tracim/tracim/public/assets/tablesorter/themes/blue/style.css View File

@@ -0,0 +1,39 @@
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
tracim/tracim/public/assets/tablesorter/themes/green/asc.png View File


BIN
tracim/tracim/public/assets/tablesorter/themes/green/bg.png View File


BIN
tracim/tracim/public/assets/tablesorter/themes/green/desc.png View File


BIN
tracim/tracim/public/assets/tablesorter/themes/green/green.zip View File


+ 39 - 0
tracim/tracim/public/assets/tablesorter/themes/green/style.css View File

@@ -0,0 +1,39 @@
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
tracim/tracim/public/assets/tablesorter/themes/tracim/asc.gif View File


BIN
tracim/tracim/public/assets/tablesorter/themes/tracim/bg.gif View File


BIN
tracim/tracim/public/assets/tablesorter/themes/tracim/desc.gif View File


+ 21 - 0
tracim/tracim/public/assets/tablesorter/themes/tracim/style.css View File

@@ -0,0 +1,21 @@
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 View File

@@ -0,0 +1,63 @@
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 View File


+ 7 - 0
tracim/tracim/templates/admin/user_edit.mak View File

@@ -0,0 +1,7 @@
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 View File

@@ -1,29 +1,43 @@
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 4
 <%namespace name="TIM" file="tracim.templates.pod"/>
3 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 26
 <div class="container-fluid">
8 27
     <div class="row-fluid">
9
-        ${TOOLBAR.USERS(fake_api.current_user)}
10 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 29
             ## ADD A USER
18 30
             % if fake_api.current_user.profile.id>=2:
19 31
                 ## FIXME: check if the current_user is a workspace manager (so he is also allowed to create user)
20 32
                 ## In this case the user is a pod manager, so he is allowed to create users (and to delete them)
21 33
                 <div class="row">
22 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 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 41
                                 <form role="form" method="POST" action="${tg.url('/admin/users')}">
28 42
                                     <div class="form-group">
29 43
                                         <label for="user-name">${_('Name')}</label>
@@ -67,7 +81,6 @@
67 81
                                             });
68 82
                                         });
69 83
                                     </script>
70
-
71 84
                                 </form>
72 85
                                 <div style="clear: both;"></div>
73 86
                             </div>
@@ -81,7 +94,7 @@
81 94
 
82 95
             ## LIST OF USERS
83 96
             <div class="row">
84
-                <div  class="col-sm-11">
97
+                <div class="col-md-offset-3 col-md-8 t-spacer-above">
85 98
                     % if result.user_nb<=0:
86 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 100
                     % else:
@@ -97,43 +110,45 @@
97 110
                                 </tr>
98 111
                             </thead>
99 112
                             % for user in result.users:
100
-                                <tr>
113
+                                <tr class="${('t-less-visible', '')[user.enabled]}">
101 114
                                     % if user.enabled:
102 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 117
                                         </td>
105 118
                                         <td><a href="${tg.url('/admin/users/{}'.format(user.id))}"><b>${user.name}</b></a></td>
106 119
                                         <td><a href="mailto:${user.email}">${user.email}</a></td>
107 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 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 125
                                         </td>
112 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 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 131
                                         </td>
117 132
                                     % else:
118 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 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 137
                                         <td>${user.email}</td>
123 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 141
                                         </td>
127 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 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 146
                                         </td>
132 147
                                     % endif
133 148
                                     <td>
134 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 153
                                         % endif
139 154
                                     </td>
@@ -144,8 +159,6 @@
144 159
                 </div>
145 160
             </div>
146 161
             ## LIST OF USERS [END]
147
-
148
-
149 162
         </div>
150 163
     </div>
151 164
 </div>

+ 110 - 0
tracim/tracim/templates/admin/user_getone.mak View File

@@ -0,0 +1,110 @@
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 View File

@@ -0,0 +1,6 @@
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 View File

@@ -1,26 +1,39 @@
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 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 25
 <div class="container-fluid">
8 26
     <div class="row-fluid">
9
-        ${TOOLBAR.WORKSPACES(fake_api.current_user)}
10 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 28
             ## ADD A WORKSPACE
18 29
             % if fake_api.current_user.profile.id>=2:
19 30
                 ## In this case the user is a pod manager, so he is allowed to create workspaces (and to delete them)
20 31
                 <div class="row">
21 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 37
                         <div id="create-workspace-form" class="collapse">
25 38
                             <div class="pod-inline-form col-sm-6" >
26 39
                                 <form role="form" method="POST" action="${tg.url('/admin/workspaces')}">
@@ -50,10 +63,9 @@
50 63
             % endif
51 64
             ## ADD A WORKSPACE [END]
52 65
 
53
-
54 66
             ## LIST OF WORKSPACES
55 67
             <div class="row">
56
-                <div  class="col-sm-11">
68
+                <div class="col-md-offset-3 col-md-8 t-spacer-above">
57 69
                     % if result.workspace_nb<=0:
58 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 71
                     % else:
@@ -79,8 +91,6 @@
79 91
                 </div>
80 92
             </div>
81 93
             ## LIST OF WORKSPACES [END]
82
-
83
-
84 94
         </div>
85 95
     </div>
86 96
 </div>

+ 133 - 0
tracim/tracim/templates/admin/workspace_getone.mak View File

@@ -0,0 +1,133 @@
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 View File

@@ -1,45 +0,0 @@
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 View File


tracim/tracim/templates/user_workspace_folder_file_edit.mak → tracim/tracim/templates/file/edit.mak View File


+ 56 - 0
tracim/tracim/templates/file/forms.mak View File

@@ -0,0 +1,56 @@
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 View File

@@ -0,0 +1,184 @@
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 View File

@@ -0,0 +1,5 @@
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 View File

@@ -1,17 +1,20 @@
1 1
 <%namespace name="TIM" file="tracim.templates.pod"/>
2
+<%namespace name="ICON" file="tracim.templates.widgets.icon"/>
2 3
 
3 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 6
     <% edit_disabled = ('', 'disabled')[file.selected_revision!='latest' or file.status.id[:6]=='closed'] %>
5 7
     <% delete_or_archive_disabled = ('', 'disabled')[file.selected_revision!='latest'] %> 
6 8
     % if h.user_role(user, workspace)>1:
7 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 11
         </div>
10 12
         <p></p>
11 13
     % endif
12 14
     
13 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 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 19
     </div>
17 20
     <p></p>
@@ -20,8 +23,8 @@
20 23
         ## if the user can see the toolbar, it means he is the workspace manager.
21 24
         ## So now, we need to know if he alsa has right to delete workspaces
22 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 28
         </div>
26 29
     % endif
27 30
 </%def>

+ 0 - 0
tracim/tracim/templates/folder/__init__.py View File


tracim/tracim/templates/folder_edit.mak → tracim/tracim/templates/folder/edit.mak View File

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

+ 82 - 0
tracim/tracim/templates/folder/forms.mak View File

@@ -0,0 +1,82 @@
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 View File

@@ -0,0 +1,177 @@
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 View File

@@ -1,8 +1,8 @@
1 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 4
 <%def name="title()"></%def>
5 5
 
6 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 View File

@@ -0,0 +1,6 @@
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 View File

@@ -1,6 +1,26 @@
1 1
 <%namespace name="TIM" file="tracim.templates.pod"/>
2 2
 
3 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 24
     <% edit_disabled = ('', 'disabled')[folder.selected_revision!='latest' or folder.status.id[:6]=='closed'] %>
5 25
     <%
6 26
         ## FIXME - This control should be based on the user role
@@ -11,7 +31,7 @@
11 31
     % if h.user_role(user, workspace)>2:
12 32
         <div class="btn-group btn-group-vertical">
13 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 35
         </div>
16 36
         <p></p>
17 37
     % endif
@@ -19,7 +39,7 @@
19 39
     % if user.profile.id>=3 or h.user_role(user, workspace)>=4:
20 40
         <div class="btn-group btn-group-vertical">
21 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 43
         </div>
24 44
         <p></p>
25 45
     % endif
@@ -28,8 +48,8 @@
28 48
         ## if the user can see the toolbar, it means he is the workspace manager.
29 49
         ## So now, we need to know if he alsa has right to delete workspaces
30 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 53
         </div>
34 54
         <p></p>
35 55
     % endif

+ 173 - 0
tracim/tracim/templates/home.mak View File

@@ -0,0 +1,173 @@
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 View File

@@ -82,7 +82,6 @@
82 82
                     <span class="icon-bar"></span>
83 83
                 </button>
84 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 85
                   <img src="${tg.url('/assets/img/logo.png')}" class="pull-left" style="margin: -13px 0.5em 0 -13px;"/>
87 86
                 </a>
88 87
             </div>

+ 53 - 44
tracim/tracim/templates/master_authenticated.mak View File

@@ -2,9 +2,9 @@
2 2
 <!DOCTYPE html>
3 3
 <html>
4 4
     <head>
5
-	    ${self.meta()}
5
+        ${self.meta()}
6 6
         <meta charset="utf-8">
7
-	    <title>${self.title()}</title>
7
+        <title>${self.title()}</title>
8 8
         <meta http-equiv="X-UA-Compatible" content="IE=edge">
9 9
         <meta name="viewport" content="width=device-width, initial-scale=1">
10 10
         <meta name="description" content="">
@@ -67,6 +67,28 @@
67 67
 
68 68
 <%def name="main_menu()">
69 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 92
         <div class="container-fluid">
71 93
             <div class="navbar-header">
72 94
                 <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
@@ -80,18 +102,32 @@
80 102
                   <img src="${tg.url('/assets/img/logo.png')}" class="pull-left" style="height: 48px; margin: -13px 0.5em 0 -13px;"/>
81 103
                 </a>
82 104
             </div>
105
+
83 106
             <div class="navbar-collapse collapse">
84 107
                 % if request.identity:
85 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 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 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 131
 ## TODO - D.A. - 2014-10-20 - Restore global configuration screen
96 132
 ##                                <li class="divider" role="presentation"></li>
97 133
 ##                                <li><a href="${tg.url('/admin/configuration')}">${TIM.ICO(16, 'categories/preferences-system')} ${_('Global configuration')}</a></li>
@@ -99,54 +135,28 @@
99 135
                             </li>
100 136
                         % endif
101 137
 
102
-                        % if h.is_debug_mode():
138
+                        % if False and h.is_debug_mode():
103 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 141
                                 <ul class="dropdown-menu">
106 142
                                     <li><a class="text-danger" href=""><strong>${_('you MUST desactivate debug in production')}</strong></a></li>
107 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 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 149
                                 </ul>
114 150
                             </li>
115 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 152
                         <li class="dropdown">
139 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 156
                             </a>
142 157
                             <ul class="dropdown-menu pull-right">
143 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 160
                                 </li>
151 161
                             </ul>
152 162
                         </li>
@@ -171,5 +181,4 @@
171 181
         </div>
172 182
     </div>
173 183
 </%def>
174
-
175 184
 </html>

+ 98 - 0
tracim/tracim/templates/master_authenticated_left_treeview.mak View File

@@ -0,0 +1,98 @@
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 View File

@@ -1,6 +1,7 @@
1 1
 <%inherit file="local:templates.master_authenticated"/>
2 2
 <%namespace name="TIM" file="tracim.templates.pod"/>
3 3
 
4
+<%def name="TITLE_ROW()"></%def>
4 5
 <%def name="SIDEBAR_LEFT_CONTENT()"></%def>
5 6
 <%def name="SIDEBAR_RIGHT_CONTENT()"></%def>
6 7
 <%def name="REQUIRED_DIALOGS()"></%def>
@@ -11,7 +12,7 @@
11 12
         <div class="row-fluid">
12 13
         
13 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 16
                 <div class="btn-group" style="position: absolute; right: 2px; top: 4px; ">
16 17
                     <button id="toggle-left-sidebar-width" type="button" class="btn btn-link"><i class="fa fa-angle-double-right"></i></button>
17 18
                 </div>
@@ -20,20 +21,14 @@
20 21
             ## SIDEBAR LEFT [END]
21 22
 
22 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 25
                 ${self.SIDEBAR_RIGHT_CONTENT()}
25 26
             </div> <!-- # End of side bar right -->
26 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 32
             </div>
38 33
         </div>
39 34
     </div>
@@ -54,13 +49,13 @@
54 49
               buttonIcon = $('> i', this);
55 50
               if (sidebar.hasClass('fixed-width-sidebar')) {
56 51
                 sidebar.removeClass('fixed-width-sidebar')
57
-                sidebar.removeClass('col-sm-2');
52
+                sidebar.removeClass('col-sm-3');
58 53
                 
59 54
                 buttonIcon.removeClass('fa-angle-double-right');
60 55
                 buttonIcon.addClass('fa-angle-double-left');
61 56
               } else {
62 57
                 sidebar.addClass('fixed-width-sidebar')
63
-                sidebar.addClass('col-sm-2');
58
+                sidebar.addClass('col-sm-3');
64 59
                 buttonIcon.removeClass('fa-angle-double-left');
65 60
                 buttonIcon.addClass('fa-angle-double-right');
66 61
               }
@@ -75,10 +70,16 @@
75 70
     <script src="${tg.url('/assets/tinymce/js/tinymce/tinymce.min.js')}"></script>
76 71
     ${TIM.TINYMCE_INIT_SCRIPT('.pod-rich-textarea')}
77 72
 
78
-
79 73
     <!-- JSTree ================================================== -->
80 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 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 84
 </%def>
84 85
 

+ 0 - 0
tracim/tracim/templates/page/__init__.py View File


tracim/tracim/templates/user_workspace_folder_page_edit.mak → tracim/tracim/templates/page/edit.mak View File


+ 0 - 0
tracim/tracim/templates/page/forms.mak View File


Some files were not shown because too many files changed in this diff