mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-01-17 06:52:27 +01:00
[feature] ability to filter events by category, theme and age
This commit is contained in:
parent
6e5fd86ad3
commit
bdda4cd7b0
@ -1,13 +1,7 @@
|
||||
'use strict'
|
||||
|
||||
Application.Controllers.controller "EventsController", ["$scope", "$state", 'Event', ($scope, $state, Event) ->
|
||||
|
||||
|
||||
|
||||
### PRIVATE STATIC CONSTANTS ###
|
||||
|
||||
# Number of events added to the page when the user clicks on 'load next events'
|
||||
EVENTS_PER_PAGE = 12
|
||||
Application.Controllers.controller "EventsController", ["$scope", "$state", 'Event', 'categoriesPromise', 'themesPromise', 'ageRangesPromise'
|
||||
, ($scope, $state, Event, categoriesPromise, themesPromise, ageRangesPromise) ->
|
||||
|
||||
|
||||
|
||||
@ -16,33 +10,37 @@ Application.Controllers.controller "EventsController", ["$scope", "$state", 'Eve
|
||||
## The events displayed on the page
|
||||
$scope.events = []
|
||||
|
||||
## By default, the pagination mode is activated to limit the page size
|
||||
$scope.paginateActive = true
|
||||
|
||||
## The currently displayed page number
|
||||
$scope.page = 1
|
||||
|
||||
## List of categories for the events
|
||||
$scope.categories = categoriesPromise
|
||||
|
||||
## List of events themes
|
||||
$scope.themes = themesPromise
|
||||
|
||||
## List of age ranges
|
||||
$scope.ageRanges = ageRangesPromise
|
||||
|
||||
## Active filters for the events list
|
||||
$scope.filters =
|
||||
category_id: null
|
||||
theme_id: null
|
||||
age_range_id: null
|
||||
|
||||
|
||||
|
||||
##
|
||||
# Adds EVENTS_PER_PAGE events to the bottom of the page, grouped by month
|
||||
# Adds a resultset of events to the bottom of the page, grouped by month
|
||||
##
|
||||
$scope.loadMoreEvents = ->
|
||||
Event.query {page: $scope.page}, (data) ->
|
||||
Event.query Object.assign({page: $scope.page}, $scope.filters), (data) ->
|
||||
$scope.events = $scope.events.concat data
|
||||
if data.length > 0
|
||||
$scope.paginateActive = false if ($scope.page-2)*EVENTS_PER_PAGE+data.length >= data[0].nb_total_events
|
||||
groupEvents(data)
|
||||
$scope.page += 1
|
||||
|
||||
$scope.eventsGroupByMonth = _.groupBy($scope.events, (obj) ->
|
||||
_.map ['month', 'year'], (key, value) -> obj[key]
|
||||
)
|
||||
$scope.monthOrder = _.sortBy _.keys($scope.eventsGroupByMonth), (k)->
|
||||
monthYearArray = k.split(',')
|
||||
date = new Date()
|
||||
date.setMonth(monthYearArray[0])
|
||||
date.setYear(monthYearArray[1])
|
||||
return -date.getTime()
|
||||
else
|
||||
$scope.paginateActive = false
|
||||
$scope.page += 1
|
||||
if (!data[0] || data[0].nb_total_events <= $scope.events.length)
|
||||
$scope.noMoreResults = true
|
||||
|
||||
|
||||
|
||||
@ -55,13 +53,58 @@ Application.Controllers.controller "EventsController", ["$scope", "$state", 'Eve
|
||||
|
||||
|
||||
|
||||
##
|
||||
# Callback to refresh the events list according to the filters set
|
||||
##
|
||||
$scope.filterEvents = ->
|
||||
# reinitialize results datasets
|
||||
$scope.page = 1
|
||||
$scope.eventsGroupByMonth = {}
|
||||
$scope.events = []
|
||||
$scope.monthOrder = []
|
||||
|
||||
# run a search query
|
||||
Event.query Object.assign({page: $scope.page}, $scope.filters), (data) ->
|
||||
$scope.events = data
|
||||
groupEvents(data)
|
||||
$scope.page += 1
|
||||
|
||||
if (!data[0] || data[0].nb_total_events <= $scope.events.length)
|
||||
$scope.noMoreResults = true
|
||||
|
||||
|
||||
|
||||
### PRIVATE SCOPE ###
|
||||
|
||||
##
|
||||
# Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
##
|
||||
initialize = ->
|
||||
$scope.loadMoreEvents()
|
||||
$scope.filterEvents()
|
||||
|
||||
|
||||
|
||||
##
|
||||
# Group the provided events by month/year and concat them with existing results
|
||||
# Then compute the ordered list of months for the complete resultset.
|
||||
# Affect the resulting events groups in $scope.eventsGroupByMonth and the ordered month keys in $scope.monthOrder.
|
||||
# @param {Array} Events retrived from the API
|
||||
##
|
||||
groupEvents = (events) ->
|
||||
if events.length > 0
|
||||
eventsGroupedByMonth = _.groupBy(events, (obj) ->
|
||||
_.map ['month', 'year'], (key, value) -> obj[key]
|
||||
)
|
||||
$scope.eventsGroupByMonth = Object.assign($scope.eventsGroupByMonth, eventsGroupedByMonth)
|
||||
|
||||
monthsOrder = _.sortBy _.keys($scope.eventsGroupByMonth), (k)->
|
||||
monthYearArray = k.split(',')
|
||||
date = new Date()
|
||||
date.setMonth(monthYearArray[0])
|
||||
date.setYear(monthYearArray[1])
|
||||
return -date.getTime()
|
||||
|
||||
$scope.monthOrder = monthsOrder
|
||||
|
||||
|
||||
|
||||
|
@ -439,6 +439,15 @@ angular.module('application.router', ['ui.router']).
|
||||
templateUrl: '<%= asset_path "events/index.html" %>'
|
||||
controller: 'EventsController'
|
||||
resolve:
|
||||
categoriesPromise: ['Category', (Category) ->
|
||||
Category.query().$promise
|
||||
]
|
||||
themesPromise: ['EventTheme', (EventTheme) ->
|
||||
EventTheme.query().$promise
|
||||
]
|
||||
ageRangesPromise: ['AgeRange', (AgeRange) ->
|
||||
AgeRange.query().$promise
|
||||
]
|
||||
translations: [ 'Translations', (Translations) ->
|
||||
Translations.query('app.public.events_list').$promise
|
||||
]
|
||||
|
@ -20,38 +20,58 @@
|
||||
|
||||
<section class="m-lg">
|
||||
|
||||
<div ng-repeat="month in monthOrder">
|
||||
<h1>{{month.split(',')[0]}}, {{month.split(',')[1]}}</h1>
|
||||
<div class="row m-b-md">
|
||||
<div class="col-md-3 m-b">
|
||||
<select ng-model="filters.category_id" ng-change="filterEvents()" class="form-control" ng-options="c.id as c.name for c in categories">
|
||||
<option value="" translate>{{ 'all_categories' }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="row" ng-repeat="event in (eventsGroupByMonth[month].length/3 | array)">
|
||||
|
||||
<div class="col-xs-12 col-sm-6 col-md-4" ng-repeat="event in eventsGroupByMonth[month].slice(3*$index, 3*$index + 3)" ng-click="showEvent(event)">
|
||||
|
||||
|
||||
<a class="block bg-white img-full p-sm p-l-m box-h-m event b b-light-dark m-t-sm" ui-sref="app.public.events_show({id: event.id})">
|
||||
<div class="pull-left half-w m-t-n-sm">
|
||||
<h5 class="text-xs">{{event.categories[0].name}}</h5>
|
||||
<h4 class="m-n text-sm clear l-n">{{event.title}}</h4>
|
||||
<h3 class="m-n">{{event.start_date | amDateFormat:'L'}} <span class="text-sm font-thin" translate> {{ 'to_date' }} </span> {{event.end_date | amDateFormat:'L'}}</h3>
|
||||
|
||||
<h6 class="m-n" ng-if="event.amount">{{ 'full_price_' | translate }} {{event.amount | currency}} <span ng-if="event.reduced_amount > 0">/ {{ 'reduced_rate_' | translate }} {{event.reduced_amount | currency}}</span></h6>
|
||||
</div>
|
||||
<!-- Event Image -->
|
||||
<div class="pull-right crop-130">
|
||||
<img class="pull-right" ng-src="{{event.event_image_small}}" title="{{event.title}}" ng-if="event.event_image">
|
||||
<img class="pull-right img-responsive" src="data:image/png;base64," data-src="holder.js/100%x100%/text:/font:FontAwesome/icon" bs-holder ng-if="!event.event_image">
|
||||
</div>
|
||||
|
||||
</a>
|
||||
<div class="col-md-3 m-b">
|
||||
<select ng-model="filters.theme_id" ng-change="filterEvents()" class="form-control" ng-options="t.id as t.name for t in themes">
|
||||
<option value="" translate>{{ 'all_themes' }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3 m-b">
|
||||
<select ng-model="filters.age_range_id" ng-change="filterEvents()" class="form-control" ng-options="a.id as a.name for a in ageRanges">
|
||||
<option value="" translate>{{ 'for_all' }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-repeat="month in monthOrder">
|
||||
<h1>{{month.split(',')[0]}}, {{month.split(',')[1]}}</h1>
|
||||
|
||||
<div class="row" ng-repeat="event in (eventsGroupByMonth[month].length/3 | array)">
|
||||
|
||||
<div class="col-xs-12 col-sm-6 col-md-4" ng-repeat="event in eventsGroupByMonth[month].slice(3*$index, 3*$index + 3)" ng-click="showEvent(event)">
|
||||
|
||||
|
||||
<a class="block bg-white img-full p-sm p-l-m box-h-m event b b-light-dark m-t-sm" ui-sref="app.public.events_show({id: event.id})">
|
||||
<div class="pull-left half-w m-t-n-sm">
|
||||
<h5 class="text-xs">{{event.categories[0].name}}</h5>
|
||||
<h4 class="m-n text-sm clear l-n">{{event.title}}</h4>
|
||||
<h3 class="m-n">{{event.start_date | amDateFormat:'L'}} <span class="text-sm font-thin" translate> {{ 'to_date' }} </span> {{event.end_date | amDateFormat:'L'}}</h3>
|
||||
|
||||
<h6 class="m-n" ng-if="event.amount">{{ 'full_price_' | translate }} {{event.amount | currency}} <span ng-if="event.reduced_amount > 0">/ {{ 'reduced_rate_' | translate }} {{event.reduced_amount | currency}}</span></h6>
|
||||
</div>
|
||||
<!-- Event Image -->
|
||||
<div class="pull-right crop-130">
|
||||
<img class="pull-right" ng-src="{{event.event_image_small}}" title="{{event.title}}" ng-if="event.event_image">
|
||||
<img class="pull-right img-responsive" src="data:image/png;base64," data-src="holder.js/100%x100%/text:/font:FontAwesome/icon" bs-holder ng-if="!event.event_image">
|
||||
</div>
|
||||
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-lg-12 text-center m-t-md">
|
||||
<a class="btn btn-warning" ng-click="loadMoreEvents()" ng-if="paginateActive" translate>{{ 'load_the_next_events' }}</a>
|
||||
<a class="btn btn-warning" ng-click="loadMoreEvents()" ng-hide="noMoreResults" translate>{{ 'load_the_next_events' }}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -1,9 +1,8 @@
|
||||
class API::AgeRangesController < API::ApiController
|
||||
before_action :authenticate_user!
|
||||
before_action :authenticate_user!, except: [:index]
|
||||
before_action :set_age_range, only: [:show, :update, :destroy]
|
||||
|
||||
def index
|
||||
authorize AgeRange
|
||||
@age_ranges = AgeRange.all
|
||||
end
|
||||
|
||||
|
@ -1,9 +1,8 @@
|
||||
class API::CategoriesController < API::ApiController
|
||||
before_action :authenticate_user!
|
||||
before_action :authenticate_user!, except: [:index]
|
||||
before_action :set_category, only: [:show, :update, :destroy]
|
||||
|
||||
def index
|
||||
authorize Category
|
||||
@categories = Category.all
|
||||
end
|
||||
|
||||
|
@ -1,9 +1,8 @@
|
||||
class API::EventThemesController < API::ApiController
|
||||
before_action :authenticate_user!
|
||||
before_action :authenticate_user!, except: [:index]
|
||||
before_action :set_event_theme, only: [:show, :update, :destroy]
|
||||
|
||||
def index
|
||||
authorize EventTheme
|
||||
@event_themes = EventTheme.all
|
||||
end
|
||||
|
||||
|
@ -3,9 +3,16 @@ class API::EventsController < API::ApiController
|
||||
|
||||
def index
|
||||
@events = policy_scope(Event)
|
||||
@total = @events.count
|
||||
@page = params[:page]
|
||||
|
||||
# filters
|
||||
@events = @events.joins(:categories).where('categories.id = :category', category: params[:category_id]) if params[:category_id]
|
||||
@events = @events.joins(:event_themes).where('event_themes.id = :theme', theme: params[:theme_id]) if params[:theme_id]
|
||||
@events = @events.where('age_range_id = :age_range', age_range: params[:age_range_id]) if params[:age_range_id]
|
||||
|
||||
# paginate
|
||||
@events = @events.page(@page).per(12)
|
||||
|
||||
end
|
||||
|
||||
# GET /events/upcoming/:limit
|
||||
|
@ -1,5 +1,5 @@
|
||||
class AgeRangePolicy < ApplicationPolicy
|
||||
%w(index create update destroy show).each do |action|
|
||||
%w(create update destroy show).each do |action|
|
||||
define_method "#{action}?" do
|
||||
user.is_admin?
|
||||
end
|
||||
|
@ -1,5 +1,5 @@
|
||||
class CategoryPolicy < ApplicationPolicy
|
||||
%w(index create update destroy show).each do |action|
|
||||
%w(create update destroy show).each do |action|
|
||||
define_method "#{action}?" do
|
||||
user.is_admin?
|
||||
end
|
||||
|
@ -1,5 +1,5 @@
|
||||
class EventThemePolicy < ApplicationPolicy
|
||||
%w(index create update destroy show).each do |action|
|
||||
%w(create update destroy show).each do |action|
|
||||
define_method "#{action}?" do
|
||||
user.is_admin?
|
||||
end
|
||||
|
@ -1,8 +1,10 @@
|
||||
total = @events.count
|
||||
|
||||
json.cache! [@events, @page] do
|
||||
json.array!(@events) do |event|
|
||||
json.partial! 'api/events/event', event: event
|
||||
json.event_image_small event.event_image.attachment.small.url if event.event_image
|
||||
json.url event_url(event, format: :json)
|
||||
json.nb_total_events @total
|
||||
json.nb_total_events total
|
||||
end
|
||||
end
|
||||
|
@ -1,7 +1,7 @@
|
||||
maxInvoices = @invoices.except(:offset, :limit, :order).count
|
||||
max_invoices = @invoices.except(:offset, :limit, :order).count
|
||||
|
||||
json.array!(@invoices) do |invoice|
|
||||
json.maxInvoices maxInvoices
|
||||
json.maxInvoices max_invoices
|
||||
json.extract! invoice, :id, :created_at, :reference, :invoiced_type, :user_id, :avoir_date
|
||||
json.total (invoice.total / 100.00)
|
||||
json.url invoice_url(invoice, format: :json)
|
||||
|
@ -1,8 +1,8 @@
|
||||
user_is_admin = (current_user and current_user.is_admin?)
|
||||
maxMembers = @query.except(:offset, :limit, :order).count
|
||||
max_members = @query.except(:offset, :limit, :order).count
|
||||
|
||||
json.array!(@members) do |member|
|
||||
json.maxMembers maxMembers
|
||||
json.maxMembers max_members
|
||||
json.id member.id
|
||||
json.username member.username
|
||||
json.slug member.slug
|
||||
|
@ -1,7 +1,7 @@
|
||||
maxMembers = @query.except(:offset, :limit, :order).count
|
||||
max_members = @query.except(:offset, :limit, :order).count
|
||||
|
||||
json.array!(@members) do |member|
|
||||
json.maxMembers maxMembers
|
||||
json.maxMembers max_members
|
||||
json.id member.id
|
||||
json.email member.email if current_user
|
||||
json.profile do
|
||||
|
@ -132,7 +132,6 @@ en:
|
||||
my_projects: "My projects"
|
||||
projects_to_whom_i_take_part_in: "Projects to whom I take part in"
|
||||
all_machines: "All machines"
|
||||
all_themes: "All themes"
|
||||
all_materials: "All materials"
|
||||
load_next_projects: "Load next projects"
|
||||
|
||||
@ -200,6 +199,8 @@ en:
|
||||
events_list:
|
||||
# Fablab's events list
|
||||
the_fablab_s_events: "The Fablab's events"
|
||||
all_categories: "All categories"
|
||||
for_all: "For all"
|
||||
|
||||
events_show:
|
||||
# details and booking of an event
|
||||
|
@ -132,7 +132,6 @@ fr:
|
||||
my_projects: "Mes projets"
|
||||
projects_to_whom_i_take_part_in: "Les projets auxquels je collabore"
|
||||
all_machines: "Toutes les machines"
|
||||
all_themes: "Toutes les thématiques"
|
||||
all_materials: "Tous les matériaux"
|
||||
load_next_projects: "Charger les projets suivants"
|
||||
|
||||
@ -200,6 +199,8 @@ fr:
|
||||
events_list:
|
||||
# liste des évènements du fablab
|
||||
the_fablab_s_events: "Les évènements du Fab Lab"
|
||||
all_categories: "Toutes les catégories"
|
||||
for_all: "Tout public"
|
||||
|
||||
events_show:
|
||||
# détails d'un événement et réservation
|
||||
|
@ -87,6 +87,7 @@ en:
|
||||
_click_on_the_synchronization_button_opposite_: "click on the synchronization button opposite"
|
||||
_disconnect_then_reconnect_: "disconnect then reconnect"
|
||||
_for_your_changes_to_take_effect: "for your changes to take effect."
|
||||
all_themes: "All themes"
|
||||
|
||||
messages:
|
||||
you_will_lose_any_unsaved_modification_if_you_quit_this_page: "You will lose any unsaved modification if you quit this page"
|
||||
|
@ -87,6 +87,7 @@ fr:
|
||||
_click_on_the_synchronization_button_opposite_: "cliquez sur le bouton de synchronisation ci-contre"
|
||||
_disconnect_then_reconnect_: "déconnectez-vous puis re-connectez vous"
|
||||
_for_your_changes_to_take_effect: "pour que les modifications soient prises en compte."
|
||||
all_themes: "Toutes les thématiques"
|
||||
|
||||
messages:
|
||||
you_will_lose_any_unsaved_modification_if_you_quit_this_page: "Vous perdrez les modifications non enregistrées si vous quittez cette page"
|
||||
|
Loading…
x
Reference in New Issue
Block a user