mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-02-19 13:54:25 +01:00
Merge branch 'events' into dev
Conflicts: CHANGELOG.md config/locales/app.shared.en.yml config/locales/app.shared.fr.yml
This commit is contained in:
commit
6839e8db38
@ -10,6 +10,11 @@
|
||||
- Public gallery of trainings with ability to view details or to book a training on its own calendar
|
||||
- Ability to switch back to all trainings booking view
|
||||
- Fix a bug: project drafts are shown on public profiles
|
||||
- Admin: Events can be associated with a theme and an age range
|
||||
- Admin: Event categories, themes and age ranges can be customized
|
||||
- Filter events by category, theme and age range in public view
|
||||
- Statistics will include informations abouts events category, theme and age range
|
||||
- [TODO DEPLOY] `rake fablab:es_add_event_filters`
|
||||
- [TODO DEPLOY] `rake db:migrate`
|
||||
|
||||
## v2.3.0 2016 June 28
|
||||
@ -27,7 +32,7 @@
|
||||
## v2.2.2 2016 June 23
|
||||
- Fix some bugs: users with uncompleted account (sso imported) won't appear in statistics, in listings and in searches. Moreover, they won't block statistics generation
|
||||
- Fix a bug: unable to display next results in statistics tables
|
||||
- Admin: Category is mandatory when creating a course/workshop (event)
|
||||
- Admin: Category is mandatory when creating an event
|
||||
|
||||
## v2.2.1 2016 June 22
|
||||
- Fix a bug: field User.merged_at should not be allowed to be mapped in SSO
|
||||
|
@ -7,7 +7,6 @@
|
||||
# in the various events' admin controllers.
|
||||
#
|
||||
# Provides :
|
||||
# - $scope.categories = [{Category}]
|
||||
# - $scope.datePicker = {}
|
||||
# - $scope.submited(content)
|
||||
# - $scope.cancel()
|
||||
@ -23,13 +22,7 @@
|
||||
# - $state (Ui-Router) [ 'app.public.events_list' ]
|
||||
##
|
||||
class EventsController
|
||||
constructor: ($scope, $state, Event, Category) ->
|
||||
|
||||
## Retrieve the list of categories from the server (stage, atelier, ...)
|
||||
Category.query().$promise.then (data)->
|
||||
$scope.categories = data.map (d) ->
|
||||
id: d.id
|
||||
name: d.name
|
||||
constructor: ($scope, $state) ->
|
||||
|
||||
## default parameters for AngularUI-Bootstrap datepicker
|
||||
$scope.datePicker =
|
||||
@ -136,7 +129,8 @@ class EventsController
|
||||
##
|
||||
# Controller used in the events listing page (admin view)
|
||||
##
|
||||
Application.Controllers.controller "AdminEventsController", ["$scope", "$state", 'Event', 'eventsPromise', ($scope, $state, Event, eventsPromise) ->
|
||||
Application.Controllers.controller "AdminEventsController", ["$scope", "$state", 'dialogs', 'growl', 'Event', 'Category', 'EventTheme', 'AgeRange', 'eventsPromise', 'categoriesPromise', 'themesPromise', 'ageRangesPromise', '_t'
|
||||
, ($scope, $state, dialogs, growl, Event, Category, EventTheme, AgeRange, eventsPromise, categoriesPromise, themesPromise, ageRangesPromise, _t) ->
|
||||
|
||||
|
||||
|
||||
@ -151,6 +145,21 @@ Application.Controllers.controller "AdminEventsController", ["$scope", "$state",
|
||||
## Current virtual page
|
||||
$scope.page = 2
|
||||
|
||||
## Temporary datastore for creating new elements
|
||||
$scope.inserted =
|
||||
category: null
|
||||
theme: null
|
||||
age_range: null
|
||||
|
||||
## List of categories for the events
|
||||
$scope.categories = categoriesPromise
|
||||
|
||||
## List of events themes
|
||||
$scope.themes = themesPromise
|
||||
|
||||
## List of age ranges
|
||||
$scope.ageRanges = ageRangesPromise
|
||||
|
||||
##
|
||||
# Adds a bucket of events to the bottom of the page, grouped by month
|
||||
##
|
||||
@ -161,6 +170,71 @@ Application.Controllers.controller "AdminEventsController", ["$scope", "$state",
|
||||
$scope.page += 1
|
||||
|
||||
|
||||
##
|
||||
# Saves a new element / Update an existing one to the server (form validation callback)
|
||||
# @param model {string} model name
|
||||
# @param data {Object} element name
|
||||
# @param [id] {number} element id, in case of update
|
||||
##
|
||||
$scope.saveElement = (model, data, id) ->
|
||||
if id?
|
||||
getModel(model)[0].update {id: id}, data
|
||||
else
|
||||
getModel(model)[0].save data, (resp)->
|
||||
getModel(model)[1][getModel(model)[1].length-1].id = resp.id
|
||||
|
||||
|
||||
|
||||
##
|
||||
# Deletes the element at the specified index
|
||||
# @param model {string} model name
|
||||
# @param index {number} element index in the $scope[model] array
|
||||
##
|
||||
$scope.removeElement = (model, index) ->
|
||||
if model == 'category' and getModel(model)[1].length == 1
|
||||
growl.error(_t('at_least_one_category_is_required')+' '+_t('unable_to_delete_the_last_one'))
|
||||
return false
|
||||
if getModel(model)[1][index].related_to > 0
|
||||
growl.error(_t('unable_to_delete_ELEMENT_already_in_use_NUMBER_times', {ELEMENT:model, NUMBER:getModel(model)[1][index].related_to}, "messageformat"))
|
||||
return false
|
||||
dialogs.confirm
|
||||
resolve:
|
||||
object: ->
|
||||
title: _t('confirmation_required')
|
||||
msg: _t('do_you_really_want_to_delete_this_ELEMENT', {ELEMENT:model}, "messageformat")
|
||||
, -> # delete confirmed
|
||||
getModel(model)[0].delete getModel(model)[1][index], null, ->
|
||||
getModel(model)[1].splice(index, 1)
|
||||
, ->
|
||||
growl.error(_t('unable_to_delete_an_error_occured'))
|
||||
|
||||
|
||||
|
||||
##
|
||||
# Creates a new empty entry in the $scope[model] array
|
||||
# @param model {string} model name
|
||||
##
|
||||
$scope.addElement = (model) ->
|
||||
$scope.inserted[model] =
|
||||
name: ''
|
||||
related_to: 0
|
||||
getModel(model)[1].push($scope.inserted[model])
|
||||
|
||||
|
||||
|
||||
##
|
||||
# Removes the newly inserted but not saved element / Cancel the current element modification
|
||||
# @param model {string} model name
|
||||
# @param rowform {Object} see http://vitalets.github.io/angular-xeditable/
|
||||
# @param index {number} element index in the $scope[model] array
|
||||
##
|
||||
$scope.cancelElement = (model, rowform, index) ->
|
||||
if getModel(model)[1][index].id?
|
||||
rowform.$cancel()
|
||||
else
|
||||
getModel(model)[1].splice(index, 1)
|
||||
|
||||
|
||||
|
||||
### PRIVATE SCOPE ###
|
||||
|
||||
@ -183,6 +257,17 @@ Application.Controllers.controller "AdminEventsController", ["$scope", "$state",
|
||||
else
|
||||
$scope.paginateActive = false
|
||||
|
||||
##
|
||||
# Return the model and the datastore matching the given name
|
||||
# @param name {string} 'category', 'theme' or 'age_range'
|
||||
# @return {[Object, Array]} model and datastore
|
||||
##
|
||||
getModel = (name) ->
|
||||
switch name
|
||||
when 'category' then [Category, $scope.categories]
|
||||
when 'theme' then [EventTheme, $scope.themes]
|
||||
when 'age_range' then [AgeRange, $scope.ageRanges]
|
||||
else [null, []]
|
||||
|
||||
|
||||
# init the controller (call at the end !)
|
||||
@ -209,8 +294,8 @@ Application.Controllers.controller "ShowEventReservationsController", ["$scope",
|
||||
##
|
||||
# Controller used in the event creation page
|
||||
##
|
||||
Application.Controllers.controller "NewEventController", ["$scope", "$state", "$locale", 'Event', 'Category', 'CSRF', '_t'
|
||||
, ($scope, $state, $locale, Event, Category, CSRF, _t) ->
|
||||
Application.Controllers.controller "NewEventController", ["$scope", "$state", "$locale", 'CSRF', 'categoriesPromise', 'themesPromise', 'ageRangesPromise', '_t'
|
||||
, ($scope, $state, $locale, CSRF, categoriesPromise, themesPromise, ageRangesPromise, _t) ->
|
||||
CSRF.setMetaTags()
|
||||
|
||||
## API URL where the form will be posted
|
||||
@ -219,6 +304,15 @@ Application.Controllers.controller "NewEventController", ["$scope", "$state", "$
|
||||
## Form action on the above URL
|
||||
$scope.method = 'post'
|
||||
|
||||
## List of categories for the events
|
||||
$scope.categories = categoriesPromise
|
||||
|
||||
## List of events themes
|
||||
$scope.themes = themesPromise
|
||||
|
||||
## List of age ranges
|
||||
$scope.ageRanges = ageRangesPromise
|
||||
|
||||
## Default event parameters
|
||||
$scope.event =
|
||||
event_files_attributes: []
|
||||
@ -243,7 +337,7 @@ Application.Controllers.controller "NewEventController", ["$scope", "$state", "$
|
||||
$scope.currencySymbol = $locale.NUMBER_FORMATS.CURRENCY_SYM;
|
||||
|
||||
## Using the EventsController
|
||||
new EventsController($scope, $state, Event, Category)
|
||||
new EventsController($scope, $state)
|
||||
]
|
||||
|
||||
|
||||
@ -251,8 +345,8 @@ Application.Controllers.controller "NewEventController", ["$scope", "$state", "$
|
||||
##
|
||||
# Controller used in the events edition page
|
||||
##
|
||||
Application.Controllers.controller "EditEventController", ["$scope", "$state", "$stateParams", "$locale", 'Event', 'Category', 'CSRF', 'eventPromise'
|
||||
, ($scope, $state, $stateParams, $locale, Event, Category, CSRF, eventPromise) ->
|
||||
Application.Controllers.controller "EditEventController", ["$scope", "$state", "$stateParams", "$locale", 'CSRF', 'eventPromise', 'categoriesPromise', 'themesPromise', 'ageRangesPromise'
|
||||
, ($scope, $state, $stateParams, $locale, CSRF, eventPromise, categoriesPromise, themesPromise, ageRangesPromise) ->
|
||||
|
||||
### PUBLIC SCOPE ###
|
||||
|
||||
@ -270,6 +364,15 @@ Application.Controllers.controller "EditEventController", ["$scope", "$state", "
|
||||
## currency symbol for the current locale (cf. angular-i18n)
|
||||
$scope.currencySymbol = $locale.NUMBER_FORMATS.CURRENCY_SYM;
|
||||
|
||||
## List of categories for the events
|
||||
$scope.categories = categoriesPromise
|
||||
|
||||
## List of events themes
|
||||
$scope.themes = themesPromise
|
||||
|
||||
## List of age ranges
|
||||
$scope.ageRanges = ageRangesPromise
|
||||
|
||||
|
||||
|
||||
### PRIVATE SCOPE ###
|
||||
@ -287,7 +390,7 @@ Application.Controllers.controller "EditEventController", ["$scope", "$state", "
|
||||
$scope.event.end_date = moment($scope.event.end_date).toDate()
|
||||
|
||||
## Using the EventsController
|
||||
new EventsController($scope, $state, Event, Category)
|
||||
new EventsController($scope, $state)
|
||||
|
||||
|
||||
|
||||
|
@ -334,7 +334,7 @@ Application.Controllers.controller "GraphsController", ["$scope", "$state", "$ro
|
||||
callback(results)
|
||||
recursiveCb()
|
||||
else # palmares (ranking)
|
||||
queryElasticRanking index.es_type_key, $scope.ranking.groupCriterion, $scope.ranking.sortCriterion, index.graph.limit, (results, error) ->
|
||||
queryElasticRanking index.es_type_key, $scope.ranking.groupCriterion, $scope.ranking.sortCriterion, (results, error) ->
|
||||
if (error)
|
||||
callback([], error)
|
||||
else
|
||||
@ -373,17 +373,18 @@ Application.Controllers.controller "GraphsController", ["$scope", "$state", "$ro
|
||||
|
||||
##
|
||||
# For ranking displays, run the elasticSearch query to retreive the /stats/type aggregations
|
||||
# @param esType {String} elasticSearch document type (subscription|machine|training|...)
|
||||
# @param statType {String} statistics type (year|month|hour|booking|...)
|
||||
# @param esType {string} elasticSearch document type (subscription|machine|training|...)
|
||||
# @param groupKey {string} statistics subtype or custom field
|
||||
# @param sortKey {string} statistics type or 'ca'
|
||||
# @param callback {function} function be to run after results were retrieved,
|
||||
# it will receive two parameters : results {Array}, error {String} (if any)
|
||||
##
|
||||
queryElasticRanking = (esType, groupKey, sortKey, limit, callback) ->
|
||||
queryElasticRanking = (esType, groupKey, sortKey, callback) ->
|
||||
# handle invalid callback
|
||||
if typeof(callback) != "function"
|
||||
console.error('[graphsController::queryElasticRanking] Error: invalid callback provided')
|
||||
return
|
||||
if !esType or !groupKey or !sortKey or typeof limit != 'number'
|
||||
if !esType or !groupKey or !sortKey
|
||||
callback([], '[graphsController::queryElasticRanking] Error: invalid parameters provided')
|
||||
|
||||
# run query
|
||||
|
@ -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,40 @@ 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
|
||||
|
||||
## Hide or show the 'load more' button
|
||||
$scope.noMoreResults = false
|
||||
|
||||
## 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($scope.events)
|
||||
$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 +56,69 @@ 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 = []
|
||||
$scope.noMoreResults = false
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
|
||||
##
|
||||
# Test if the provided event occurs on a single day or on many days
|
||||
# @param event {{start_date:Date, end_date:Date}} Event object as retreived from the API
|
||||
# @return {boolean} false if the event occurs on many days
|
||||
##
|
||||
$scope.onSingleDay = (event) ->
|
||||
moment(event.start_date).isSame(event.end_date, 'day')
|
||||
|
||||
|
||||
|
||||
### 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
|
||||
|
||||
|
||||
|
||||
@ -353,7 +410,7 @@ Application.Controllers.controller "ShowEventController", ["$scope", "$state", "
|
||||
# Create an hash map implementing the Reservation specs
|
||||
# @param member {Object} User as retreived from the API: current user / selected user if current is admin
|
||||
# @param reserve {Object} Reservation parameters (places...)
|
||||
# @param event {Object} Current event (Atelier/Stage)
|
||||
# @param event {Object} Current event
|
||||
# @return {{user_id:Number, reservable_id:Number, reservable_type:String, slots_attributes:Array<Object>, nb_reserve_places:Number, nb_reserve_reduced_places:Number}}
|
||||
##
|
||||
mkReservation = (member, reserve, event) ->
|
||||
|
@ -25,7 +25,7 @@ Application.Controllers.controller "MainNavController", ["$scope", "$location",
|
||||
}
|
||||
{
|
||||
state: 'app.public.events_list'
|
||||
linkText: 'courses_and_workshops_registrations'
|
||||
linkText: 'events_registrations'
|
||||
linkIcon: 'tags'
|
||||
}
|
||||
{
|
||||
@ -73,7 +73,7 @@ Application.Controllers.controller "MainNavController", ["$scope", "$location",
|
||||
}
|
||||
{
|
||||
state: 'app.admin.events'
|
||||
linkText: 'courses_and_workshops_monitoring'
|
||||
linkText: 'manage_the_events'
|
||||
linkIcon: 'tags'
|
||||
}
|
||||
{
|
||||
|
@ -468,6 +468,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
|
||||
]
|
||||
@ -591,6 +600,15 @@ angular.module('application.router', ['ui.router']).
|
||||
eventsPromise: ['Event', (Event)->
|
||||
Event.query(page: 1).$promise
|
||||
]
|
||||
categoriesPromise: ['Category', (Category) ->
|
||||
Category.query().$promise
|
||||
]
|
||||
themesPromise: ['EventTheme', (EventTheme) ->
|
||||
EventTheme.query().$promise
|
||||
]
|
||||
ageRangesPromise: ['AgeRange', (AgeRange) ->
|
||||
AgeRange.query().$promise
|
||||
]
|
||||
translations: [ 'Translations', (Translations) ->
|
||||
Translations.query('app.admin.events').$promise
|
||||
]
|
||||
@ -601,6 +619,15 @@ angular.module('application.router', ['ui.router']).
|
||||
templateUrl: '<%= asset_path "events/new.html" %>'
|
||||
controller: 'NewEventController'
|
||||
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.admin.events_new', 'app.shared.event']).$promise
|
||||
]
|
||||
@ -614,6 +641,15 @@ angular.module('application.router', ['ui.router']).
|
||||
eventPromise: ['Event', '$stateParams', (Event, $stateParams)->
|
||||
Event.get(id: $stateParams.id).$promise
|
||||
]
|
||||
categoriesPromise: ['Category', (Category) ->
|
||||
Category.query().$promise
|
||||
]
|
||||
themesPromise: ['EventTheme', (EventTheme) ->
|
||||
EventTheme.query().$promise
|
||||
]
|
||||
ageRangesPromise: ['AgeRange', (AgeRange) ->
|
||||
AgeRange.query().$promise
|
||||
]
|
||||
translations: [ 'Translations', (Translations) ->
|
||||
Translations.query(['app.admin.events_edit', 'app.shared.event']).$promise
|
||||
]
|
||||
|
8
app/assets/javascripts/services/age_range.coffee
Normal file
8
app/assets/javascripts/services/age_range.coffee
Normal file
@ -0,0 +1,8 @@
|
||||
'use strict'
|
||||
|
||||
Application.Services.factory 'AgeRange', ["$resource", ($resource)->
|
||||
$resource "/api/age_ranges/:id",
|
||||
{id: "@id"},
|
||||
update:
|
||||
method: 'PUT'
|
||||
]
|
8
app/assets/javascripts/services/event_theme.coffee
Normal file
8
app/assets/javascripts/services/event_theme.coffee
Normal file
@ -0,0 +1,8 @@
|
||||
'use strict'
|
||||
|
||||
Application.Services.factory 'EventTheme', ["$resource", ($resource)->
|
||||
$resource "/api/event_themes/:id",
|
||||
{id: "@id"},
|
||||
update:
|
||||
method: 'PUT'
|
||||
]
|
@ -154,8 +154,11 @@
|
||||
}
|
||||
|
||||
.article-thumbnail {
|
||||
// max-height: 400px;
|
||||
overflow: hidden;
|
||||
|
||||
img {
|
||||
height: 400px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -417,6 +420,7 @@
|
||||
|
||||
.event {
|
||||
transition: all 0.07s linear;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.event:hover {
|
||||
@ -431,8 +435,8 @@ border-color: #eee;
|
||||
}
|
||||
|
||||
.box-h-m {
|
||||
height: 150px;
|
||||
max-height: 150px;
|
||||
height: 175px;
|
||||
max-height: 175px;
|
||||
}
|
||||
|
||||
.half-w {
|
||||
@ -446,25 +450,31 @@ border-color: #d0d0d0;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.crop-130 {
|
||||
height: 130px;
|
||||
width: 130px;
|
||||
max-width: 130px;
|
||||
max-height: 130px;
|
||||
.crop-155 {
|
||||
height: 155px;
|
||||
width: 155px;
|
||||
max-width: 155px;
|
||||
max-height: 155px;
|
||||
overflow: hidden;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
.crop-130 img {
|
||||
height: 130px;
|
||||
.crop-155 img {
|
||||
height: 155px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1280px) and (min-width: 770px) {
|
||||
.crop-130 {
|
||||
@media only screen and (max-width: 1375px) and (min-width: 770px) {
|
||||
.crop-155 {
|
||||
height: 90px;
|
||||
width: 90px;
|
||||
margin-top: 25px;
|
||||
margin-top: 35px;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1375px) and (min-width: 1125px) {
|
||||
.half-w {
|
||||
width: 60%;
|
||||
}
|
||||
}
|
||||
|
||||
|
120
app/assets/templates/admin/events/filters.html.erb
Normal file
120
app/assets/templates/admin/events/filters.html.erb
Normal file
@ -0,0 +1,120 @@
|
||||
<div class="m-t">
|
||||
<h3 translate>{{ 'categories' }}</h3>
|
||||
<p translate>{{ 'at_least_one_category_is_required' }}</p>
|
||||
<button type="button" class="btn btn-warning m-b m-t" ng-click="addElement('category')" translate>{{ 'add_a_category' }}</button>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:80%" translate>{{ 'name' }}</th>
|
||||
<th style="width:20%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="category in categories">
|
||||
<td>
|
||||
<span editable-text="category.name" e-cols="100" e-name="name" e-form="rowform" e-required>
|
||||
{{ category.name }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<!-- form -->
|
||||
<form editable-form name="rowform" onbeforesave="saveElement('category', $data, category.id)" ng-show="rowform.$visible" class="form-buttons form-inline" shown="inserted.category == category">
|
||||
<button type="submit" ng-disabled="rowform.$waiting" class="btn btn-warning">
|
||||
<i class="fa fa-check"></i>
|
||||
</button>
|
||||
<button type="button" ng-disabled="rowform.$waiting" ng-click="cancelElement('category', rowform, $index)" class="btn btn-default">
|
||||
<i class="fa fa-times"></i>
|
||||
</button>
|
||||
</form>
|
||||
<div class="buttons" ng-show="!rowform.$visible">
|
||||
<button class="btn btn-default" ng-click="rowform.$show()">
|
||||
<i class="fa fa-edit"></i> <span class="hidden-xs hidden-sm" translate>{{ 'edit' }}</span>
|
||||
</button>
|
||||
<button class="btn btn-danger" ng-click="removeElement('category', $index)">
|
||||
<i class="fa fa-trash-o"></i>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h3 translate>{{ 'themes' }}</h3>
|
||||
<button type="button" class="btn btn-warning m-b m-t" ng-click="addElement('theme')" translate>{{ 'add_a_theme' }}</button>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:80%" translate>{{ 'name' }}</th>
|
||||
<th style="width:20%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="theme in themes">
|
||||
<td>
|
||||
<span editable-text="theme.name" e-cols="100" e-name="name" e-form="rowform" e-required>
|
||||
{{ theme.name }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<!-- form -->
|
||||
<form editable-form name="rowform" onbeforesave="saveElement('theme', $data, theme.id)" ng-show="rowform.$visible" class="form-buttons form-inline" shown="inserted.theme == theme">
|
||||
<button type="submit" ng-disabled="rowform.$waiting" class="btn btn-warning">
|
||||
<i class="fa fa-check"></i>
|
||||
</button>
|
||||
<button type="button" ng-disabled="rowform.$waiting" ng-click="cancelElement('theme', rowform, $index)" class="btn btn-default">
|
||||
<i class="fa fa-times"></i>
|
||||
</button>
|
||||
</form>
|
||||
<div class="buttons" ng-show="!rowform.$visible">
|
||||
<button class="btn btn-default" ng-click="rowform.$show()">
|
||||
<i class="fa fa-edit"></i> <span class="hidden-xs hidden-sm" translate>{{ 'edit' }}</span>
|
||||
</button>
|
||||
<button class="btn btn-danger" ng-click="removeElement('theme', $index)">
|
||||
<i class="fa fa-trash-o"></i>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h3 translate>{{ 'age_ranges' }}</h3>
|
||||
<button type="button" class="btn btn-warning m-b m-t" ng-click="addElement('age_range')" translate>{{ 'add_a_range' }}</button>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:80%" translate>{{ 'name' }}</th>
|
||||
<th style="width:20%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="range in ageRanges">
|
||||
<td>
|
||||
<span editable-text="range.name" e-cols="100" e-name="name" e-form="rowform" e-required>
|
||||
{{ range.name }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<!-- form -->
|
||||
<form editable-form name="rowform" onbeforesave="saveElement('age_range', $data, range.id)" ng-show="rowform.$visible" class="form-buttons form-inline" shown="inserted.age_range == range">
|
||||
<button type="submit" ng-disabled="rowform.$waiting" class="btn btn-warning">
|
||||
<i class="fa fa-check"></i>
|
||||
</button>
|
||||
<button type="button" ng-disabled="rowform.$waiting" ng-click="cancelElement('age_range', rowform, $index)" class="btn btn-default">
|
||||
<i class="fa fa-times"></i>
|
||||
</button>
|
||||
</form>
|
||||
<div class="buttons" ng-show="!rowform.$visible">
|
||||
<button class="btn btn-default" ng-click="rowform.$show()">
|
||||
<i class="fa fa-edit"></i> <span class="hidden-xs hidden-sm" translate>{{ 'edit' }}</span>
|
||||
</button>
|
||||
<button class="btn btn-danger" ng-click="removeElement('age_range', $index)">
|
||||
<i class="fa fa-trash-o"></i>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
@ -7,7 +7,7 @@
|
||||
</div>
|
||||
<div class="col-xs-10 col-sm-10 col-md-8 b-l b-r-md">
|
||||
<section class="heading-title">
|
||||
<h1 translate>{{ 'fablab_courses_and_workshops' }}</h1>
|
||||
<h1 translate>{{ 'fablab_events' }}</h1>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@ -21,57 +21,66 @@
|
||||
<section class="m-lg">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<uib-tabset justified="true">
|
||||
<uib-tab heading="{{ 'events_monitoring' | translate }}">
|
||||
|
||||
<div class="col-md-6 m-b">
|
||||
<select ng-model="selectedTimezone" class="form-control">
|
||||
<option value="" translate>{{ 'all_events' }}</option>
|
||||
<option value="passed" translate>{{ 'passed_events' }}</option>
|
||||
<option value="future" translate>{{ 'events_to_come' }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6 m-b m-t">
|
||||
<select ng-model="selectedTimezone" class="form-control">
|
||||
<option value="" translate>{{ 'all_events' }}</option>
|
||||
<option value="passed" translate>{{ 'passed_events' }}</option>
|
||||
<option value="future" translate>{{ 'events_to_come' }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:30%" translate>{{ 'title' }}</th>
|
||||
<th style="width:30%" translate>{{ 'dates' }}</th>
|
||||
<th style="width:40%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="event in filtered = (events | eventsReservationsFilter:selectedTimezone)">
|
||||
<td>
|
||||
<a ui-sref="app.public.events_show({id: event.id})">{{ event.title }} </a>
|
||||
</td>
|
||||
<td>
|
||||
<span> {{ 'from_DATE' | translate:{DATE:(event.start_date | amDateFormat:'LL')} }} <span class="text-sm font-thin" translate>{{ 'to_date' }}</span> {{event.end_date | amDateFormat:'LL'}}</span>
|
||||
<br/>
|
||||
<span ng-if="event.all_day == 'true'" translate>{{ 'all_day' }}</span>
|
||||
<span ng-if="event.all_day == 'false'">
|
||||
{{ 'from_TIME' | translate:{TIME:(event.start_date | amDateFormat:'LT')} }}
|
||||
<span class="text-sm font-thin" translate>{{ 'to_time' }}</span>
|
||||
{{event.end_date | amDateFormat:'LT'}}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<div class="buttons">
|
||||
<button class="btn btn-default" ui-sref="app.admin.event_reservations({id: event.id})">
|
||||
<i class="fa fa-bookmark"></i> {{ 'view_reservations' | translate }}
|
||||
</button>
|
||||
<button class="btn btn-default" ui-sref="app.admin.events_edit({id: event.id})">
|
||||
<i class="fa fa-edit"></i> {{ 'edit' | translate }}
|
||||
</button>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:30%" translate>{{ 'title' }}</th>
|
||||
<th style="width:30%" translate>{{ 'dates' }}</th>
|
||||
<th style="width:40%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="event in filtered = (events | eventsReservationsFilter:selectedTimezone)">
|
||||
<td>
|
||||
<a ui-sref="app.public.events_show({id: event.id})">{{ event.title }} </a>
|
||||
</td>
|
||||
<td>
|
||||
<span> {{ 'from_DATE' | translate:{DATE:(event.start_date | amDateFormat:'LL')} }} <span class="text-sm font-thin" translate>{{ 'to_date' }}</span> {{event.end_date | amDateFormat:'LL'}}</span>
|
||||
<br/>
|
||||
<span ng-if="event.all_day == 'true'" translate>{{ 'all_day' }}</span>
|
||||
<span ng-if="event.all_day == 'false'">
|
||||
{{ 'from_TIME' | translate:{TIME:(event.start_date | amDateFormat:'LT')} }}
|
||||
<span class="text-sm font-thin" translate>{{ 'to_time' }}</span>
|
||||
{{event.end_date | amDateFormat:'LT'}}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<div class="buttons">
|
||||
<button class="btn btn-default" ui-sref="app.admin.event_reservations({id: event.id})">
|
||||
<i class="fa fa-bookmark"></i> {{ 'view_reservations' | translate }}
|
||||
</button>
|
||||
<button class="btn btn-default" ui-sref="app.admin.events_edit({id: event.id})">
|
||||
<i class="fa fa-edit"></i> {{ 'edit' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<a class="btn btn-warning" ng-click="loadMoreEvents()" ng-if="paginateActive" translate>{{ 'load_the_next_events' }}</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</uib-tab>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<a class="btn btn-warning" ng-click="loadMoreEvents()" ng-if="paginateActive" translate>{{ 'load_the_next_courses_and_workshops' }}</a>
|
||||
|
||||
<uib-tab heading="{{ 'manage_filters' | translate }}">
|
||||
<ng-include src="'<%= asset_path 'admin/events/filters.html' %>'"></ng-include>
|
||||
</uib-tab>
|
||||
</uib-tabset>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
@ -138,11 +138,11 @@
|
||||
</div>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'courses_and_workshops' | translate }}">
|
||||
<uib-tab heading="{{ 'events' | translate }}">
|
||||
<div class="col-md-6">
|
||||
<div class="widget panel b-a m m-t-lg">
|
||||
<div class="panel-heading b-b">
|
||||
<h4 class="text-u-c"><i class="fa fa-tag m-r-xs"></i> {{ 'next_courses_and_workshops' | translate }}</h4>
|
||||
<h4 class="text-u-c"><i class="fa fa-tag m-r-xs"></i> {{ 'next_events' | translate }}</h4>
|
||||
</div>
|
||||
<div class="widget-content bg-light wrapper r-b">
|
||||
<ul class="list-unstyled" ng-if="user.events_reservations.length > 0">
|
||||
@ -158,14 +158,14 @@
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div ng-if="(user.events_reservations | eventsReservationsFilter:'future').length == 0" translate>{{ 'no_upcomning_courses_or_workshops'}}</div>
|
||||
<div ng-if="(user.events_reservations | eventsReservationsFilter:'future').length == 0" translate>{{ 'no_upcoming_events' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="widget panel b-a m m-t-lg">
|
||||
<div class="panel-heading b-b">
|
||||
<h4 class="text-u-c"><i class="fa fa-tag m-r-xs"></i> {{ 'passed_courses_and_workshops' | translate }}</h4>
|
||||
<h4 class="text-u-c"><i class="fa fa-tag m-r-xs"></i> {{ 'passed_events' | translate }}</h4>
|
||||
</div>
|
||||
<div class="widget-content bg-light auto wrapper r-b">
|
||||
<ul class="list-unstyled" ng-if="user.events_reservations.length > 0">
|
||||
@ -173,7 +173,7 @@
|
||||
<span class="font-sbold">{{r.reservable.title}}</span> - <span class="label label-info text-white wrapper-sm">{{ r.start_at | amDateFormat:'LLL' }} - {{ r.end_at | amDateFormat:'LT' }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div ng-if="(user.events_reservations | eventsReservationsFilter:'passed').length == 0" translate>{{ 'no_passed_courses_or_workshop' }}</div>
|
||||
<div ng-if="(user.events_reservations | eventsReservationsFilter:'passed').length == 0" translate>{{ 'no_passed_events' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -13,7 +13,7 @@
|
||||
<div class="col-md-6">
|
||||
<div class="widget panel b-a m m-t-lg">
|
||||
<div class="panel-heading b-b">
|
||||
<h4 class="text-u-c"><i class="fa fa-tag m-r-xs"></i> {{ 'your_next_courses_and_workshops' | translate }}</h4>
|
||||
<h4 class="text-u-c"><i class="fa fa-tag m-r-xs"></i> {{ 'your_next_events' | translate }}</h4>
|
||||
</div>
|
||||
<div class="widget-content bg-light wrapper r-b">
|
||||
<ul class="list-unstyled" ng-if="user.events_reservations.length > 0">
|
||||
@ -23,14 +23,14 @@
|
||||
<br/><span translate translate-values="{NUMBER: r.nb_reserve_reduced_places}" translate-interpolation="messageformat">{{ 'NUMBER_reduced_fare_places_reserved' }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div ng-if="(user.events_reservations | eventsReservationsFilter:'future').length == 0" translate>{{ 'no_courses_or_workshops_to_come' }}</div>
|
||||
<div ng-if="(user.events_reservations | eventsReservationsFilter:'future').length == 0" translate>{{ 'no_events_to_come' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="widget panel b-a m m-t-lg">
|
||||
<div class="panel-heading b-b">
|
||||
<h4 class="text-u-c"><i class="fa fa-tag m-r-xs"></i> {{ 'your_previous_courses_and_workshops' | translate }}</h4>
|
||||
<h4 class="text-u-c"><i class="fa fa-tag m-r-xs"></i> {{ 'your_previous_events' | translate }}</h4>
|
||||
</div>
|
||||
<div class="widget-content bg-light auto wrapper r-b">
|
||||
<ul class="list-unstyled" ng-if="user.events_reservations.length > 0">
|
||||
@ -38,7 +38,7 @@
|
||||
<span class="font-sbold">{{r.reservable.title}}</span> - <span class="label label-info text-white wrapper-sm">{{ r.start_at | amDateFormat:'LLL' }} - {{ r.end_at | amDateFormat:'LT' }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div ng-if="(user.events_reservations | eventsReservationsFilter:'passed').length == 0" translate>{{ 'no_passed_courses_or_workshops' }}</div>
|
||||
<div ng-if="(user.events_reservations | eventsReservationsFilter:'passed').length == 0" translate>{{ 'no_passed_events' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -14,7 +14,7 @@
|
||||
<li ui-sref-active="active"><a class="text-black" href="#" ui-sref="app.logged.dashboard.settings" translate>{{ 'my_settings' }}</a></li>
|
||||
<li ui-sref-active="active"><a class="text-black" href="#" ui-sref="app.logged.dashboard.projects" translate>{{ 'my_projects' }}</a></li>
|
||||
<li ui-sref-active="active"><a class="text-black" href="#" ui-sref="app.logged.dashboard.trainings" translate>{{ 'my_trainings' }}</a></li>
|
||||
<li ui-sref-active="active"><a class="text-black" href="#" ui-sref="app.logged.dashboard.events" translate>{{ 'my_courses_and_workshops' }}</a></li>
|
||||
<li ui-sref-active="active"><a class="text-black" href="#" ui-sref="app.logged.dashboard.events" translate>{{ 'my_events' }}</a></li>
|
||||
<li ui-sref-active="active"><a class="text-black" href="#" ui-sref="app.logged.dashboard.invoices" translate>{{ 'my_invoices' }}</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
@ -80,7 +80,7 @@
|
||||
|
||||
<div class="widget panel b-a m m-t-lg">
|
||||
<div class="panel-heading b-b small">
|
||||
<h3 translate>{{ 'event_type' }}</h3>
|
||||
<h3 translate>{{ 'event_type' }} *</h3>
|
||||
</div>
|
||||
<div class="widget-content no-bg wrapper">
|
||||
<input type="hidden" name="event[category_ids][]" value="" />
|
||||
@ -96,6 +96,40 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="widget panel b-a m m-t-lg" ng-show="themes.length > 0">
|
||||
<div class="panel-heading b-b small">
|
||||
<h3 translate>{{ 'event_theme' }}</h3>
|
||||
</div>
|
||||
<div class="widget-content no-bg wrapper">
|
||||
<input type="hidden" name="event[event_theme_ids][]" value="" />
|
||||
<ui-select ng-model="event.event_theme_ids" name="event[event_theme_ids][]">
|
||||
<ui-select-match>
|
||||
<span ng-bind="$select.selected.name"></span>
|
||||
<input type="hidden" name="event[event_theme_ids][]" value="{{$select.selected.id}}" />
|
||||
</ui-select-match>
|
||||
<ui-select-choices repeat="t.id as t in (themes | filter: $select.search)">
|
||||
<span ng-bind-html="t.name | highlight: $select.search"></span>
|
||||
</ui-select-choices>
|
||||
</ui-select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="widget panel b-a m m-t-lg" ng-show="ageRanges.length > 0">
|
||||
<div class="panel-heading b-b small">
|
||||
<h3 translate>{{ 'age_range' }}</h3>
|
||||
</div>
|
||||
<div class="widget-content no-bg wrapper">
|
||||
<ui-select ng-model="event.age_range_id" name="event[age_range_id][]">
|
||||
<ui-select-match>
|
||||
<span ng-bind="$select.selected.name"></span>
|
||||
<input type="hidden" name="event[age_range_id]" value="{{$select.selected.id}}" />
|
||||
</ui-select-match>
|
||||
<ui-select-choices repeat="a.id as a in (ageRanges | filter: $select.search)">
|
||||
<span ng-bind-html="a.name | highlight: $select.search"></span>
|
||||
</ui-select-choices>
|
||||
</ui-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="widget panel b-a m m-t-lg">
|
||||
<div class="panel-heading b-b small">
|
||||
<h3 translate>{{ 'dates_and_opening_hours' }}</h3>
|
||||
|
@ -7,7 +7,7 @@
|
||||
</div>
|
||||
<div class="col-xs-10 col-sm-10 col-md-8 b-l b-r-md">
|
||||
<section class="heading-title">
|
||||
<h1 translate>{{ 'the_fablab_s_courses_and_workshops' }}</h1>
|
||||
<h1 translate>{{ 'the_fablab_s_events' }}</h1>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@ -20,38 +20,64 @@
|
||||
|
||||
<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" ng-show="categories.length > 0">
|
||||
<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" ng-show="themes.length > 0">
|
||||
<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" ng-show="ageRanges.length > 0">
|
||||
<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" ng-show="onSingleDay(event)">{{event.start_date | amDateFormat:'L'}}</h3>
|
||||
<h3 class="m-n" ng-hide="onSingleDay(event)">{{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>
|
||||
<span class="text-black-light text-xs" ng-if="event.event_themes[0]"><i class="fa fa-tags" aria-hidden="true"></i> {{event.event_themes[0].name}}</span>
|
||||
<span class="text-black-light text-xs" ng-if="event.age_range"><i class="fa fa-users" aria-hidden="true"></i> {{event.age_range.name}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Event Image -->
|
||||
<div class="pull-right crop-155">
|
||||
<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_courses_and_workshops' }}</a>
|
||||
<a class="btn btn-warning" ng-click="loadMoreEvents()" ng-hide="noMoreResults" translate>{{ 'load_the_next_events' }}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -69,7 +69,11 @@
|
||||
|
||||
<h5>{{event.categories[0].name}}</h5>
|
||||
<dl class="text-sm">
|
||||
<dt><i class="fa fa-calendar"></i> {{ 'dates' | translate }}</dt>
|
||||
<dt ng-if="event.event_themes.length > 0"><i class="fa fa-tags" aria-hidden="true"></i> {{event.event_themes[0].name}}</dt>
|
||||
<dt ng-if="event.age_range"><i class="fa fa-users" aria-hidden="true"></i> {{event.age_range.name}}</dt>
|
||||
</dl>
|
||||
<dl class="text-sm">
|
||||
<dt><i class="fa fa-calendar" aria-hidden="true"></i> {{ 'dates' | translate }}</dt>
|
||||
<dd>{{ 'beginning' | translate }} <span class="text-u-l">{{event.start_date | amDateFormat:'L'}}</span><br>{{ 'ending' | translate }} <span class="text-u-l">{{event.end_date | amDateFormat:'L'}}</span></dd>
|
||||
<dt><i class="fa fa-clock-o"></i> {{ 'opening_hours' | translate }}</dt>
|
||||
<dd ng-if="event.all_day == 'true'"><span translate>{{ 'all_day' }}</span></dd>
|
||||
|
@ -80,7 +80,7 @@
|
||||
</div>
|
||||
|
||||
<section class="col-lg-12 wrapper">
|
||||
<h4 class="text-sm m-t-sm">{{ 'fablab_s_next_courses_and_workshops' | translate }} <a ui-sref="app.public.events_list" class="pull-right"><i class="fa fa-tags"></i> {{ 'every_events' | translate }}</a></h4>
|
||||
<h4 class="text-sm m-t-sm">{{ 'fablab_s_next_events' | translate }} <a ui-sref="app.public.events_list" class="pull-right"><i class="fa fa-tags"></i> {{ 'every_events' | translate }}</a></h4>
|
||||
|
||||
<div class="row" ng-repeat="event in (upcomingEvents.length/3 | array)">
|
||||
|
||||
|
@ -38,7 +38,7 @@
|
||||
<li><a href="#" ui-sref="app.logged.dashboard.settings" translate>{{ 'my_settings' }}</a></li>
|
||||
<li><a href="#" ui-sref="app.logged.dashboard.projects" translate>{{ 'my_projects' }}</a></li>
|
||||
<li><a href="#" ui-sref="app.logged.dashboard.trainings" translate>{{ 'my_trainings' }}</a></li>
|
||||
<li><a href="#" ui-sref="app.logged.dashboard.events" translate>{{ 'my_courses_and_workshops' }}</a></li>
|
||||
<li><a href="#" ui-sref="app.logged.dashboard.events" translate>{{ 'my_events' }}</a></li>
|
||||
<li><a href="#" ui-sref="app.logged.dashboard.invoices" translate>{{ 'my_invoices' }}</a></li>
|
||||
|
||||
<li class="divider"></li>
|
||||
|
@ -53,7 +53,7 @@
|
||||
</li>
|
||||
<li class="hidden-sm hidden-md hidden-lg">
|
||||
<a href="#" ui-sref="app.logged.dashboard.events">
|
||||
<i class="fa fa-calendar-o"></i> <span translate>{{ 'my_courses_and_workshops' }}</span>
|
||||
<i class="fa fa-calendar-o"></i> <span translate>{{ 'my_events' }}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="hidden-sm hidden-md hidden-lg" ng-if-end>
|
||||
|
49
app/controllers/api/age_ranges_controller.rb
Normal file
49
app/controllers/api/age_ranges_controller.rb
Normal file
@ -0,0 +1,49 @@
|
||||
class API::AgeRangesController < API::ApiController
|
||||
before_action :authenticate_user!, except: [:index]
|
||||
before_action :set_age_range, only: [:show, :update, :destroy]
|
||||
|
||||
def index
|
||||
@age_ranges = AgeRange.all
|
||||
end
|
||||
|
||||
def show
|
||||
end
|
||||
|
||||
def create
|
||||
authorize AgeRange
|
||||
@age_range = AgeRange.new(age_range_params)
|
||||
if @age_range.save
|
||||
render :show, status: :created, location: @age_range
|
||||
else
|
||||
render json: @age_range.errors, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def update
|
||||
authorize AgeRange
|
||||
if @age_range.update(age_range_params)
|
||||
render :show, status: :ok, location: @age_range
|
||||
else
|
||||
render json: @age_range.errors, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
authorize AgeRange
|
||||
if @age_range.safe_destroy
|
||||
head :no_content
|
||||
else
|
||||
render json: @age_range.errors, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def set_age_range
|
||||
@age_range = AgeRange.find(params[:id])
|
||||
end
|
||||
|
||||
def age_range_params
|
||||
params.require(:age_range).permit(:name)
|
||||
end
|
||||
end
|
@ -1,5 +1,49 @@
|
||||
class API::CategoriesController < API::ApiController
|
||||
before_action :authenticate_user!, except: [:index]
|
||||
before_action :set_category, only: [:show, :update, :destroy]
|
||||
|
||||
def index
|
||||
@categories = Category.all
|
||||
end
|
||||
|
||||
def show
|
||||
end
|
||||
|
||||
def create
|
||||
authorize Category
|
||||
@category = Category.new(category_params)
|
||||
if @category.save
|
||||
render :show, status: :created, location: @category
|
||||
else
|
||||
render json: @category.errors, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def update
|
||||
authorize Category
|
||||
if @category.update(category_params)
|
||||
render :show, status: :ok, location: @category
|
||||
else
|
||||
render json: @category.errors, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
authorize Category
|
||||
if @category.safe_destroy
|
||||
head :no_content
|
||||
else
|
||||
render json: @category.errors, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def set_category
|
||||
@category = Category.find(params[:id])
|
||||
end
|
||||
|
||||
def category_params
|
||||
params.require(:category).permit(:name)
|
||||
end
|
||||
end
|
||||
|
49
app/controllers/api/event_themes_controller.rb
Normal file
49
app/controllers/api/event_themes_controller.rb
Normal file
@ -0,0 +1,49 @@
|
||||
class API::EventThemesController < API::ApiController
|
||||
before_action :authenticate_user!, except: [:index]
|
||||
before_action :set_event_theme, only: [:show, :update, :destroy]
|
||||
|
||||
def index
|
||||
@event_themes = EventTheme.all
|
||||
end
|
||||
|
||||
def show
|
||||
end
|
||||
|
||||
def create
|
||||
authorize EventTheme
|
||||
@event_theme = EventTheme.new(event_theme_params)
|
||||
if @event_theme.save
|
||||
render :show, status: :created, location: @event_theme
|
||||
else
|
||||
render json: @event_theme.errors, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def update
|
||||
authorize EventTheme
|
||||
if @event_theme.update(event_theme_params)
|
||||
render :show, status: :ok, location: @event_theme
|
||||
else
|
||||
render json: @event_theme.errors, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
authorize EventTheme
|
||||
if @event_theme.safe_destroy
|
||||
head :no_content
|
||||
else
|
||||
render json: @event_theme.errors, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def set_event_theme
|
||||
@event_theme = EventTheme.find(params[:id])
|
||||
end
|
||||
|
||||
def event_theme_params
|
||||
params.require(:event_theme).permit(:name)
|
||||
end
|
||||
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
|
||||
@ -57,7 +64,8 @@ class API::EventsController < API::ApiController
|
||||
def event_params
|
||||
event_preparams = params.required(:event).permit(:title, :description, :start_date, :start_time, :end_date, :end_time,
|
||||
:amount, :reduced_amount, :nb_total_places, :availability_id,
|
||||
:all_day, :recurrence, :recurrence_end_at, :category_ids, category_ids: [],
|
||||
:all_day, :recurrence, :recurrence_end_at, :category_ids, :event_theme_ids,
|
||||
:age_range_id, event_theme_ids: [], category_ids: [],
|
||||
event_image_attributes: [:attachment], event_files_attributes: [:id, :attachment, :_destroy])
|
||||
start_date = Time.zone.parse(event_preparams[:start_date])
|
||||
end_date = Time.zone.parse(event_preparams[:end_date])
|
||||
|
14
app/models/age_range.rb
Normal file
14
app/models/age_range.rb
Normal file
@ -0,0 +1,14 @@
|
||||
class AgeRange < ActiveRecord::Base
|
||||
extend FriendlyId
|
||||
friendly_id :name, use: :slugged
|
||||
|
||||
has_many :events, dependent: :nullify
|
||||
|
||||
def safe_destroy
|
||||
if self.events.count == 0
|
||||
destroy
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
@ -1,3 +1,36 @@
|
||||
class Category < ActiveRecord::Base
|
||||
has_and_belongs_to_many :events, join_table: :events_categories
|
||||
extend FriendlyId
|
||||
friendly_id :name, use: :slugged
|
||||
|
||||
has_and_belongs_to_many :events, join_table: :events_categories, dependent: :destroy
|
||||
|
||||
after_create :create_statistic_subtype
|
||||
after_update :update_statistic_subtype, if: :name_changed?
|
||||
after_destroy :remove_statistic_subtype
|
||||
|
||||
|
||||
def create_statistic_subtype
|
||||
index = StatisticIndex.where(es_type_key: 'event')
|
||||
StatisticSubType.create!({statistic_types: index.first.statistic_types, key: self.slug, label: self.name})
|
||||
end
|
||||
|
||||
def update_statistic_subtype
|
||||
index = StatisticIndex.where(es_type_key: 'event')
|
||||
subtype = StatisticSubType.joins(statistic_type_sub_types: :statistic_type).where(key: self.slug, statistic_types: { statistic_index_id: index.first.id }).first
|
||||
subtype.label = self.name
|
||||
subtype.save!
|
||||
end
|
||||
|
||||
def remove_statistic_subtype
|
||||
subtype = StatisticSubType.where(key: self.slug).first
|
||||
subtype.destroy!
|
||||
end
|
||||
|
||||
def safe_destroy
|
||||
if Category.count > 1 && self.events.count == 0
|
||||
destroy
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -8,6 +8,9 @@ class Event < ActiveRecord::Base
|
||||
has_and_belongs_to_many :categories, join_table: :events_categories
|
||||
validates :categories, presence: true
|
||||
has_many :reservations, as: :reservable, dependent: :destroy
|
||||
has_and_belongs_to_many :event_themes, join_table: :events_event_themes, dependent: :destroy
|
||||
|
||||
belongs_to :age_range
|
||||
|
||||
belongs_to :availability, dependent: :destroy
|
||||
accepts_nested_attributes_for :availability
|
||||
@ -23,6 +26,10 @@ class Event < ActiveRecord::Base
|
||||
title
|
||||
end
|
||||
|
||||
def themes
|
||||
self.event_themes
|
||||
end
|
||||
|
||||
def recurrence_events
|
||||
Event.includes(:availability).where('events.recurrence_id = ? AND events.id != ? AND availabilities.start_at >= ?', recurrence_id, id, Time.now).references(:availabilities)
|
||||
end
|
||||
|
14
app/models/event_theme.rb
Normal file
14
app/models/event_theme.rb
Normal file
@ -0,0 +1,14 @@
|
||||
class EventTheme < ActiveRecord::Base
|
||||
extend FriendlyId
|
||||
friendly_id :name, use: :slugged
|
||||
|
||||
has_and_belongs_to_many :events, join_table: :events_event_themes, dependent: :destroy
|
||||
|
||||
def safe_destroy
|
||||
if self.events.count == 0
|
||||
destroy
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
@ -6,5 +6,7 @@ module Stats
|
||||
|
||||
attribute :eventId, Integer
|
||||
attribute :eventDate, String
|
||||
attribute :ageRange, String
|
||||
attribute :eventTheme, String
|
||||
end
|
||||
end
|
||||
|
@ -110,9 +110,9 @@ module PDF
|
||||
### Training reservation
|
||||
when 'Training'
|
||||
details += I18n.t('invoices.training_reservation_DESCRIPTION', DESCRIPTION: item.description)
|
||||
### courses and workshops reservation
|
||||
### events reservation
|
||||
when 'Event'
|
||||
details += I18n.t('invoices.courses_and_workshops_reservation_DESCRIPTION', DESCRIPTION: item.description)
|
||||
details += I18n.t('invoices.event_reservation_DESCRIPTION', DESCRIPTION: item.description)
|
||||
# details of the number of tickets
|
||||
details += "\n "+I18n.t('invoices.full_price_ticket', count: invoice.invoiced.nb_reserve_places) if invoice.invoiced.nb_reserve_places > 0
|
||||
details += "\n "+I18n.t('invoices.reduced_rate_ticket', count: invoice.invoiced.nb_reserve_reduced_places) if invoice.invoiced.nb_reserve_reduced_places > 0
|
||||
|
7
app/policies/age_range_policy.rb
Normal file
7
app/policies/age_range_policy.rb
Normal file
@ -0,0 +1,7 @@
|
||||
class AgeRangePolicy < ApplicationPolicy
|
||||
%w(create update destroy show).each do |action|
|
||||
define_method "#{action}?" do
|
||||
user.is_admin?
|
||||
end
|
||||
end
|
||||
end
|
7
app/policies/category_policy.rb
Normal file
7
app/policies/category_policy.rb
Normal file
@ -0,0 +1,7 @@
|
||||
class CategoryPolicy < ApplicationPolicy
|
||||
%w(create update destroy show).each do |action|
|
||||
define_method "#{action}?" do
|
||||
user.is_admin?
|
||||
end
|
||||
end
|
||||
end
|
7
app/policies/event_theme_policy.rb
Normal file
7
app/policies/event_theme_policy.rb
Normal file
@ -0,0 +1,7 @@
|
||||
class EventThemePolicy < ApplicationPolicy
|
||||
%w(create update destroy show).each do |action|
|
||||
define_method "#{action}?" do
|
||||
user.is_admin?
|
||||
end
|
||||
end
|
||||
end
|
@ -68,7 +68,9 @@ class StatisticService
|
||||
eventId: r.event_id,
|
||||
name: r.event_name,
|
||||
eventDate: r.event_date,
|
||||
reservationId: r.reservation_id
|
||||
reservationId: r.reservation_id,
|
||||
eventTheme: r.event_theme,
|
||||
ageRange: r.age_range
|
||||
}.merge(user_info_stat(r)))
|
||||
stat.stat = (type == 'booking' ? r.nb_places : r.nb_hours)
|
||||
stat.save
|
||||
@ -201,6 +203,8 @@ class StatisticService
|
||||
event_type: r.reservable.categories.first.name,
|
||||
event_name: r.reservable.name,
|
||||
event_date: slot.start_at.to_date,
|
||||
event_theme: (r.reservable.event_themes.first ? r.reservable.event_themes.first.name : ''),
|
||||
age_range: (r.reservable.age_range_id ? r.reservable.age_range.name : ''),
|
||||
nb_places: r.nb_reserve_places + r.nb_reserve_reduced_places,
|
||||
nb_hours: difference_in_hours(slot.start_at, slot.end_at),
|
||||
ca: calcul_ca(r.invoice)
|
||||
|
6
app/views/api/age_ranges/index.json.jbuilder
Normal file
6
app/views/api/age_ranges/index.json.jbuilder
Normal file
@ -0,0 +1,6 @@
|
||||
user_is_admin = (current_user and current_user.is_admin?)
|
||||
|
||||
json.array!(@age_ranges) do |ar|
|
||||
json.extract! ar, :id, :name
|
||||
json.related_to ar.events.count if user_is_admin
|
||||
end
|
1
app/views/api/age_ranges/show.json.jbuilder
Normal file
1
app/views/api/age_ranges/show.json.jbuilder
Normal file
@ -0,0 +1 @@
|
||||
json.extract! @age_range, :id, :name
|
@ -1,3 +1,6 @@
|
||||
user_is_admin = (current_user and current_user.is_admin?)
|
||||
|
||||
json.array!(@categories) do |category|
|
||||
json.extract! category, :id, :name
|
||||
json.related_to category.events.count if user_is_admin
|
||||
end
|
||||
|
1
app/views/api/categories/show.json.jbuilder
Normal file
1
app/views/api/categories/show.json.jbuilder
Normal file
@ -0,0 +1 @@
|
||||
json.extract! @category, :id, :name
|
6
app/views/api/event_themes/index.json.jbuilder
Normal file
6
app/views/api/event_themes/index.json.jbuilder
Normal file
@ -0,0 +1,6 @@
|
||||
user_is_admin = (current_user and current_user.is_admin?)
|
||||
|
||||
json.array!(@event_themes) do |theme|
|
||||
json.extract! theme, :id, :name
|
||||
json.related_to theme.events.count if user_is_admin
|
||||
end
|
1
app/views/api/event_themes/show.json.jbuilder
Normal file
1
app/views/api/event_themes/show.json.jbuilder
Normal file
@ -0,0 +1 @@
|
||||
json.extract! @event_theme, :id, :name
|
@ -1,4 +1,4 @@
|
||||
json.extract! event, :id, :title, :description
|
||||
json.extract! event, :id, :title, :description, :age_range_id
|
||||
json.event_image event.event_image.attachment_url if event.event_image
|
||||
json.event_files_attributes event.event_files do |f|
|
||||
json.id f.id
|
||||
@ -10,6 +10,14 @@ json.categories event.categories do |c|
|
||||
json.id c.id
|
||||
json.name c.name
|
||||
end
|
||||
json.event_theme_ids event.event_theme_ids
|
||||
json.event_themes event.event_themes do |e|
|
||||
json.name e.name
|
||||
end
|
||||
json.age_range_id event.age_range_id
|
||||
json.age_range do
|
||||
json.name event.age_range.name
|
||||
end if event.age_range
|
||||
json.start_date event.availability.start_at
|
||||
json.start_time event.availability.start_at
|
||||
json.end_date event.availability.end_at
|
||||
@ -28,3 +36,4 @@ json.amount (event.amount / 100.0) if event.amount
|
||||
json.reduced_amount (event.reduced_amount / 100.0) if event.reduced_amount
|
||||
json.nb_total_places event.nb_total_places
|
||||
json.nb_free_places event.nb_free_places || event.nb_total_places
|
||||
|
||||
|
@ -1,8 +1,10 @@
|
||||
total = @events.except(:offset, :limit, :order).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
|
||||
|
@ -70,17 +70,29 @@ en:
|
||||
dont_forget_to_change_them_before_creating_slots_for_this_training: "Don't forget to change them before creating slots for this training."
|
||||
|
||||
events:
|
||||
# courses and workshops tracking and management
|
||||
fablab_courses_and_workshops: "Fablab courses and workshops"
|
||||
# events tracking and management
|
||||
events_monitoring: "Events monitoring"
|
||||
manage_filters: "Manage filters"
|
||||
fablab_events: "Fablab events"
|
||||
all_events: "All events"
|
||||
passed_events: "Passed events"
|
||||
events_to_come: "Events to come"
|
||||
from_DATE: "From {{DATE}}" # angular interpolation
|
||||
from_TIME: "From {{TIME}}" # angular interpolation
|
||||
view_reservations: "View reservations"
|
||||
categories: "Categories"
|
||||
add_a_category: "Add a category"
|
||||
add_a_theme: "Add a theme"
|
||||
age_ranges: "Age ranges"
|
||||
add_a_range: "Add a range"
|
||||
do_you_really_want_to_delete_this_ELEMENT: "Do you really want to delete this {ELEMENT, select, category{category} theme{theme} age_range{age range} other{element}}?" # messageFormat interpolation
|
||||
unable_to_delete_ELEMENT_already_in_use_NUMBER_times: "Unable to delete this {ELEMENT, select, category{category} theme{theme} age_range{age range} other{element}} because it is already associated with {NUMBER, plural, =0{no events} one{one event} other{{NUMBER} events}}." # messageFormat interpolation
|
||||
at_least_one_category_is_required: "At least one category is required."
|
||||
unable_to_delete_the_last_one: "Unable to delete the last one."
|
||||
unable_to_delete_an_error_occured: "Unable to delete: an error occurred."
|
||||
|
||||
events_new:
|
||||
# add a new workshop/course
|
||||
# add a new event
|
||||
none: "None"
|
||||
every_days: "Every days"
|
||||
every_week: "Every week"
|
||||
@ -319,13 +331,12 @@ en:
|
||||
next_trainings: "Next trainings"
|
||||
passed_trainings: "Passed trainings"
|
||||
validated_trainings: "Validated trainings"
|
||||
courses_and_workshops: "Courses and workshops"
|
||||
next_courses_and_workshops: "Next courses and workshops"
|
||||
no_upcomning_courses_or_workshops: "No upcoming courses and workshops"
|
||||
events: "Events"
|
||||
next_events: "Next events"
|
||||
no_upcoming_events: "No upcoming events"
|
||||
NUMBER_full_price_tickets_reserved: "{NUMBER, plural, =0{} one{1 full price ticket reserved} other{{NUMBER} full price tickets reserved}}" # messageFormat interpolation
|
||||
NUMBER_reduced_rate_tickets_reserved: "{NUMBER, plural, =0{} one{1 reduced rate ticket reserved} other{{NUMBER} reduced rate tickets reserved}}" # messageFormat interpolation
|
||||
passed_courses_and_workshops: "Passed courses and workshops"
|
||||
no_passed_courses_or_workshop: "No passed courses or workshops"
|
||||
passed_events: "Passed events"
|
||||
invoices: "Invoices"
|
||||
invoice_#: "Invoice #"
|
||||
download_the_refund_invoice: "Download the refund invoice"
|
||||
|
@ -70,17 +70,29 @@ fr:
|
||||
dont_forget_to_change_them_before_creating_slots_for_this_training: "Pensez à les modifier avant de créer des créneaux pour cette formation."
|
||||
|
||||
events:
|
||||
# gestion et suivi des stages et ateliers
|
||||
fablab_courses_and_workshops: "Les Stages et ateliers du Fab Lab"
|
||||
# gestion et suivi des évènements
|
||||
events_monitoring: "Suivi des évènements"
|
||||
manage_filters: "Gérer les filtres"
|
||||
fablab_events: "Les évènements du Fab Lab"
|
||||
all_events: "Tous les évènements"
|
||||
passed_events: "Les évènements déjà passés"
|
||||
events_to_come: "Les évènements à venir"
|
||||
from_DATE: "Du {{DATE}}" # angular interpolation
|
||||
from_TIME: "De {{TIME}}" # angular interpolation
|
||||
view_reservations: "Consulter les réservations"
|
||||
categories: "Catégories"
|
||||
add_a_category: "Ajouter une catégorie"
|
||||
add_a_theme: "Ajouter une thématique"
|
||||
age_ranges: "Tranches d'âge"
|
||||
add_a_range: "Ajouter une tranche"
|
||||
do_you_really_want_to_delete_this_ELEMENT: "Voulez-vous vraiment supprimer cette {ELEMENT, select, category{catégorie} theme{thématique} age_range{tranche d'âge} other{élément}} ?" # messageFormat interpolation
|
||||
unable_to_delete_ELEMENT_already_in_use_NUMBER_times: "Impossible de supprimer cette {ELEMENT, select, category{catégorie} theme{thématique} age_range{tranche d'âge} other{élément}} car elle est actuellement associée à {NUMBER, plural, =0{aucun évènement} one{un évènement} other{{NUMBER} évènements}}." # messageFormat interpolation
|
||||
at_least_one_category_is_required: "Au moins une catégorie est requise."
|
||||
unable_to_delete_the_last_one: "Impossible de supprimer la dernière."
|
||||
unable_to_delete_an_error_occured: "Impossible de supprimer : une erreur est survenue."
|
||||
|
||||
events_new:
|
||||
# ajouter un nouveau atelier/stage
|
||||
# ajouter un nouvel évènement
|
||||
none: "Aucune"
|
||||
every_days: "Tous les jours"
|
||||
every_week: "Chaque semaine"
|
||||
@ -319,13 +331,12 @@ fr:
|
||||
next_trainings: "Les prochaines formations"
|
||||
passed_trainings: "Les formations passées"
|
||||
validated_trainings: "Les formations validées"
|
||||
courses_and_workshops: "Ateliers et stages"
|
||||
next_courses_and_workshops: "Les prochains stages et ateliers"
|
||||
no_upcomning_courses_or_workshops: "Aucun stage ou atelier à venir"
|
||||
events: "Évènements"
|
||||
next_events: "Les prochains évènements"
|
||||
no_upcoming_events: "Aucun évènement à venir"
|
||||
NUMBER_full_price_tickets_reserved: "{NUMBER, plural, =0{} one{1 place plein tarif réservée} other{{NUMBER} places plein tarif réservées}}" # messageFormat interpolation
|
||||
NUMBER_reduced_rate_tickets_reserved: "{NUMBER, plural, =0{} one{1 place à tarif réduit réservée} other{{NUMBER} places à tarif réduit réservées}}" # messageFormat interpolation
|
||||
passed_courses_and_workshops: "Les stages et ateliers passés"
|
||||
no_passed_courses_or_workshop: "Aucun stage ou atelier passé"
|
||||
passed_events: "Les évènements passés"
|
||||
invoices: "Factures"
|
||||
invoice_#: "Facture n°"
|
||||
download_the_refund_invoice: "Télécharger l'avoir"
|
||||
|
@ -59,10 +59,9 @@ en:
|
||||
your_approved_trainings: "Your approved trainings"
|
||||
events:
|
||||
# dashboard: my events
|
||||
your_next_courses_and_workshops: "Your next courses and workshops"
|
||||
no_courses_or_workshops_to_come: "No courses or workshops to come"
|
||||
your_previous_courses_and_workshops: "Your previous courses and workshops"
|
||||
no_passed_courses_or_workshops: "No passed courses or workshops"
|
||||
your_next_events: "Your next events"
|
||||
no_events_to_come: "No events to come"
|
||||
your_previous_events: "Your previous events"
|
||||
NUMBER_normal_places_reserved: "{NUMBER} {NUMBER, plural, =1{normal place reserved}, other{normal places reserved}}" # messageFormat interpolation
|
||||
NUMBER_reduced_fare_places_reserved: "{NUMBER} {NUMBER, plural, =1{reduced fare place reserved}, other{reduced fare places reserved}" # messageFormat interpolation
|
||||
invoices:
|
||||
|
@ -59,10 +59,9 @@ fr:
|
||||
your_approved_trainings: "Vos formations validées"
|
||||
events:
|
||||
# tableau de bord : mes évènements
|
||||
your_next_courses_and_workshops: "Vos prochains stages et ateliers"
|
||||
no_courses_or_workshops_to_come: "Aucun stage ou atelier à venir"
|
||||
your_previous_courses_and_workshops: "Vos stages et ateliers passés"
|
||||
no_passed_courses_or_workshops: "Aucun stage ou atelier passé"
|
||||
your_next_events: "Vos prochains évènements"
|
||||
no_events_to_come: "Aucun évènement à venir"
|
||||
your_previous_events: "Vos évènements passés"
|
||||
NUMBER_normal_places_reserved: "{NUMBER} {NUMBER, plural, =1{place normale réservée}, other{places normales réservées}}" # messageFormat interpolation
|
||||
NUMBER_reduced_fare_places_reserved: "{NUMBER} {NUMBER, plural, =1{place réservée à tarif réduit}, other{places réservées à tarif réduit}" # messageFormat interpolation
|
||||
invoices:
|
||||
|
@ -12,7 +12,7 @@ en:
|
||||
my_settings: "My Settings"
|
||||
my_projects: "My Projects"
|
||||
my_trainings: "My Trainings"
|
||||
my_courses_and_workshops: "My Courses and Workshops"
|
||||
my_events: "My Events"
|
||||
my_invoices: "My Invoices"
|
||||
|
||||
# login/logout
|
||||
@ -29,7 +29,7 @@ en:
|
||||
home: "Home"
|
||||
reserve_a_machine: "Reserve a Machine"
|
||||
trainings_registrations: "Trainings registrations"
|
||||
courses_and_workshops_registrations: "Courses and Workshops registrations"
|
||||
events_registrations: "Events registrations"
|
||||
projects_gallery: "Projects gallery"
|
||||
subscriptions: "Subscriptions"
|
||||
|
||||
@ -40,7 +40,7 @@ en:
|
||||
manage_the_users: "Manage the Users"
|
||||
manage_the_invoices: "Manage the invoices"
|
||||
subscriptions_and_prices: "Subscriptions and Prices"
|
||||
courses_and_workshops_monitoring: "Courses and Workshops monitoring"
|
||||
manage_the_events: "Manage the events"
|
||||
manage_the_machines: "Manage the Machines"
|
||||
manage_the_projects_elements: "Manage the Projects Elements"
|
||||
statistics: "Statistics"
|
||||
@ -108,7 +108,7 @@ en:
|
||||
discover_members: "Discover members"
|
||||
|
||||
# next events summary on the home page
|
||||
fablab_s_next_courses_and_workshops: "Fablab's next courses and workshops"
|
||||
fablab_s_next_events: "Fablab's next events"
|
||||
every_events: "Every events"
|
||||
from_date_to_date: "From {{START}} to {{END}}" # angular interpolation
|
||||
on_the_date: "On the {{DATE}}" # angular interpolation
|
||||
@ -131,7 +131,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"
|
||||
|
||||
@ -205,7 +204,9 @@ en:
|
||||
|
||||
events_list:
|
||||
# Fablab's events list
|
||||
the_fablab_s_courses_and_workshops: "The Fablab's courses and workshops"
|
||||
the_fablab_s_events: "The Fablab's events"
|
||||
all_categories: "All categories"
|
||||
for_all: "For all"
|
||||
|
||||
events_show:
|
||||
# details and booking of an event
|
||||
|
@ -12,7 +12,7 @@ fr:
|
||||
my_settings: "Mes paramètres"
|
||||
my_projects: "Mes projets"
|
||||
my_trainings: "Mes formations"
|
||||
my_courses_and_workshops: "Mes stages et ateliers"
|
||||
my_events: "Mes évènements"
|
||||
my_invoices: "Mes factures"
|
||||
|
||||
# connexion / déconnexion
|
||||
@ -29,7 +29,7 @@ fr:
|
||||
home: "Accueil"
|
||||
reserve_a_machine: "Réserver une machine"
|
||||
trainings_registrations: "Inscriptions formations"
|
||||
courses_and_workshops_registrations: "Inscriptions stages et ateliers"
|
||||
events_registrations: "Inscriptions aux évènements"
|
||||
projects_gallery: "Galerie de projets"
|
||||
subscriptions: "Abonnements"
|
||||
|
||||
@ -40,7 +40,7 @@ fr:
|
||||
manage_the_users: "Gérer les utilisateurs"
|
||||
manage_the_invoices: "Gérer les factures"
|
||||
subscriptions_and_prices: "Abonnements & Tarifs"
|
||||
courses_and_workshops_monitoring: "Suivi stages et ateliers"
|
||||
manage_the_events: "Gérer les évènements"
|
||||
manage_the_machines: "Gérer les machines"
|
||||
manage_the_projects_elements: "Gérer les éléments projets"
|
||||
statistics: "Statistiques"
|
||||
@ -108,7 +108,7 @@ fr:
|
||||
discover_members: "Découvrir les membres"
|
||||
|
||||
# résumé des prochains évènements sur la page d'acceuil
|
||||
fablab_s_next_courses_and_workshops: "Les prochains ateliers et stages du Fab Lab"
|
||||
fablab_s_next_events: "Les prochains évènements du Fab Lab"
|
||||
every_events: "Tous les évènements"
|
||||
from_date_to_date: "Du {{START}} au {{END}}" # angular interpolation
|
||||
on_the_date: "Le {{DATE}}" # angular interpolation
|
||||
@ -131,7 +131,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"
|
||||
|
||||
@ -207,7 +206,9 @@ fr:
|
||||
|
||||
events_list:
|
||||
# liste des évènements du fablab
|
||||
the_fablab_s_courses_and_workshops: "Les Stages et ateliers du Fab Lab"
|
||||
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
|
||||
|
@ -54,7 +54,8 @@ en:
|
||||
confirm_and_pay: "Confirm and pay"
|
||||
your_invoice_will_be_available_soon_from_your_: "Your invoice will be available soon form your"
|
||||
add_an_event: "Add an event"
|
||||
load_the_next_courses_and_workshops: "Load the next courses and workshops..."
|
||||
load_the_next_events: "Load the next events..."
|
||||
no_passed_events: "No passed events"
|
||||
dates: "Dates:"
|
||||
thank_you_your_payment_has_been_successfully_registered: "Thank you. Your payment has been successfully registered !"
|
||||
surname: "Surname"
|
||||
@ -92,6 +93,7 @@ en:
|
||||
book: "Book"
|
||||
description_is_required: "Description is required."
|
||||
name_is_required: "Name is required."
|
||||
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"
|
||||
@ -163,7 +165,7 @@ en:
|
||||
here_is_the_summary_of_the_slots_to_book_for_the_current_user: "Here is the summary of the slots to book for the current user:"
|
||||
|
||||
event:
|
||||
# event edition form (courses/workshops)
|
||||
# event edition form
|
||||
title_is_required: "Title is required."
|
||||
matching_visual: "Matching visual"
|
||||
choose_a_picture: "Choose a picture"
|
||||
@ -182,6 +184,8 @@ en:
|
||||
standard_rate: "Standard rate"
|
||||
0_=_free: "0 = free"
|
||||
tickets_available: "Tickets available"
|
||||
event_theme: "Event theme"
|
||||
age_range: "Age range"
|
||||
|
||||
plan:
|
||||
# subscription plan edition form
|
||||
|
@ -54,7 +54,8 @@ fr:
|
||||
confirm_and_pay: "Valider et payer"
|
||||
your_invoice_will_be_available_soon_from_your_: "Votre facture sera bientôt disponible depuis votre"
|
||||
add_an_event: "Ajouter un évènement"
|
||||
load_the_next_courses_and_workshops: "Charger les stages et ateliers suivants ..."
|
||||
load_the_next_events: "Charger les évènements suivants ..."
|
||||
no_passed_events: "Aucun évènement passé"
|
||||
dates: "Dates :"
|
||||
thank_you_your_payment_has_been_successfully_registered: "Merci. Votre paiement a bien été pris en compte !"
|
||||
surname: "Nom"
|
||||
@ -92,6 +93,7 @@ fr:
|
||||
book: "Réserver"
|
||||
description_is_required: "La description est requise."
|
||||
name_is_required: "Le nom est requis."
|
||||
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"
|
||||
@ -163,7 +165,7 @@ fr:
|
||||
here_is_the_summary_of_the_slots_to_book_for_the_current_user: "Voici le récapitulatif des créneaux à réserver pour l'utilisateur courant :"
|
||||
|
||||
event:
|
||||
# formulaire d'édition d'un événement (stage/atelier)
|
||||
# formulaire d'édition d'un événement
|
||||
title_is_required: "Le titre est requis."
|
||||
matching_visual: "Visuel associé"
|
||||
choose_a_picture: "Choisir une image"
|
||||
@ -182,6 +184,8 @@ fr:
|
||||
standard_rate: "Tarif standard"
|
||||
0_=_free: "0 = gratuit"
|
||||
tickets_available: "Places disponibles"
|
||||
event_theme: "Thème de l'évènement"
|
||||
age_range: "Tranche d'âge"
|
||||
|
||||
plan:
|
||||
# formulaire d'édition d'une formule d'abonnement
|
||||
|
@ -78,7 +78,7 @@ en:
|
||||
subscription_NAME_from_START_to_END: "Subscription - From %{START} to %{END}"
|
||||
machine_reservation_DESCRIPTION: "Machine reservation - %{DESCRIPTION}"
|
||||
training_reservation_DESCRIPTION: "Training reservation - %{DESCRIPTION}"
|
||||
courses_and_workshops_reservation_DESCRIPTION: "Courses and Workshops reservation - %{DESCRIPTION}"
|
||||
event_reservation_DESCRIPTION: "Event reservation - %{DESCRIPTION}"
|
||||
full_price_ticket:
|
||||
one: "One full price ticket"
|
||||
other: "%{count} full price tickets"
|
||||
@ -244,6 +244,8 @@ en:
|
||||
event_id: "Event ID"
|
||||
event_date: "Event Date"
|
||||
event_name: "Event Name"
|
||||
event_theme: "Theme"
|
||||
age_range: "Age Range"
|
||||
themes: "Themes"
|
||||
components: "Components"
|
||||
machines: "Machines"
|
||||
@ -251,4 +253,6 @@ en:
|
||||
bookings: "Bookings"
|
||||
hours_number: "Hours number"
|
||||
tickets_number: "Tickets number"
|
||||
revenue: "Revenue"
|
||||
revenue: "Revenue"
|
||||
account_creation: "Account creation"
|
||||
project_publication: "Project publication"
|
||||
|
@ -78,7 +78,7 @@ fr:
|
||||
subscription_NAME_from_START_to_END: "Abonnement - Du %{START} au %{END}"
|
||||
machine_reservation_DESCRIPTION: "Réservation Machine - %{DESCRIPTION}"
|
||||
training_reservation_DESCRIPTION: "Réservation Formation - %{DESCRIPTION}"
|
||||
courses_and_workshops_reservation_DESCRIPTION: "Réservation Ateliers et Stages - %{DESCRIPTION}"
|
||||
event_reservation_DESCRIPTION: "Réservation Évènement - %{DESCRIPTION}"
|
||||
full_price_ticket:
|
||||
one: "Une place plein tarif"
|
||||
other: "%{count} places plein tarif"
|
||||
@ -244,6 +244,8 @@ fr:
|
||||
event_id: "ID Évènement"
|
||||
event_date: "Date Évènement"
|
||||
event_name: "Nom Évènement"
|
||||
event_theme: "Thématique"
|
||||
age_range: "Tranche d'âge"
|
||||
themes: "Thèmes"
|
||||
components: "Composants"
|
||||
machines: "Machines"
|
||||
@ -252,7 +254,5 @@ fr:
|
||||
hours_number: "Nombre d'heures"
|
||||
tickets_number: "Nombre de places"
|
||||
revenue: "Chiffre d'affaires"
|
||||
course: "Stage"
|
||||
workshop: "Atelier"
|
||||
account_creation: "Création de compte"
|
||||
project_publication: "Publication de projet"
|
||||
project_publication: "Publication de projet"
|
||||
|
@ -87,7 +87,9 @@ Rails.application.routes.draw do
|
||||
# for admin
|
||||
resources :trainings
|
||||
resources :credits
|
||||
resources :categories, only: [:index]
|
||||
resources :categories
|
||||
resources :event_themes
|
||||
resources :age_ranges
|
||||
resources :statistics, only: [:index]
|
||||
resources :custom_assets, only: [:show, :create, :update]
|
||||
resources :tags
|
||||
|
@ -0,0 +1,13 @@
|
||||
class RenameCoursesWorkshopsToEvents < ActiveRecord::Migration
|
||||
def up
|
||||
execute "UPDATE statistic_indices
|
||||
SET label='Évènements'
|
||||
WHERE es_type_key='event';"
|
||||
end
|
||||
|
||||
def down
|
||||
execute "UPDATE statistic_indices
|
||||
SET label='Ateliers/Stages'
|
||||
WHERE es_type_key='event';"
|
||||
end
|
||||
end
|
9
db/migrate/20160628124538_create_event_themes.rb
Normal file
9
db/migrate/20160628124538_create_event_themes.rb
Normal file
@ -0,0 +1,9 @@
|
||||
class CreateEventThemes < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :event_themes do |t|
|
||||
t.string :name
|
||||
|
||||
t.timestamps null: false
|
||||
end
|
||||
end
|
||||
end
|
8
db/migrate/20160628131408_create_events_event_themes.rb
Normal file
8
db/migrate/20160628131408_create_events_event_themes.rb
Normal file
@ -0,0 +1,8 @@
|
||||
class CreateEventsEventThemes < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :events_event_themes do |t|
|
||||
t.belongs_to :event, index: true, foreign_key: true
|
||||
t.belongs_to :event_theme, index: true, foreign_key: true
|
||||
end
|
||||
end
|
||||
end
|
9
db/migrate/20160628134211_create_age_ranges.rb
Normal file
9
db/migrate/20160628134211_create_age_ranges.rb
Normal file
@ -0,0 +1,9 @@
|
||||
class CreateAgeRanges < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :age_ranges do |t|
|
||||
t.string :range
|
||||
|
||||
t.timestamps null: false
|
||||
end
|
||||
end
|
||||
end
|
5
db/migrate/20160628134303_add_age_range_id_to_event.rb
Normal file
5
db/migrate/20160628134303_add_age_range_id_to_event.rb
Normal file
@ -0,0 +1,5 @@
|
||||
class AddAgeRangeIdToEvent < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :events, :age_range_id, :integer
|
||||
end
|
||||
end
|
@ -0,0 +1,3 @@
|
||||
class RenameRangeToNameFromAgeRange < ActiveRecord::Migration
|
||||
rename_column :age_ranges, :range, :name
|
||||
end
|
6
db/migrate/20160630083438_add_slug_to_categories.rb
Normal file
6
db/migrate/20160630083438_add_slug_to_categories.rb
Normal file
@ -0,0 +1,6 @@
|
||||
class AddSlugToCategories < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :categories, :slug, :string
|
||||
add_index :categories, :slug, unique: true
|
||||
end
|
||||
end
|
6
db/migrate/20160630083556_add_slug_to_age_range.rb
Normal file
6
db/migrate/20160630083556_add_slug_to_age_range.rb
Normal file
@ -0,0 +1,6 @@
|
||||
class AddSlugToAgeRange < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :age_ranges, :slug, :string
|
||||
add_index :age_ranges, :slug, unique: true
|
||||
end
|
||||
end
|
6
db/migrate/20160630083759_add_slug_to_event_theme.rb
Normal file
6
db/migrate/20160630083759_add_slug_to_event_theme.rb
Normal file
@ -0,0 +1,6 @@
|
||||
class AddSlugToEventTheme < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :event_themes, :slug, :string
|
||||
add_index :event_themes, :slug, unique: true
|
||||
end
|
||||
end
|
@ -0,0 +1,6 @@
|
||||
class AddEventThemeAndAgeRangeToStatisticField < ActiveRecord::Migration
|
||||
def change
|
||||
StatisticField.create!({key:'eventTheme', label:I18n.t('statistics.event_theme'), statistic_index_id: 4, data_type: 'text'})
|
||||
StatisticField.create!({key:'ageRange', label:I18n.t('statistics.age_range'), statistic_index_id: 4, data_type: 'text'})
|
||||
end
|
||||
end
|
@ -0,0 +1,13 @@
|
||||
class AddSlugsToExistingCategories < ActiveRecord::Migration
|
||||
def up
|
||||
execute 'UPDATE categories
|
||||
SET slug=name
|
||||
WHERE slug IS NULL;'
|
||||
end
|
||||
|
||||
def down
|
||||
execute 'UPDATE categories
|
||||
SET slug=NULL
|
||||
WHERE slug=name;'
|
||||
end
|
||||
end
|
@ -27,7 +27,9 @@ if StatisticField.count == 0
|
||||
{key:'components', label:I18n.t('statistics.components'), statistic_index_id: 6, data_type: 'list'},
|
||||
{key:'machines', label:I18n.t('statistics.machines'), statistic_index_id: 6, data_type: 'list'},
|
||||
{key:'name', label:I18n.t('statistics.event_name'), statistic_index_id: 4, data_type: 'text'},
|
||||
{key:'userId', label:I18n.t('statistics.user_id'), statistic_index_id: 7, data_type: 'index'}
|
||||
{key:'userId', label:I18n.t('statistics.user_id'), statistic_index_id: 7, data_type: 'index'},
|
||||
{key:'eventTheme', label:I18n.t('statistics.event_theme'), statistic_index_id: 4, data_type: 'text'},
|
||||
{key:'ageRange', label:I18n.t('statistics.age_range'), statistic_index_id: 4, data_type: 'text'}
|
||||
])
|
||||
end
|
||||
|
||||
@ -55,9 +57,6 @@ end
|
||||
|
||||
if StatisticSubType.count == 0
|
||||
StatisticSubType.create!([
|
||||
{key: 'Stage', label:I18n.t('statistics.course'), statistic_types: StatisticIndex.find_by(es_type_key: 'event').statistic_types},
|
||||
{key: 'Atelier', label:I18n.t('statistics.workshop'), statistic_types: StatisticIndex.find_by(es_type_key: 'event').statistic_types},
|
||||
|
||||
{key: 'created', label:I18n.t('statistics.account_creation'), statistic_types: StatisticIndex.find_by(es_type_key: 'account').statistic_types},
|
||||
{key: 'published', label:I18n.t('statistics.project_publication'), statistic_types: StatisticIndex.find_by(es_type_key: 'project').statistic_types}
|
||||
])
|
||||
|
@ -408,6 +408,14 @@ http://localhost:9200/stats/_mapping?pretty
|
||||
},
|
||||
"userId" : {
|
||||
"type" : "long"
|
||||
},
|
||||
"ageRange" : {
|
||||
"type" : "string",
|
||||
"index" : "not_analyzed"
|
||||
},
|
||||
"eventTheme" : {
|
||||
"type" : "string",
|
||||
"index" : "not_analyzed"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -72,6 +72,28 @@ namespace :fablab do
|
||||
}
|
||||
}';`
|
||||
end
|
||||
es_add_event_filters
|
||||
end
|
||||
|
||||
desc 'add event filters to statistics'
|
||||
task es_add_event_filters: :environment do
|
||||
es_add_event_filters
|
||||
end
|
||||
|
||||
def es_add_event_filters
|
||||
`curl -XPUT http://#{ENV["ELASTICSEARCH_HOST"]}:9200/stats/event/_mapping -d '
|
||||
{
|
||||
"properties": {
|
||||
"ageRange": {
|
||||
"type": "string",
|
||||
"index" : "not_analyzed"
|
||||
},
|
||||
"eventTheme": {
|
||||
"type": "string",
|
||||
"index" : "not_analyzed"
|
||||
}
|
||||
}
|
||||
}';`
|
||||
end
|
||||
|
||||
desc "sync all/one project in elastic search index"
|
||||
|
13
test/fixtures/age_ranges.yml
vendored
Normal file
13
test/fixtures/age_ranges.yml
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
|
||||
|
||||
youngs:
|
||||
id: 1
|
||||
name: De 10 à 21 ans
|
||||
|
||||
adults:
|
||||
id: 2
|
||||
name: A partir de 18 ans
|
||||
|
||||
seniors:
|
||||
id: 3
|
||||
name: A partir de 65 ans
|
7
test/fixtures/event_themes.yml
vendored
Normal file
7
test/fixtures/event_themes.yml
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
diy:
|
||||
id: 1
|
||||
name: Do it yourself
|
||||
|
||||
robot:
|
||||
id: 2
|
||||
name: Robot
|
1
test/fixtures/events.yml
vendored
1
test/fixtures/events.yml
vendored
@ -12,6 +12,7 @@ event_2:
|
||||
nb_total_places: 10
|
||||
nb_free_places: 10
|
||||
recurrence_id: 1
|
||||
age_range_id: 2
|
||||
|
||||
event_3:
|
||||
id: 3
|
||||
|
5
test/fixtures/events_event_themes.yml
vendored
Normal file
5
test/fixtures/events_event_themes.yml
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
events_event_themes_1:
|
||||
id: 1
|
||||
event_id: 1
|
||||
event_theme_id: 1
|
20
test/fixtures/statistic_fields.yml
vendored
20
test/fixtures/statistic_fields.yml
vendored
@ -88,3 +88,23 @@ statistic_field_10:
|
||||
created_at: 2016-04-04 14:11:33.423307000 Z
|
||||
updated_at: 2016-04-04 14:11:33.423307000 Z
|
||||
data_type: text
|
||||
|
||||
statistic_field_11:
|
||||
id: 11
|
||||
statistic_index_id: 4
|
||||
key: ageRange
|
||||
label: Tranche d'âge
|
||||
created_at: 2016-06-30 12:10:49.812226000 Z
|
||||
updated_at: 2016-06-30 12:10:49.812226000 Z
|
||||
data_type: text
|
||||
|
||||
|
||||
statistic_field_12:
|
||||
id: 12
|
||||
statistic_index_id: 4
|
||||
key: eventTheme
|
||||
label: Thématique
|
||||
created_at: 2016-06-30 12:10:49.814331000 Z
|
||||
updated_at: 2016-06-30 12:10:49.814331000 Z
|
||||
data_type: text
|
||||
|
||||
|
23
test/models/event_test.rb
Normal file
23
test/models/event_test.rb
Normal file
@ -0,0 +1,23 @@
|
||||
require 'test_helper'
|
||||
|
||||
class EventTest < ActiveSupport::TestCase
|
||||
test 'event must have a category' do
|
||||
e = Event.first
|
||||
assert_not_nil e.categories.first
|
||||
end
|
||||
|
||||
test 'event must have a theme' do
|
||||
e = Event.find(1)
|
||||
assert_not_empty e.themes
|
||||
end
|
||||
|
||||
test 'event must have an age range' do
|
||||
e = Event.find(2)
|
||||
assert_not_nil e.age_range.name
|
||||
end
|
||||
|
||||
test 'event must not have any age range' do
|
||||
e = Event.find(3)
|
||||
assert_nil e.age_range
|
||||
end
|
||||
end
|
Loading…
x
Reference in New Issue
Block a user