1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2024-12-01 12:24:28 +01:00

interface to create space availabilities

This commit is contained in:
Sylvain 2017-02-15 11:32:29 +01:00
parent 30454c4262
commit 1855935322
9 changed files with 183 additions and 99 deletions

View File

@ -150,6 +150,15 @@ Application.Controllers.controller "AdminCalendarController", ["$scope", "$state
resolve:
start: -> start
end: -> end
machinesPromise: ['Machine', (Machine)->
Machine.query().$promise
]
trainingsPromise: ['Training', (Training)->
Training.query().$promise
]
spacesPromise: ['Space', (Space)->
Space.query().$promise
]
# when the modal is closed, we send the slot to the server for saving
modalInstance.result.then (availability) ->
uiCalendarConfig.calendars.calendar.fullCalendar 'renderEvent',
@ -227,7 +236,8 @@ Application.Controllers.controller "AdminCalendarController", ["$scope", "$state
##
# Controller used in the slot creation modal window
##
Application.Controllers.controller 'CreateEventModalController', ["$scope", "$uibModalInstance", "moment", "start", "end", "Machine", "Availability", "Training", 'Tag', 'growl', '_t', ($scope, $uibModalInstance, moment, start, end, Machine, Availability, Training, Tag, growl, _t) ->
Application.Controllers.controller 'CreateEventModalController', ["$scope", "$uibModalInstance", "moment", "start", "end", "machinesPromise", "Availability", "trainingsPromise", "spacesPromise", 'Tag', 'growl', '_t'
, ($scope, $uibModalInstance, moment, start, end, machinesPromise, Availability, trainingsPromise, spacesPromise, Tag, growl, _t) ->
## $uibModal parameter
$scope.start = start
@ -236,14 +246,26 @@ Application.Controllers.controller 'CreateEventModalController', ["$scope", "$ui
$scope.end = end
## machines list
$scope.machines = []
$scope.machines = machinesPromise
## trainings list
$scope.trainings = []
$scope.trainings = trainingsPromise
## spaces list
$scope.spaces = spacesPromise
## machines associated with the created slot
$scope.selectedMachines = []
## training associated with the created slot
$scope.selectedTraining = null
## space associated with the created slot
$scope.selectedSpace = null
## UI step
$scope.step = 1
## the user is not able to edit the ending time of the availability, unless he set the type to 'training'
$scope.endDateReadOnly = true
@ -296,6 +318,23 @@ Application.Controllers.controller 'CreateEventModalController', ["$scope", "$ui
##
# Move the modal UI to the next step
##
$scope.next = ->
$scope.setNbTotalPlaces() if $scope.step == 1
$scope.step++
##
# Move the modal UI to the next step
##
$scope.previous = ->
$scope.step--
##
# Callback to cancel the slot creation
##
@ -304,22 +343,14 @@ Application.Controllers.controller 'CreateEventModalController', ["$scope", "$ui
##
# Switches the slot type : machine availability or training availability
##
$scope.changeAvailableType = ->
if $scope.availability.available_type == "machines"
$scope.availability.available_type = "training"
else
$scope.availability.available_type = "machines"
##
# For training avaiabilities, set the maximum number of people allowed to register on this slot
##
$scope.setNbTotalPlaces = ->
$scope.availability.nb_total_places = $scope.selectedTraining.nb_total_places
if $scope.availability.available_type == 'training'
$scope.availability.nb_total_places = $scope.selectedTraining.nb_total_places
else if $scope.availability.available_type == 'space'
$scope.availability.nb_total_places = $scope.selectedSpace.default_places
### PRIVATE SCOPE ###
@ -328,18 +359,11 @@ Application.Controllers.controller 'CreateEventModalController', ["$scope", "$ui
# Kind of constructor: these actions will be realized first when the controller is loaded
##
initialize = ->
Machine.query().$promise.then (data)->
$scope.machines = data.map (d) ->
id: d.id
name: d.name
Training.query().$promise.then (data)->
$scope.trainings = data.map (d) ->
id: d.id
name: d.name
nb_total_places: d.nb_total_places
if $scope.trainings.length > 0
$scope.selectedTraining = $scope.trainings[0]
$scope.setNbTotalPlaces()
if $scope.trainings.length > 0
$scope.selectedTraining = $scope.trainings[0]
if $scope.spaces.length > 0
$scope.selectedSpace = $scope.spaces[0]
Tag.query().$promise.then (data) ->
$scope.tags = data

View File

@ -5,6 +5,7 @@
//.bg-yellow { background-color: $yellow !important; }
.bg-token { background-color: rgba(230, 208, 137, 0.49); }
.bg-machine { background-color: $beige; }
.bg-space { background-color: $cyan }
.bg-formation { background-color: $violet; }
.bg-event { background-color: $japonica; }
.bg-atelier { background-color: $blue; }

View File

@ -176,6 +176,7 @@ p, .widget p {
.r-n { border-radius: 0 0 0 0; }
.p-xs { padding: 5px;}
.p-s { padding: 10px;}
.p-lg { padding: 30px; }
.p-l { padding: 16px; }

View File

@ -43,6 +43,7 @@ $blue: $brand-info;
$green: $brand-success;
$beige: #e4cd78;
$violet: #bd7ae9;
$cyan: #3fc7ff;
$japonica: #dd7e6b;
$border-color: #dddddd;
@ -767,7 +768,7 @@ $panel-footer-padding: $panel-heading-padding !default;
$panel-border-radius: $border-radius-large !default;
// add sleede
$panel-border: $border-color !default;
$panel-border: $border-color !default;
$panel-heading-bg: #fff !default;
$panel-footer-bg: #fff !default;

View File

@ -7,14 +7,15 @@
</div>
<div class="col-xs-10 col-sm-10 col-md-8 b-l b-r-md">
<section class="heading-title">
<h1 translate>{{ 'calendar_management' }}</h1>
<h1 translate>{{ 'calendar.calendar_management' }}</h1>
</section>
</div>
<div class="col-xs-12 col-sm-12 col-md-3 b-t hide-b-md">
<section class="heading-actions wrapper">
<span class="badge text-sm bg-formation m-t-sm" translate>{{ 'trainings' }}</span><br>
<span class="badge text-sm bg-machine" translate>{{ 'machines' }}</span>
<section class="heading-actions wrapper p-s">
<span class="badge text-sm bg-formation" translate>{{ 'calendar.trainings' }}</span><br>
<span class="badge text-sm bg-machine" translate>{{ 'calendar.machines' }}</span><br>
<span class="badge text-sm bg-space" translate>{{ 'calendar.spaces' }}</span>
</section>
</div>
@ -31,7 +32,7 @@
<div class="col-sm-12 col-md-12 col-lg-3">
<div class="widget panel b-a m m-t-lg">
<div class="panel-heading b-b small">
<h3 translate>{{ 'ongoing_reservations' }}</h3>
<h3 translate>{{ 'calendar.ongoing_reservations' }}</h3>
</div>
<div class="widget-content no-bg auto wrapper">
<ul class="list-unstyled" ng-if="reservations.length > 0">
@ -42,7 +43,7 @@
<span class="btn btn-warning btn-xs" ng-click="cancelBooking(r)" ng-if="!r.canceled_at"><i class="fa fa-times red"></i></span>
</li>
</ul>
<div ng-if="reservations.length == 0" translate>{{ 'no_reservations' }}</div>
<div ng-if="reservations.length == 0" translate>{{ 'calendar.no_reservations' }}</div>
</div>
</div>
</div>
@ -50,7 +51,7 @@
<div class="col-sm-12 col-md-12 col-lg-3" ng-if="availability.machine_ids.length > 0">
<div class="widget panel b-a m m-t-lg">
<div class="panel-heading b-b small">
<h3 translate>{{ 'machines' }}</h3>
<h3 translate>{{ 'calendar.machines' }}</h3>
</div>
<div class="widget-content no-bg auto wrapper">
<ul class="list-unstyled">

View File

@ -1,22 +1,41 @@
<div class="modal-header">
<h3 class="text-center red">
{{ 'DATE_slot' | translate:{DATE:(start | amDateFormat: 'LL')} }} {{start | amDateFormat:'LT'}} - {{end | amDateFormat:'LT'}}
{{ 'calendar.DATE_slot' | translate:{DATE:(start | amDateFormat: 'LL')} }} {{start | amDateFormat:'LT'}} - {{end | amDateFormat:'LT'}}
</h3>
</div>
<div class="modal-body">
<p class="text-center font-sbold" translate>{{ 'you_can_define_a_training_on_that_slot' }}</p>
<div>
<label class="checkbox-inline">
<input type="checkbox" ng-model="available_type" ng-change="changeAvailableType()"> {{ 'link_a_training' | translate }}
</label>
<div class="modal-body" ng-show="step === 1">
<label class="m-t-sm" translate>{{ 'calendar.what_kind_of_slot_do_you_want_to_create' }}</label>
<div class="form-group">
<div class="radio">
<label>
<input type="radio" id="training" name="available_type" value="training" ng-model="availability.available_type">
<span translate>{{ 'calendar.training' }}</span>
</label>
</div>
<div class="radio">
<label>
<input type="radio" id="machine" name="available_type" value="machines" ng-model="availability.available_type">
<span translate>{{ 'calendar.machine' }}</span>
</label>
</div>
<div class="radio">
<label>
<input type="radio" id="space" name="available_type" value="space" ng-model="availability.available_type">
<span translate>{{ 'calendar.space' }}</span>
</label>
</div>
</div>
</div>
<div class="modal-body" ng-show="step === 2">
<p class="text-center font-sbold m-t" ng-show="availability.available_type == 'machines'"><span class="underline" translate>{{ 'or_' }}</span> {{ '_select_some_machines' | translate }}</p>
<div ng-show="availability.available_type == 'machines'">
<p class="text-center font-sbold m-t-sm">{{ 'calendar.select_some_machines' | translate }}</p>
<div class="checkbox" ng-show="availability.available_type == 'machines'">
<label class="checkbox" ng-repeat="machine in machines">
<input type="checkbox" ng-click="toggleSelection(machine)"> {{machine.name}} <span class="text-xs">(id {{machine.id}})</span>
</label>
<div class="form-group m-l-xl">
<label class="checkbox" ng-repeat="machine in machines">
<input type="checkbox" ng-click="toggleSelection(machine)"> {{machine.name}} <span class="text-xs">(id {{machine.id}})</span>
</label>
</div>
</div>
<div ng-show="availability.available_type == 'training'">
@ -24,27 +43,42 @@
</select>
<div class="row m-t">
<div class="form-group">
<label class="col-sm-6 control-label" translate>{{ 'number_of_tickets' }}</label>
<label class="col-sm-6 control-label" for="nb_places_training" translate>{{ 'calendar.number_of_tickets' }}</label>
<div class="col-sm-6">
<input type="number" class="form-control" ng-model="availability.nb_total_places">
<input type="number" id="nb_places_training" class="form-control" ng-model="availability.nb_total_places">
</div>
</div>
</div>
</div>
<div id="timeAdjust" class="m-t-lg">
<p class="text-center font-sbold" translate>{{ 'adjust_the_opening_hours' }}</p>
<div ng-show="availability.available_type == 'space'">
<select ng-model="selectedSpace" class="form-control m-t-sm" ng-options="t.name for t in spaces" ng-change="setNbTotalPlaces()">
</select>
<div class="row m-t">
<div class="form-group">
<label class="col-sm-6 control-label" for="nb_places_space" translate>{{ 'calendar.number_of_tickets' }}</label>
<div class="col-sm-6">
<input type="number" id="nb_places_space" class="form-control" ng-model="availability.nb_total_places">
</div>
</div>
</div>
</div>
</div>
<div class="modal-body" ng-show="step === 3">
<div id="timeAdjust" class="m-t-sm">
<p class="text-center font-sbold" translate>{{ 'calendar.adjust_the_opening_hours' }}</p>
<div class="row">
<div class="col-md-3 col-md-offset-2">
<uib-timepicker ng-model="start" hour-step="timepickers.start.hstep" readonly-input="true" minute-step="timepickers.start.mstep" show-meridian="false"></uib-timepicker>
</div>
<span class="col-md-1 m-t-xl m-l" translate>{{ 'to_time' }}</span>
<span class="col-md-1 m-t-xl m-l" translate>{{ 'calendar.to_time' }}</span>
<fieldset ng-disabled="endDateReadOnly" class="col-md-5">
<uib-timepicker ng-model="end" hour-step="timepickers.end.hstep" readonly-input="true" minute-step="timepickers.end.mstep" show-meridian="false"></uib-timepicker>
</fieldset>
</div>
</div>
<div id="tagAssociate" class="m-t-lg">
<p class="text-center font-sbold" translate>{{ 'restrict_this_slot_with_labels_(optional)' }}</p>
<p class="text-center font-sbold" translate>{{ 'calendar.restrict_this_slot_with_labels_(optional)' }}</p>
<div class="row">
<div class="col-sm-12">
<ui-select multiple ng-model="availability.tag_ids" class="form-control">
@ -59,7 +93,13 @@
</div>
</div>
</div>
<div class="modal-footer">
<div class="modal-footer" ng-show="step < 3">
<button class="btn btn-info" ng-click="previous()" ng-disabled="step === 1" translate>{{ 'calendar.previous' }}</button>
<button class="btn btn-info" ng-click="next()" translate>{{ 'calendar.next' }}</button>
<button class="btn btn-default" ng-click="cancel()" translate>{{ 'cancel' }}</button>
</div>
<div class="modal-footer" ng-show="step === 3">
<button class="btn btn-info" ng-click="previous()" translate>{{ 'calendar.previous' }}</button>
<button class="btn btn-warning" ng-click="ok()" translate>{{ 'confirm' }}</button>
<button class="btn btn-default" ng-click="cancel()" translate>{{ 'cancel' }}</button>
</div>

View File

@ -1,4 +1,4 @@
json.array!(@spaces) do |space|
json.extract! space, :id, :name, :description, :slug
json.extract! space, :id, :name, :description, :slug, :default_places
json.space_image space.space_image.attachment.medium.url if space.space_image
end

View File

@ -13,28 +13,36 @@ en:
calendar:
# manage the trainings & machines slots
calendar_management: "Calendar management"
ongoing_reservations: "Ongoing reservations"
no_reservations: "No reservations"
do_you_really_want_to_cancel_the_USER_s_reservation_the_DATE_at_TIME_concerning_RESERVATION: "Do you really want to cancel the {USER}'s reservation, the {DATE} at {TIME}, concerning {RESERVATION}?" # messageFormat interpolation
reservation_cancellation_failed: "Reservation cancellation failed."
unable_to_remove_the_last_machine_of_the_slot_delete_the_slot_rather: "Unable to remove the last machine of the slot. Delete the slot rather."
do_you_really_want_to_remove_MACHINE_from_this_slot: "Do you really want to remove \"{MACHINE}\" from this slot?" # messageFormat interpolation
this_will_prevent_any_new_reservation_on_this_slot_but_wont_cancel_those_existing: "This will prevent any new reservation on this slot but won't cancel those existing."
beware_this_cannot_be_reverted: "Beware: this cannot be reverted."
the_machine_was_successfully_removed_from_the_slot: "The machine was successfully removed from the slot."
deletion_failed: "Deletion failed."
DATE_slot: "{{DATE}} slot:" # angular interpolation
you_can_define_a_training_on_that_slot: "You can define a training on that slot:"
link_a_training: "Link a training"
or_: "Or"
_select_some_machines: "select some machines"
number_of_tickets: "Number of tickets: "
adjust_the_opening_hours: "Adjust the opening hours"
restrict_this_slot_with_labels_(optional): "Restrict this slot with labels (optional)"
the_slot_START-END_has_been_successfully_deleted: "The slot {{START}} - {{END}} has been successfully deleted" # angular interpolation
unable_to_delete_the_slot_START-END_because_it_s_already_reserved_by_a_member: "Unable to delete the slot {{START}} - {{END}} because it's already reserved by a member" # angular interpolation
you_should_link_a_training_or_a_machine_to_this_slot: "You should link a training or a machine to this slot."
calendar:
calendar_management: "Calendar management"
trainings: "Trainings"
machines: "Machines"
spaces: "Spaces"
ongoing_reservations: "Ongoing reservations"
no_reservations: "No reservations"
do_you_really_want_to_cancel_the_USER_s_reservation_the_DATE_at_TIME_concerning_RESERVATION: "Do you really want to cancel the {USER}'s reservation, the {DATE} at {TIME}, concerning {RESERVATION}?" # messageFormat interpolation
reservation_cancellation_failed: "Reservation cancellation failed."
unable_to_remove_the_last_machine_of_the_slot_delete_the_slot_rather: "Unable to remove the last machine of the slot. Delete the slot rather."
do_you_really_want_to_remove_MACHINE_from_this_slot: "Do you really want to remove \"{MACHINE}\" from this slot?" # messageFormat interpolation
this_will_prevent_any_new_reservation_on_this_slot_but_wont_cancel_those_existing: "This will prevent any new reservation on this slot but won't cancel those existing."
beware_this_cannot_be_reverted: "Beware: this cannot be reverted."
the_machine_was_successfully_removed_from_the_slot: "The machine was successfully removed from the slot."
deletion_failed: "Deletion failed."
DATE_slot: "{{DATE}} slot:" # angular interpolation
what_kind_of_slot_do_you_want_to_create: "What kind of slot do you want to create?"
training: "Training"
machine: "Machine"
space: "Space"
next: "Next >"
previous: "< Previous"
select_some_machines: "Select some machines"
number_of_tickets: "Number of tickets: "
adjust_the_opening_hours: "Adjust the opening hours"
to_time: "to" # context: time. eg. "from 18:00 to 21:00"
restrict_this_slot_with_labels_(optional): "Restrict this slot with labels (optional)"
the_slot_START-END_has_been_successfully_deleted: "The slot {{START}} - {{END}} has been successfully deleted" # angular interpolation
unable_to_delete_the_slot_START-END_because_it_s_already_reserved_by_a_member: "Unable to delete the slot {{START}} - {{END}} because it's already reserved by a member" # angular interpolation
you_should_link_a_training_or_a_machine_to_this_slot: "You should link a training or a machine to this slot."
project_elements:
# management of the projects' components

View File

@ -13,28 +13,36 @@ fr:
calendar:
# gestion des créneaux machines et formations
calendar_management: "Gestion du calendrier"
ongoing_reservations: "Réservations en cours"
no_reservations: "Aucune réservation"
do_you_really_want_to_cancel_the_USER_s_reservation_the_DATE_at_TIME_concerning_RESERVATION: "Êtes-vous {GENDER, select, female{sûre} other{sûr}} de vouloir annuler la réservation de {USER}, le {DATE} à {TIME}, concernant {RESERVATION} ?" # messageFormat interpolation
reservation_cancellation_failed: "L'annulation de la réservation a échouée."
unable_to_remove_the_last_machine_of_the_slot_delete_the_slot_rather: "Impossible de supprimer la dernière machine du créneau. Supprimez plutôt le créneau."
do_you_really_want_to_remove_MACHINE_from_this_slot: "Êtes-vous {GENDER, select, female{sûre} other{sûr}} de vouloir retirer \"{MACHINE}\" de ce créneau ?" # messageFormat interpolation
this_will_prevent_any_new_reservation_on_this_slot_but_wont_cancel_those_existing: "Ceci interdira toute nouvelle réservation de cette machine sur ce créneau mais n'annulera pas les réservation existantes."
beware_this_cannot_be_reverted: "Attention : ceci n'est pas réversible."
the_machine_was_successfully_removed_from_the_slot: "La machine a bien été supprimée du créneau."
deletion_failed: "La suppression a échouée."
DATE_slot: "Créneau du {{DATE}} :" # angular interpolation
you_can_define_a_training_on_that_slot: "Vous pouvez définir une formation sur ce créneau :"
link_a_training: "Associer une formation"
or_: "Ou"
_select_some_machines: "sélectionner des machines"
number_of_tickets: "Nombre de places : "
adjust_the_opening_hours: "Ajuster l'horaire"
restrict_this_slot_with_labels_(optional): "Restreindre ce créneau avec des étiquettes (optionnel)"
the_slot_START-END_has_been_successfully_deleted: "Le créneau {{START}} - {{END}} a bien été supprimé" # angular interpolation
unable_to_delete_the_slot_START-END_because_it_s_already_reserved_by_a_member: "Le créneau {{START}} - {{END}} n'a pu être supprimé car il est déjà réservé par un membre" # angular interpolation
you_should_link_a_training_or_a_machine_to_this_slot: "Vous devriez associer une formation ou une machine à ce créneau."
calendar:
calendar_management: "Gestion du calendrier"
trainings: "Formations"
machines: "Machines"
spaces: "Espaces"
ongoing_reservations: "Réservations en cours"
no_reservations: "Aucune réservation"
do_you_really_want_to_cancel_the_USER_s_reservation_the_DATE_at_TIME_concerning_RESERVATION: "Êtes-vous {GENDER, select, female{sûre} other{sûr}} de vouloir annuler la réservation de {USER}, le {DATE} à {TIME}, concernant {RESERVATION} ?" # messageFormat interpolation
reservation_cancellation_failed: "L'annulation de la réservation a échouée."
unable_to_remove_the_last_machine_of_the_slot_delete_the_slot_rather: "Impossible de supprimer la dernière machine du créneau. Supprimez plutôt le créneau."
do_you_really_want_to_remove_MACHINE_from_this_slot: "Êtes-vous {GENDER, select, female{sûre} other{sûr}} de vouloir retirer \"{MACHINE}\" de ce créneau ?" # messageFormat interpolation
this_will_prevent_any_new_reservation_on_this_slot_but_wont_cancel_those_existing: "Ceci interdira toute nouvelle réservation de cette machine sur ce créneau mais n'annulera pas les réservation existantes."
beware_this_cannot_be_reverted: "Attention : ceci n'est pas réversible."
the_machine_was_successfully_removed_from_the_slot: "La machine a bien été supprimée du créneau."
deletion_failed: "La suppression a échouée."
DATE_slot: "Créneau du {{DATE}} :" # angular interpolation
what_kind_of_slot_do_you_want_to_create: "Quel type de créneau voulez-vous créer ?"
training: "Formation"
machine: "Machine"
space: "Espace"
next: "Suivant >"
previous: "< Précédent"
select_some_machines: "Sélectionnez des machines"
number_of_tickets: "Nombre de places : "
adjust_the_opening_hours: "Ajuster l'horaire"
to_time: "à" # context: time. eg. "from 18:00 to 21:00"
restrict_this_slot_with_labels_(optional): "Restreindre ce créneau avec des étiquettes (optionnel)"
the_slot_START-END_has_been_successfully_deleted: "Le créneau {{START}} - {{END}} a bien été supprimé" # angular interpolation
unable_to_delete_the_slot_START-END_because_it_s_already_reserved_by_a_member: "Le créneau {{START}} - {{END}} n'a pu être supprimé car il est déjà réservé par un membre" # angular interpolation
you_should_link_a_training_or_a_machine_to_this_slot: "Vous devriez associer une formation ou une machine à ce créneau."
project_elements:
# gestion des éléments constituant les projets