 Holger Frey
					
					6 years ago
						Holger Frey
					
					6 years ago
					
				
				 14 changed files with 285 additions and 26 deletions
			
			
		| @ -0,0 +1,85 @@@@ -0,0 +1,85 @@ | ||||
| /*! | ||||
| Waypoints Infinite Scroll Shortcut - 4.0.1 | ||||
| Copyright © 2011-2016 Caleb Troughton | ||||
| Licensed under the MIT license. | ||||
| https://github.com/imakewebthings/waypoints/blob/master/licenses.txt
 | ||||
| */ | ||||
| (function() { | ||||
|   'use strict' | ||||
| 
 | ||||
|   var $ = window.jQuery | ||||
|   var Waypoint = window.Waypoint | ||||
| 
 | ||||
|   /* http://imakewebthings.com/waypoints/shortcuts/infinite-scroll */ | ||||
|   function Infinite(options) { | ||||
|     this.options = $.extend({}, Infinite.defaults, options) | ||||
|     this.container = this.options.element | ||||
|     if (this.options.container !== 'auto') { | ||||
|       this.container = this.options.container | ||||
|     } | ||||
|     this.$container = $(this.container) | ||||
|     this.$more = $(this.options.more) | ||||
| 
 | ||||
|     if (this.$more.length) { | ||||
|       this.setupHandler() | ||||
|       this.waypoint = new Waypoint(this.options) | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /* Private */ | ||||
|   Infinite.prototype.setupHandler = function() { | ||||
|     this.options.handler = $.proxy(function() { | ||||
|       this.options.onBeforePageLoad() | ||||
|       this.destroy() | ||||
|       this.$container.addClass(this.options.loadingClass) | ||||
| 
 | ||||
|       $.get($(this.options.more).attr('href'), $.proxy(function(data) { | ||||
|         var $data = $($.parseHTML(data)) | ||||
|         var $newMore = $data.find(this.options.more) | ||||
| 
 | ||||
|         var $items = $data.find(this.options.items) | ||||
|         if (!$items.length) { | ||||
|           $items = $data.filter(this.options.items) | ||||
|         } | ||||
| 
 | ||||
|         this.$container.append($items) | ||||
|         this.$container.removeClass(this.options.loadingClass) | ||||
| 
 | ||||
|         if (!$newMore.length) { | ||||
|           $newMore = $data.filter(this.options.more) | ||||
|         } | ||||
|         if ($newMore.length) { | ||||
|           this.$more.replaceWith($newMore) | ||||
|           this.$more = $newMore | ||||
|           this.waypoint = new Waypoint(this.options) | ||||
|           this.$container.append(this.$more) | ||||
|         } | ||||
|         else { | ||||
|           this.$more.remove() | ||||
|         } | ||||
| 
 | ||||
|         this.options.onAfterPageLoad($items) | ||||
|       }, this)) | ||||
|     }, this) | ||||
|   } | ||||
| 
 | ||||
|   /* Public */ | ||||
|   Infinite.prototype.destroy = function() { | ||||
|     if (this.waypoint) { | ||||
|       this.waypoint.destroy() | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   Infinite.defaults = { | ||||
|     container: 'auto', | ||||
|     items: '.infinite-item', | ||||
|     more: '.infinite-more-link', | ||||
|     offset: 'bottom-in-view', | ||||
|     loadingClass: 'infinite-loading', | ||||
|     onBeforePageLoad: $.noop, | ||||
|     onAfterPageLoad: $.noop | ||||
|   } | ||||
| 
 | ||||
|   Waypoint.Infinite = Infinite | ||||
| }()) | ||||
| ; | ||||
| @ -0,0 +1,7 @@@@ -0,0 +1,7 @@ | ||||
| /*! | ||||
| Waypoints Infinite Scroll Shortcut - 4.0.1 | ||||
| Copyright © 2011-2016 Caleb Troughton | ||||
| Licensed under the MIT license. | ||||
| https://github.com/imakewebthings/waypoints/blob/master/licenses.txt
 | ||||
| */ | ||||
| !function(){"use strict";function t(n){this.options=i.extend({},t.defaults,n),this.container=this.options.element,"auto"!==this.options.container&&(this.container=this.options.container),this.$container=i(this.container),this.$more=i(this.options.more),this.$more.length&&(this.setupHandler(),this.waypoint=new o(this.options))}var i=window.jQuery,o=window.Waypoint;t.prototype.setupHandler=function(){this.options.handler=i.proxy(function(){this.options.onBeforePageLoad(),this.destroy(),this.$container.addClass(this.options.loadingClass),i.get(i(this.options.more).attr("href"),i.proxy(function(t){var n=i(i.parseHTML(t)),e=n.find(this.options.more),s=n.find(this.options.items);s.length||(s=n.filter(this.options.items)),this.$container.append(s),this.$container.removeClass(this.options.loadingClass),e.length||(e=n.filter(this.options.more)),e.length?(this.$more.replaceWith(e),this.$more=e,this.waypoint=new o(this.options)):this.$more.remove(),this.options.onAfterPageLoad(s)},this))},this)},t.prototype.destroy=function(){this.waypoint&&this.waypoint.destroy()},t.defaults={container:"auto",items:".infinite-item",more:".infinite-more-link",offset:"bottom-in-view",loadingClass:"infinite-loading",onBeforePageLoad:i.noop,onAfterPageLoad:i.noop},o.Infinite=t}(); | ||||
									
										
											File diff suppressed because one or more lines are too long
										
									
								
							
						| @ -1,29 +1,18 @@@@ -1,29 +1,18 @@ | ||||
| {% extends "ordr3:templates/layout_small.jinja2" %} | ||||
| {% extends "ordr3:templates/layout_full.jinja2" %} | ||||
| 
 | ||||
| {% block subtitle %} My Account {% endblock subtitle %} | ||||
| 
 | ||||
| {% block content %} | ||||
| 
 | ||||
| <div class="container"> | ||||
|     <div class="row o3-registration-card"> | ||||
|         <div class="col"></div> | ||||
|         <div class="col"> | ||||
|             <div class="card"> | ||||
|                 <div class="card-header bg-dark text-light"> | ||||
|                     <h2 class="card-title text-center pt-1">Ordr</h5> | ||||
|                 </div> | ||||
|                 <div class="card-body"> | ||||
|                     <h6 class="card-subtitle mb-2 text-muted text-center mt-1 mb-4">Edit your account</h6> | ||||
|                     {{form.render()|safe}} | ||||
|                     <hr> | ||||
|                     <p class="mt-4"> | ||||
|                         <a href="{{request.resource_url(request.root, 'mypassword')}}" class="btn btn-outline-secondary">Change Password</a> | ||||
|                     </p> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="col"></div> | ||||
|     </div> | ||||
| <div class="col-2 o3-sidebar"></div> | ||||
| <div class="col-5"> | ||||
|     <h4 class="mb-2 text-muted mb-4">Edit your account</h4> | ||||
|     {{form.render()|safe}} | ||||
|     <hr> | ||||
|     <p class="mt-4"> | ||||
|         <a href="{{request.resource_url(request.root, 'mypassword')}}" class="btn btn-outline-secondary">Change Password</a> | ||||
|     </p> | ||||
| </div> | ||||
| <div class="col-5"></div> | ||||
| 
 | ||||
| {% endblock content %} | ||||
|  | ||||
| @ -0,0 +1,40 @@@@ -0,0 +1,40 @@ | ||||
| {% extends "ordr3:templates/layout_full.jinja2" %} | ||||
| 
 | ||||
| {% block subtitle %} Manage Users {% endblock subtitle %} | ||||
| 
 | ||||
| {% block content %} | ||||
| 
 | ||||
| <div class="col-2 o3-sidebar"> | ||||
| 
 | ||||
|     <nav class="nav nav-pills flex-column"> | ||||
|         <div class="nav-link disabled text-small" tabindex="-1" aria-disabled="true">Role</div> | ||||
|         <a class="nav-link  {% if filter_role == 'all' %}active{% endif %}" href="{{ request.resource_url(context) }}">All</a> | ||||
|         {% for role in roles %} | ||||
|             <a class="nav-link {% if filter_role == role.name.lower() %}active{% endif %}" href="{{ request.resource_url(context, query={'role':role.name.lower()}) }}">{{role.name.lower()}}</a> | ||||
|         {% endfor %} | ||||
|     </nav> | ||||
| 
 | ||||
| </div> | ||||
| <div class="col-10"> | ||||
|     <table class="table table-hover o3-data-table"> | ||||
|         <thead> | ||||
|             <tr> | ||||
|                 <th scope="col">Username</th> | ||||
|                 <th scope="col">First Name</th> | ||||
|                 <th scope="col">Last Name</th> | ||||
|                 <th scope="col">Email</th> | ||||
|                 <th scope="col">Role</th> | ||||
|                 <th scope="col">Actions</th> | ||||
|             </tr> | ||||
|         </thead> | ||||
|         <tbody class="infinite-container"> | ||||
|             {% include 'ordr3:templates/users/list_content.jinja2' %} | ||||
|         </tbody> | ||||
|     </table> | ||||
|     {% if not users %} | ||||
|         <p class="bg-light text-center pt-2 pb-2">No data available</p> | ||||
|     {% endif %} | ||||
| </div> | ||||
| 
 | ||||
| 
 | ||||
| {% endblock content %} | ||||
| @ -0,0 +1,24 @@@@ -0,0 +1,24 @@ | ||||
| {% import 'ordr3:templates/macros.jinja2' as macros with context %} | ||||
| {% for user in users %} | ||||
|     <tr class="infinite-item"> | ||||
|         <td><a href="{{request.resource_url(request.root, 'orders', query={'user':user.username})}}" title="show orders">{{ user.username }}</a></td> | ||||
|         <td>{{ user.first_name }}</td> | ||||
|         <td>{{ user.last_name }}</td> | ||||
|         <td><a class="o3-copy" title="copy to clipboard">{{ user.email }}</a></td> | ||||
|         <td>{{ user.role.name.capitalize() }}</td> | ||||
|         <td class="o3-actions"> | ||||
|             <a href="{{ request.resource_url(context, user.username, 'edit') }}" title="Edit user">{{ macros.icon("pencil")}}</a> | ||||
|             <a href="{{ request.resource_url(context, user.username, 'delete') }}" title="Delete user">{{ macros.icon("trash")}}</a> | ||||
|         </td> | ||||
|     </tr> | ||||
| {% endfor %} | ||||
| {% if next_offset %} | ||||
|     <tr class="infinite-more-link" href="{{ request.resource_url(context, query={'o':next_offset, 'role':filter_role.lower()}) }}"> | ||||
|         <td colspan="6"> | ||||
|             <button class="btn btn-outline-primary btn-small"> | ||||
|                 <span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> | ||||
|                 Loading... | ||||
|             </button> | ||||
|         </td> | ||||
|     </tr> | ||||
| {% endif %} | ||||
| @ -0,0 +1,55 @@@@ -0,0 +1,55 @@ | ||||
| from sqlalchemy import func | ||||
| from pyramid.view import view_config | ||||
| 
 | ||||
| from .. import models | ||||
| 
 | ||||
| 
 | ||||
| def _get_role(request): | ||||
|     role_param = request.GET.get("role", "") | ||||
|     try: | ||||
|         return models.UserRole[role_param.upper()] | ||||
|     except KeyError: | ||||
|         return None | ||||
| 
 | ||||
| 
 | ||||
| def _get_offset(request): | ||||
|     offset_param = request.GET.get("o", 0) | ||||
|     try: | ||||
|         return int(offset_param) | ||||
|     except ValueError: | ||||
|         return 0 | ||||
| 
 | ||||
| 
 | ||||
| @view_config( | ||||
|     context="ordr3:resources.UserList", | ||||
|     permission="view", | ||||
|     request_method="GET", | ||||
|     renderer="ordr3:templates/users/list.jinja2", | ||||
| ) | ||||
| @view_config( | ||||
|     context="ordr3:resources.UserList", | ||||
|     permission="view", | ||||
|     request_method="GET", | ||||
|     xhr=True, | ||||
|     renderer="ordr3:templates/users/list_content.jinja2", | ||||
| ) | ||||
| def list(context, request): | ||||
|     role = _get_role(request) | ||||
|     offset = _get_offset(request) | ||||
|     limit = 12 | ||||
| 
 | ||||
|     query = request.repo.session.query(models.User) | ||||
|     if role: | ||||
|         query = query.filter(models.User.role == role) | ||||
|     query = query.order_by(func.lower(models.User.username)) | ||||
|     users = query[offset : offset + limit]  # noqa: E203 | ||||
| 
 | ||||
|     next_offset = None if limit != len(users) else (offset + limit) | ||||
|     filter_role = "all" if role is None else role.name.lower() | ||||
| 
 | ||||
|     return { | ||||
|         "filter_role": filter_role, | ||||
|         "roles": models.UserRole, | ||||
|         "users": users, | ||||
|         "next_offset": next_offset, | ||||
|     } | ||||
					Loading…
					
					
				
		Reference in new issue