mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-01-18 07:52:23 +01:00
(ui) option to disable the machines module
This commit is contained in:
parent
249285ea51
commit
ac1d518ddc
@ -2,6 +2,7 @@
|
||||
|
||||
## next deploy
|
||||
|
||||
- Option to disable the 'machines' module
|
||||
- Ability to define social networks for the FabLab "about page"
|
||||
- Support for OpenID Connect in Sign-Sign-On authentication providers
|
||||
- ICS file attached to the reservation notification email
|
||||
@ -20,10 +21,12 @@
|
||||
- Webpack overlay will now report eslint issues
|
||||
- Linted all code according to eslint rules
|
||||
- when generating an avoir, the option "by_wallet" is not present anymore if wallet module is off
|
||||
- Fix a bug: when enabled, the statistics module is still not shown in the menu
|
||||
- Fix a bug: Refused to connect to 'wss://localhost:3035/ws' when using a https tunnel in development mode
|
||||
- Fix a bug: edge case of birthday in the future in seeds.rb, we should use Date.current instead of DateTime.current since birthday is a date (see https://github.com/sleede/fab-manager/issues/344)
|
||||
- Fix a security issue: updated ruby to 2.6.10 to fix [CVE-2022-28739](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-28739)
|
||||
- Fix a security issue: updated rails to 5.2.7.1 to fix [CVE-2022-22577](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-22577) and [CVE-2022-27777](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-27777)
|
||||
- [TODO DEPLOY] `rails db:seed`
|
||||
|
||||
## v5.3.13 2022 May 02
|
||||
|
||||
|
@ -621,7 +621,7 @@ Application.Controllers.controller('CreateEventModalController', ['$scope', '$ui
|
||||
$scope.availability = {
|
||||
start_at: start,
|
||||
end_at: end,
|
||||
available_type: 'machines', // default
|
||||
available_type: $scope.$root.modules.machines ? 'machines' : undefined, // default to machines if enabled
|
||||
tag_ids: [],
|
||||
is_recurrent: false,
|
||||
period: 'week',
|
||||
@ -927,6 +927,9 @@ Application.Controllers.controller('CreateEventModalController', ['$scope', '$ui
|
||||
* Initialize some settings, depending on the availability type, before continuing to step 2 (select a machine/training/space)
|
||||
*/
|
||||
const validateType = function () {
|
||||
if ($scope.availability.available_type === null || $scope.availability.available_type === undefined) {
|
||||
return growl.error(_t('app.admin.calendar.select_type'));
|
||||
}
|
||||
$scope.setNbTotalPlaces();
|
||||
if ($scope.availability.available_type === 'training') {
|
||||
$scope.availability.slot_duration = undefined;
|
||||
|
@ -125,7 +125,8 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
|
||||
$scope.hiddenTab = function (tab) {
|
||||
if (tab.graph) {
|
||||
return !((tab.es_type_key === 'subscription' && !$rootScope.modules.plans) ||
|
||||
(tab.es_type_key === 'training' && !$rootScope.modules.trainings));
|
||||
(tab.es_type_key === 'training' && !$rootScope.modules.trainings) ||
|
||||
(tab.es_type_key === 'machine' && !$rootScope.modules.machines));
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
@ -685,14 +685,16 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
placement: 'bottom'
|
||||
});
|
||||
}
|
||||
uitour.createStep({
|
||||
selector: '.plans-pricing .machines-tab',
|
||||
stepId: 'machines',
|
||||
order: 3,
|
||||
title: _t('app.admin.tour.pricing.machines.title'),
|
||||
content: _t('app.admin.tour.pricing.machines.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
if ($scope.$root.modules.machines) {
|
||||
uitour.createStep({
|
||||
selector: '.plans-pricing .machines-tab',
|
||||
stepId: 'machines',
|
||||
order: 3,
|
||||
title: _t('app.admin.tour.pricing.machines.title'),
|
||||
content: _t('app.admin.tour.pricing.machines.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
}
|
||||
if ($scope.$root.modules.spaces) {
|
||||
uitour.createStep({
|
||||
selector: '.plans-pricing .spaces-tab',
|
||||
|
@ -186,7 +186,8 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
if (tab.table) {
|
||||
return ((tab.es_type_key === 'subscription' && !$rootScope.modules.plans) ||
|
||||
(tab.es_type_key === 'training' && !$rootScope.modules.trainings) ||
|
||||
(tab.es_type_key === 'space' && !$rootScope.modules.spaces)
|
||||
(tab.es_type_key === 'space' && !$rootScope.modules.spaces) ||
|
||||
(tab.es_type_key === 'machine' && !$rootScope.modules.machines)
|
||||
);
|
||||
} else {
|
||||
return true;
|
||||
|
@ -23,12 +23,30 @@ Application.Controllers.controller('MainNavController', ['$scope', 'settingsProm
|
||||
class: 'home-link'
|
||||
},
|
||||
{ class: 'menu-spacer' },
|
||||
{
|
||||
$scope.$root.modules.publicAgenda && {
|
||||
state: 'app.public.calendar',
|
||||
linkText: 'app.public.common.public_calendar',
|
||||
linkIcon: 'calendar',
|
||||
class: 'public-calendar-link'
|
||||
},
|
||||
$scope.$root.modules.machines && {
|
||||
state: 'app.public.machines_list',
|
||||
linkText: 'app.public.common.reserve_a_machine',
|
||||
linkIcon: 'cogs',
|
||||
class: 'reserve-machine-link'
|
||||
},
|
||||
$scope.$root.modules.trainings && {
|
||||
state: 'app.public.trainings_list',
|
||||
linkText: 'app.public.common.trainings_registrations',
|
||||
linkIcon: 'graduation-cap',
|
||||
class: 'reserve-training-link'
|
||||
},
|
||||
$scope.$root.modules.spaces && {
|
||||
state: 'app.public.spaces_list',
|
||||
linkText: 'app.public.common.reserve_a_space',
|
||||
linkIcon: 'rocket',
|
||||
class: 'reserve-space-link'
|
||||
},
|
||||
{
|
||||
state: 'app.public.events_list',
|
||||
linkText: 'app.public.common.events_registrations',
|
||||
@ -42,60 +60,40 @@ Application.Controllers.controller('MainNavController', ['$scope', 'settingsProm
|
||||
linkIcon: 'th',
|
||||
class: 'projects-gallery-link'
|
||||
},
|
||||
{ class: 'menu-spacer' }
|
||||
|
||||
];
|
||||
|
||||
if ($scope.$root.modules.plans) {
|
||||
$scope.navLinks.push({
|
||||
$scope.$root.modules.plans && { class: 'menu-spacer' },
|
||||
$scope.$root.modules.plans && {
|
||||
state: 'app.public.plans',
|
||||
linkText: 'app.public.common.subscriptions',
|
||||
linkIcon: 'credit-card',
|
||||
class: 'plans-link'
|
||||
});
|
||||
}
|
||||
|
||||
if ($scope.$root.modules.trainings) {
|
||||
$scope.navLinks.splice(4, 0, {
|
||||
state: 'app.public.trainings_list',
|
||||
linkText: 'app.public.common.trainings_registrations',
|
||||
linkIcon: 'graduation-cap',
|
||||
class: 'reserve-training-link'
|
||||
});
|
||||
}
|
||||
|
||||
if ($scope.$root.modules.spaces) {
|
||||
$scope.navLinks.splice(4, 0, {
|
||||
state: 'app.public.spaces_list',
|
||||
linkText: 'app.public.common.reserve_a_space',
|
||||
linkIcon: 'rocket',
|
||||
class: 'reserve-space-link'
|
||||
});
|
||||
}
|
||||
|
||||
if ($scope.$root.modules.publicAgenda) {
|
||||
$scope.navLinks.splice(2, 0, {
|
||||
state: 'app.public.calendar',
|
||||
linkText: 'app.public.common.public_calendar',
|
||||
linkIcon: 'calendar',
|
||||
class: 'public-calendar-link'
|
||||
});
|
||||
}
|
||||
}
|
||||
].filter(Boolean);
|
||||
|
||||
Fablab.adminNavLinks = Fablab.adminNavLinks || [];
|
||||
const adminNavLinks = [
|
||||
$scope.adminNavLinks = [
|
||||
{
|
||||
state: 'app.admin.calendar',
|
||||
linkText: 'app.public.common.manage_the_calendar',
|
||||
linkIcon: 'calendar',
|
||||
authorizedRoles: ['admin', 'manager']
|
||||
},
|
||||
{
|
||||
$scope.$root.modules.machines && {
|
||||
state: 'app.public.machines_list',
|
||||
linkText: 'app.public.common.manage_the_machines',
|
||||
linkIcon: 'cogs',
|
||||
authorizedRoles: ['admin', 'manager']
|
||||
},
|
||||
$scope.$root.modules.trainings && {
|
||||
state: 'app.admin.trainings',
|
||||
linkText: 'app.public.common.trainings_monitoring',
|
||||
linkIcon: 'graduation-cap',
|
||||
authorizedRoles: ['admin', 'manager']
|
||||
},
|
||||
$scope.$root.modules.spaces && {
|
||||
state: 'app.public.spaces_list',
|
||||
linkText: 'app.public.common.manage_the_spaces',
|
||||
linkIcon: 'rocket'
|
||||
},
|
||||
{
|
||||
state: 'app.admin.events',
|
||||
linkText: 'app.public.common.manage_the_events',
|
||||
@ -121,6 +119,12 @@ Application.Controllers.controller('MainNavController', ['$scope', 'settingsProm
|
||||
linkIcon: 'file-pdf-o',
|
||||
authorizedRoles: ['admin', 'manager']
|
||||
},
|
||||
$scope.$root.modules.statistics && {
|
||||
state: 'app.admin.statistics',
|
||||
linkText: 'app.public.common.statistics',
|
||||
linkIcon: 'bar-chart-o',
|
||||
authorizedRoles: ['admin']
|
||||
},
|
||||
{
|
||||
class: 'menu-spacer',
|
||||
authorizedRoles: ['admin']
|
||||
@ -143,35 +147,7 @@ Application.Controllers.controller('MainNavController', ['$scope', 'settingsProm
|
||||
linkIcon: 'cloud',
|
||||
authorizedRoles: ['admin']
|
||||
}
|
||||
].concat(Fablab.adminNavLinks);
|
||||
|
||||
$scope.adminNavLinks = adminNavLinks;
|
||||
|
||||
if ($scope.$root.modules.trainings) {
|
||||
$scope.adminNavLinks.splice(3, 0, {
|
||||
state: 'app.admin.trainings',
|
||||
linkText: 'app.public.common.trainings_monitoring',
|
||||
linkIcon: 'graduation-cap',
|
||||
authorizedRoles: ['admin', 'manager']
|
||||
});
|
||||
}
|
||||
|
||||
if ($scope.$root.modules.spaces) {
|
||||
$scope.adminNavLinks.splice(3, 0, {
|
||||
state: 'app.public.spaces_list',
|
||||
linkText: 'app.public.common.manage_the_spaces',
|
||||
linkIcon: 'rocket'
|
||||
});
|
||||
}
|
||||
|
||||
if ($scope.$root.modules.statistics) {
|
||||
$scope.adminNavLinks.splice($scope.$root.modules.spaces ? 9 : 8, 0, {
|
||||
state: 'app.admin.statistics',
|
||||
linkText: 'app.public.common.statistics',
|
||||
linkIcon: 'bar-chart-o',
|
||||
authorizedRoles: ['admin']
|
||||
});
|
||||
}
|
||||
].filter(Boolean).concat(Fablab.adminNavLinks);
|
||||
|
||||
/**
|
||||
* Returns the current state of the public registration setting (allowed/blocked).
|
||||
|
@ -132,7 +132,8 @@ export enum SettingName {
|
||||
SocialsEchosciences = 'echosciences',
|
||||
SocialsPinterest = 'pinterest',
|
||||
SocialsLastfm = 'lastfm',
|
||||
SocialsFlickr = 'flickr'
|
||||
SocialsFlickr = 'flickr',
|
||||
MachinesModule = 'machines_module',
|
||||
}
|
||||
|
||||
export type SettingValue = string|boolean|number;
|
||||
|
@ -27,7 +27,7 @@ angular.module('application.router', ['ui.router'])
|
||||
logoFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'logo-file' }).$promise; }],
|
||||
logoBlackFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'logo-black-file' }).$promise; }],
|
||||
sharedTranslations: ['Translations', function (Translations) { return Translations.query(['app.shared', 'app.public.common']).$promise; }],
|
||||
modulesPromise: ['Setting', function (Setting) { return Setting.query({ names: "['spaces_module', 'plans_module', 'invoicing_module', 'wallet_module', 'statistics_module', 'trainings_module', 'public_agenda_module']" }).$promise; }],
|
||||
modulesPromise: ['Setting', function (Setting) { return Setting.query({ names: "['machines_module', 'spaces_module', 'plans_module', 'invoicing_module', 'wallet_module', 'statistics_module', 'trainings_module', 'public_agenda_module']" }).$promise; }],
|
||||
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['public_registrations']" }).$promise; }]
|
||||
},
|
||||
onEnter: ['$rootScope', 'logoFile', 'logoBlackFile', 'modulesPromise', 'CSRF', function ($rootScope, logoFile, logoBlackFile, modulesPromise, CSRF) {
|
||||
@ -37,6 +37,7 @@ angular.module('application.router', ['ui.router'])
|
||||
$rootScope.logo = logoFile.custom_asset;
|
||||
$rootScope.logoBlack = logoBlackFile.custom_asset;
|
||||
$rootScope.modules = {
|
||||
machines: (modulesPromise.machines_module === 'true'),
|
||||
spaces: (modulesPromise.spaces_module === 'true'),
|
||||
plans: (modulesPromise.plans_module === 'true'),
|
||||
trainings: (modulesPromise.trainings_module === 'true'),
|
||||
@ -1071,7 +1072,7 @@ angular.module('application.router', ['ui.router'])
|
||||
"'renew_pack_threshold', 'pack_only_for_subscription', 'overlapping_categories', 'public_registrations'," +
|
||||
"'extended_prices_in_same_day', 'recaptcha_site_key', 'recaptcha_secret_key', 'user_validation_required', 'user_validation_required_machine', " +
|
||||
"'user_validation_required_training', 'user_validation_required_subscription', 'user_validation_required_space'," +
|
||||
"'user_validation_required_event', 'user_validation_required_pack', 'user_validation_required_list']"
|
||||
"'user_validation_required_event', 'user_validation_required_pack', 'user_validation_required_list', 'machines_module']"
|
||||
}).$promise;
|
||||
}],
|
||||
privacyDraftsPromise: ['Setting', function (Setting) { return Setting.get({ name: 'privacy_draft', history: true }).$promise; }],
|
||||
|
@ -37,7 +37,7 @@
|
||||
<div class="calendar-legend-group">
|
||||
<span class="calendar-legend-item text-sm border-formation" translate>{{ 'app.admin.calendar.trainings' }}</span><br>
|
||||
<span class="calendar-legend-item text-sm border-machine" translate>{{ 'app.admin.calendar.machines' }}</span><br>
|
||||
<span class="calendar-legend-item text-sm border-space" ng-show="$root.modules.spaces" translate>{{ 'app.admin.calendar.spaces' }}</span>
|
||||
<span class="calendar-legend-item text-sm border-space" translate>{{ 'app.admin.calendar.spaces' }}</span>
|
||||
<span class="calendar-legend-item text-sm border-event" ng-show="eventsInCalendar" translate>{{ 'app.admin.calendar.events' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -12,7 +12,7 @@
|
||||
<span translate>{{ 'app.admin.calendar.training' }}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<div class="radio" ng-show="$root.modules.machines">
|
||||
<label>
|
||||
<input type="radio" id="machine" name="available_type" value="machines" ng-model="availability.available_type">
|
||||
<span translate>{{ 'app.admin.calendar.machine' }}</span>
|
||||
@ -24,6 +24,9 @@
|
||||
<span translate>{{ 'app.admin.calendar.space' }}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="alert alert-warning" ng-hide="$root.modules.spaces || $root.modules.machines || $root.modules.trainings">
|
||||
<span translate>{{ 'app.admin.calendar.no_modules_available' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-body" ng-show="step === 2">
|
||||
|
@ -52,47 +52,52 @@
|
||||
<option value=""></option>
|
||||
</select>
|
||||
</div>
|
||||
<h3 translate>{{ 'app.admin.plans.edit.machines' }}</h3>
|
||||
<table class="table">
|
||||
|
||||
<div ng-show="$root.modules.machines">
|
||||
<h3 translate>{{ 'app.admin.plans.edit.machines' }}</h3>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<th translate>{{ 'app.admin.plans.edit.machine' }}</th>
|
||||
<th translate>{{ 'app.admin.plans.edit.hourly_rate' }}</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
<tr ng-repeat="price in plan.prices" ng-if="price.priceable_type === 'Machine'" ng-hide="getMachine(price.priceable_id).disabled">
|
||||
<td style="width: 60%;">{{ getMachine(price.priceable_id).name }} (id {{ price.priceable_id }}) *</td>
|
||||
<td>
|
||||
<div class="input-group" ng-class="{'has-error': planForm['plan[prices_attributes][][amount]'].$dirty && planForm['plan[prices_attributes][][amount]'].$invalid}">
|
||||
<span class="input-group-addon">{{currencySymbol}}</span>
|
||||
<input type="number" class="form-control" name="plan[prices_attributes][][amount]" ng-value="price.amount" required="true"/>
|
||||
<input type="hidden" class="form-control" name="plan[prices_attributes][][id]" ng-value="price.id"/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div ng-show="$root.modules.spaces">
|
||||
<h3 translate>{{ 'app.admin.plans.edit.spaces' }}</h3>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<th translate>{{ 'app.admin.plans.edit.machine' }}</th>
|
||||
<th translate>{{ 'app.admin.plans.edit.hourly_rate' }}</th>
|
||||
<th translate>{{ 'app.admin.plans.edit.space' }}</th>
|
||||
<th translate>{{ 'app.admin.plans.edit.hourly_rate' }}</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
<tr ng-repeat="price in plan.prices" ng-if="price.priceable_type === 'Machine'" ng-hide="getMachine(price.priceable_id).disabled">
|
||||
<td style="width: 60%;">{{ getMachine(price.priceable_id).name }} (id {{ price.priceable_id }}) *</td>
|
||||
<td>
|
||||
<div class="input-group" ng-class="{'has-error': planForm['plan[prices_attributes][][amount]'].$dirty && planForm['plan[prices_attributes][][amount]'].$invalid}">
|
||||
<span class="input-group-addon">{{currencySymbol}}</span>
|
||||
<input type="number" class="form-control" name="plan[prices_attributes][][amount]" ng-value="price.amount" required="true"/>
|
||||
<input type="hidden" class="form-control" name="plan[prices_attributes][][id]" ng-value="price.id"/>
|
||||
</div>
|
||||
</td>
|
||||
<tr ng-repeat="price in plan.prices" ng-if="price.priceable_type === 'Space'" ng-hide="getSpace(price.priceable_id).disabled">
|
||||
<td style="width: 60%;">{{ getSpace(price.priceable_id).name }} *</td>
|
||||
<td>
|
||||
<div class="input-group" ng-class="{'has-error': planForm['plan[prices_attributes][][amount]'].$dirty && planForm['plan[prices_attributes][][amount]'].$invalid}">
|
||||
<span class="input-group-addon">{{currencySymbol}}</span>
|
||||
<input type="number" class="form-control" name="plan[prices_attributes][][amount]" ng-value="price.amount" required="true"/>
|
||||
<input type="hidden" class="form-control" name="plan[prices_attributes][][id]" ng-value="price.id"/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h3 ng-show="$root.modules.spaces" translate>{{ 'app.admin.plans.edit.spaces' }}</h3>
|
||||
<table class="table" ng-show="$root.modules.spaces">
|
||||
<thead>
|
||||
<th translate>{{ 'app.admin.plans.edit.space' }}</th>
|
||||
<th translate>{{ 'app.admin.plans.edit.hourly_rate' }}</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
<tr ng-repeat="price in plan.prices" ng-if="price.priceable_type === 'Space'" ng-hide="getSpace(price.priceable_id).disabled">
|
||||
<td style="width: 60%;">{{ getSpace(price.priceable_id).name }} *</td>
|
||||
<td>
|
||||
<div class="input-group" ng-class="{'has-error': planForm['plan[prices_attributes][][amount]'].$dirty && planForm['plan[prices_attributes][][amount]'].$invalid}">
|
||||
<span class="input-group-addon">{{currencySymbol}}</span>
|
||||
<input type="number" class="form-control" name="plan[prices_attributes][][amount]" ng-value="price.amount" required="true"/>
|
||||
<input type="hidden" class="form-control" name="plan[prices_attributes][][id]" ng-value="price.id"/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</table>
|
||||
</div>
|
||||
<ul>
|
||||
<li ng-repeat="(key, errors) in planForm.$error track by $index"> <strong>{{ key }}</strong> errors
|
||||
<ul>
|
||||
|
@ -1,149 +1,155 @@
|
||||
<h2 class="m-t-lg" translate>{{ 'app.admin.pricing.trainings' }}</h2>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:20%" translate>{{ 'app.admin.pricing.subscription' }}</th>
|
||||
<th style="width:10%" translate>{{ 'app.admin.pricing.credits' }}</th>
|
||||
<th style="width:50%" translate>{{ 'app.admin.pricing.related_trainings' }}</th>
|
||||
<th style="width:20%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<div ng-show="$root.modules.trainings">
|
||||
<h2 class="m-t-lg" translate>{{ 'app.admin.pricing.trainings' }}</h2>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:20%" translate>{{ 'app.admin.pricing.subscription' }}</th>
|
||||
<th style="width:10%" translate>{{ 'app.admin.pricing.credits' }}</th>
|
||||
<th style="width:50%" translate>{{ 'app.admin.pricing.related_trainings' }}</th>
|
||||
<th style="width:20%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
<tr ng-repeat="(planId, trainingIds) in trainingCreditsGroups" ng-init="plan = getPlanFromId(planId)" ng-hide="plan.disabled">
|
||||
<td>
|
||||
{{ plan | humanReadablePlanName: groups }}
|
||||
</td>
|
||||
<td>
|
||||
<span editable-text="plan.training_credit_nb" e-form="rowform" e-name="training_credits" e-required>
|
||||
{{ plan.training_credit_nb }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span editable-checklist="trainingIds" e-form="rowform" e-name="training_ids" e-ng-options="t.id as t.name for t in trainings" e-required>
|
||||
{{ showTrainings(trainingIds) }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<form editable-form name="rowform" onbeforesave="saveTrainingCredits($data, planId)" ng-show="rowform.$visible" class="form-buttons form-inline" shown="inserted == trainingIds">
|
||||
<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="cancelTrainingCredit(rowform)" 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> {{ 'app.shared.buttons.edit' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2 class="m-t-lg" translate>{{ 'app.admin.pricing.machines' }}</h2>
|
||||
<div class="btn-group m-t-md m-b-md">
|
||||
<button type="button" class="btn btn-warning" ng-click="addMachineCredit($event)" translate>{{ 'app.admin.pricing.add_a_machine_credit' }}</button>
|
||||
<tr ng-repeat="(planId, trainingIds) in trainingCreditsGroups" ng-init="plan = getPlanFromId(planId)" ng-hide="plan.disabled">
|
||||
<td>
|
||||
{{ plan | humanReadablePlanName: groups }}
|
||||
</td>
|
||||
<td>
|
||||
<span editable-text="plan.training_credit_nb" e-form="rowform" e-name="training_credits" e-required>
|
||||
{{ plan.training_credit_nb }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span editable-checklist="trainingIds" e-form="rowform" e-name="training_ids" e-ng-options="t.id as t.name for t in trainings" e-required>
|
||||
{{ showTrainings(trainingIds) }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<form editable-form name="rowform" onbeforesave="saveTrainingCredits($data, planId)" ng-show="rowform.$visible" class="form-buttons form-inline" shown="inserted == trainingIds">
|
||||
<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="cancelTrainingCredit(rowform)" 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> {{ 'app.shared.buttons.edit' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:20%" translate>{{ 'app.admin.pricing.machine' }}</th>
|
||||
<th style="width:10%">{{ 'app.admin.pricing.hours' | translate:{DURATION:slotDuration} }}</th>
|
||||
<th style="width:50%" translate>{{ 'app.admin.pricing.related_subscriptions' }}</th>
|
||||
<th style="width:20%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="mc in machineCredits" ng-hide="getPlanFromId(mc.plan_id).disabled || getCreditable(mc).disabled">
|
||||
<td>
|
||||
<span editable-select="mc.creditable_id" e-name="creditable_id" e-form="rowform" e-ng-options="m.id as m.name+' ( id. '+m.id+' )' for m in enabledMachines" e-required>
|
||||
{{ showCreditableName(mc) }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span editable-number="mc.hours" e-name="hours" e-form="rowform" e-required>
|
||||
{{ mc.hours }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span editable-select="mc.plan_id" e-ng-options="p.id as humanReadablePlanName(p, groups, 'short') for p in enabledPlans" e-name="plan_id" e-form="rowform">
|
||||
{{ getPlanFromId(mc.plan_id) | humanReadablePlanName: groups: 'short' }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<form editable-form name="rowform" onbeforesave="saveMachineCredit($data, mc.id)" ng-show="rowform.$visible" class="form-buttons form-inline" shown="inserted == mc">
|
||||
<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="cancelMachineCredit(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> {{ 'app.shared.buttons.edit' | translate }}
|
||||
</button>
|
||||
<button class="btn btn-danger" ng-click="removeMachineCredit($index)">
|
||||
<i class="fa fa-trash-o"></i> {{ 'app.shared.buttons.delete' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div ng-show="$root.modules.machines">
|
||||
<h2 class="m-t-lg" translate>{{ 'app.admin.pricing.machines' }}</h2>
|
||||
<div class="btn-group m-t-md m-b-md">
|
||||
<button type="button" class="btn btn-warning" ng-click="addMachineCredit($event)" translate>{{ 'app.admin.pricing.add_a_machine_credit' }}</button>
|
||||
</div>
|
||||
|
||||
<h2 ng-show="$root.modules.spaces" class="m-t-lg" translate>{{ 'app.admin.pricing.spaces' }}</h2>
|
||||
<div ng-show="$root.modules.spaces" class="btn-group m-t-md m-b-md">
|
||||
<button type="button" class="btn btn-warning" ng-click="addSpaceCredit($event)" translate>{{ 'app.admin.pricing.add_a_space_credit' }}</button>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:20%" translate>{{ 'app.admin.pricing.machine' }}</th>
|
||||
<th style="width:10%">{{ 'app.admin.pricing.hours' | translate:{DURATION:slotDuration} }}</th>
|
||||
<th style="width:50%" translate>{{ 'app.admin.pricing.related_subscriptions' }}</th>
|
||||
<th style="width:20%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="mc in machineCredits" ng-hide="getPlanFromId(mc.plan_id).disabled || getCreditable(mc).disabled">
|
||||
<td>
|
||||
<span editable-select="mc.creditable_id" e-name="creditable_id" e-form="rowform" e-ng-options="m.id as m.name+' ( id. '+m.id+' )' for m in enabledMachines" e-required>
|
||||
{{ showCreditableName(mc) }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span editable-number="mc.hours" e-name="hours" e-form="rowform" e-required>
|
||||
{{ mc.hours }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span editable-select="mc.plan_id" e-ng-options="p.id as humanReadablePlanName(p, groups, 'short') for p in enabledPlans" e-name="plan_id" e-form="rowform">
|
||||
{{ getPlanFromId(mc.plan_id) | humanReadablePlanName: groups: 'short' }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<form editable-form name="rowform" onbeforesave="saveMachineCredit($data, mc.id)" ng-show="rowform.$visible" class="form-buttons form-inline" shown="inserted == mc">
|
||||
<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="cancelMachineCredit(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> {{ 'app.shared.buttons.edit' | translate }}
|
||||
</button>
|
||||
<button class="btn btn-danger" ng-click="removeMachineCredit($index)">
|
||||
<i class="fa fa-trash-o"></i> {{ 'app.shared.buttons.delete' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div ng-show="$root.modules.spaces">
|
||||
<h2 class="m-t-lg" translate>{{ 'app.admin.pricing.spaces' }}</h2>
|
||||
<div class="btn-group m-t-md m-b-md">
|
||||
<button type="button" class="btn btn-warning" ng-click="addSpaceCredit($event)" translate>{{ 'app.admin.pricing.add_a_space_credit' }}</button>
|
||||
</div>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:20%" translate>{{ 'app.admin.pricing.space' }}</th>
|
||||
<th style="width:10%">{{ 'app.admin.pricing.hours' | translate:{DURATION:slotDuration} }}</th>
|
||||
<th style="width:50%" translate>{{ 'app.admin.pricing.related_subscriptions' }}</th>
|
||||
<th style="width:20%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="sc in spaceCredits" ng-hide="getPlanFromId(sc.plan_id).disabled || getCreditable(sc).disabled">
|
||||
<td>
|
||||
<span editable-select="sc.creditable_id" e-name="creditable_id" e-form="rowform" e-ng-options="s.id as s.name for s in enabledSpaces" e-required>
|
||||
{{ showCreditableName(sc) }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span editable-number="sc.hours" e-name="hours" e-form="rowform" e-required>
|
||||
{{ sc.hours }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span editable-select="sc.plan_id" e-ng-options="p.id as humanReadablePlanName(p, groups, 'short') for p in enabledPlans" e-name="plan_id" e-form="rowform">
|
||||
{{ getPlanFromId(sc.plan_id) | humanReadablePlanName: groups: 'short' }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<form editable-form name="rowform" onbeforesave="saveSpaceCredit($data, sc.id)" ng-show="rowform.$visible" class="form-buttons form-inline" shown="inserted == sc">
|
||||
<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="cancelSpaceCredit(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> {{ 'app.shared.buttons.edit' | translate }}
|
||||
</button>
|
||||
<button class="btn btn-danger" ng-click="removeSpaceCredit($index)">
|
||||
<i class="fa fa-trash-o"></i> {{ 'app.shared.buttons.delete' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<table ng-show="$root.modules.spaces" class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:20%" translate>{{ 'app.admin.pricing.space' }}</th>
|
||||
<th style="width:10%">{{ 'app.admin.pricing.hours' | translate:{DURATION:slotDuration} }}</th>
|
||||
<th style="width:50%" translate>{{ 'app.admin.pricing.related_subscriptions' }}</th>
|
||||
<th style="width:20%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="sc in spaceCredits" ng-hide="getPlanFromId(sc.plan_id).disabled || getCreditable(sc).disabled">
|
||||
<td>
|
||||
<span editable-select="sc.creditable_id" e-name="creditable_id" e-form="rowform" e-ng-options="s.id as s.name for s in enabledSpaces" e-required>
|
||||
{{ showCreditableName(sc) }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span editable-number="sc.hours" e-name="hours" e-form="rowform" e-required>
|
||||
{{ sc.hours }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span editable-select="sc.plan_id" e-ng-options="p.id as humanReadablePlanName(p, groups, 'short') for p in enabledPlans" e-name="plan_id" e-form="rowform">
|
||||
{{ getPlanFromId(sc.plan_id) | humanReadablePlanName: groups: 'short' }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<form editable-form name="rowform" onbeforesave="saveSpaceCredit($data, sc.id)" ng-show="rowform.$visible" class="form-buttons form-inline" shown="inserted == sc">
|
||||
<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="cancelSpaceCredit(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> {{ 'app.shared.buttons.edit' | translate }}
|
||||
</button>
|
||||
<button class="btn btn-danger" ng-click="removeSpaceCredit($index)">
|
||||
<i class="fa fa-trash-o"></i> {{ 'app.shared.buttons.delete' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -40,7 +40,7 @@
|
||||
<ng-include src="'/admin/pricing/trainings.html'"></ng-include>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'app.admin.pricing.machine_hours' | translate }}" index="2" class="machines-tab">
|
||||
<uib-tab heading="{{ 'app.admin.pricing.machine_hours' | translate }}" ng-show="$root.modules.machines" index="2" class="machines-tab">
|
||||
<ng-include src="'/admin/pricing/machine_hours.html'"></ng-include>
|
||||
</uib-tab>
|
||||
|
||||
|
@ -46,7 +46,7 @@
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<div class="col-md-3" ng-show="$root.modules.machines">
|
||||
<h4 translate>{{ 'app.admin.settings.message_of_the_machine_booking_page' }}</h4>
|
||||
<div ng-model="machineExplicationsAlert.value"
|
||||
medium-editor
|
||||
@ -59,7 +59,7 @@
|
||||
</div>
|
||||
<button name="button" class="btn btn-warning" ng-click="save(machineExplicationsAlert)" translate>{{ 'app.shared.buttons.save' }}</button>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="col-md-3" ng-show="$root.modules.trainings">
|
||||
<h4 translate>{{ 'app.admin.settings.warning_message_of_the_training_booking_page'}}</h4>
|
||||
<div ng-model="trainingExplicationsAlert.value"
|
||||
medium-editor
|
||||
@ -72,7 +72,7 @@
|
||||
</div>
|
||||
<button name="button" class="btn btn-warning" ng-click="save(trainingExplicationsAlert)" translate>{{ 'app.shared.buttons.save' }}</button>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="col-md-3" ng-show="$root.modules.trainings">
|
||||
<h4 translate>{{ 'app.admin.settings.information_message_of_the_training_reservation_page'}}</h4>
|
||||
<div ng-model="trainingInformationMessage.value"
|
||||
medium-editor
|
||||
@ -85,7 +85,7 @@
|
||||
</div>
|
||||
<button name="button" class="btn btn-warning" ng-click="save(trainingInformationMessage)" translate>{{ 'app.shared.buttons.save' }}</button>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="col-md-3" ng-show="$root.modules.plans">
|
||||
<h4 translate>{{ 'app.admin.settings.message_of_the_subscriptions_page' }}</h4>
|
||||
<div ng-model="subscriptionExplicationsAlert.value"
|
||||
medium-editor
|
||||
@ -109,7 +109,7 @@
|
||||
</div>
|
||||
<button name="button" class="btn btn-warning" ng-click="save(eventExplicationsAlert)" translate>{{ 'app.shared.buttons.save' }}</button>
|
||||
</div>
|
||||
<div class="col-md-3" ng-show="$root.modules.spaces">
|
||||
<div class="col-md-3" ng-show="$root.modules.spaces" ng-show="$root.modules.spaces">
|
||||
<h4 translate>{{ 'app.admin.settings.message_of_the_spaces_page' }}</h4>
|
||||
<div ng-model="spaceExplicationsAlert.value"
|
||||
medium-editor
|
||||
@ -340,7 +340,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default m-t-lg">
|
||||
<div class="panel panel-default m-t-lg" ng-show="$root.modules.machines">
|
||||
<div class="panel-heading">
|
||||
<span class="font-sbold" translate>{{ 'app.admin.settings.general.elements_ordering' }}</span>
|
||||
</div>
|
||||
@ -489,6 +489,14 @@
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p class="alert alert-info"><i class="fa fa-info-circle m-r"></i><span translate>{{ 'app.admin.settings.remember_to_refresh_the_page_for_the_changes_to_take_effect' }}</span> </p>
|
||||
<div class="row">
|
||||
<h3 class="m-l" translate>{{ 'app.admin.settings.machines' }}</h3>
|
||||
<p class="alert alert-warning m-h-md" ng-bind-html="'app.admin.settings.machines_info_html' | translate"></p>
|
||||
<boolean-setting name="machines_module"
|
||||
settings="allSettings"
|
||||
label="app.admin.settings.enable_machines"
|
||||
classes="m-l"></boolean-setting>
|
||||
</div>
|
||||
<div class="row">
|
||||
<h3 class="m-l" translate>{{ 'app.admin.settings.spaces' }}</h3>
|
||||
<p class="alert alert-warning m-h-md" ng-bind-html="'app.admin.settings.spaces_info_html' | translate"></p>
|
||||
|
@ -175,7 +175,7 @@
|
||||
<span class="font-sbold" translate>{{ 'app.admin.settings.display' }}</span>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="row">
|
||||
<div class="row" ng-show="$root.modules.machines">
|
||||
<h3 class="m-l" translate>{{ 'app.admin.settings.display_machine_reservation_user_name' }}</h3>
|
||||
<p class="alert alert-warning m-h-md" ng-bind-html="'app.admin.settings.display_name_info_html' | translate"></p>
|
||||
<boolean-setting name="display_name_enable"
|
||||
|
@ -143,7 +143,8 @@ class Setting < ApplicationRecord
|
||||
echosciences
|
||||
pinterest
|
||||
lastfm
|
||||
flickr] }
|
||||
flickr
|
||||
machines_module] }
|
||||
# WARNING: when adding a new key, you may also want to add it in:
|
||||
# - config/locales/en.yml#settings
|
||||
# - app/frontend/src/javascript/models/setting.ts#SettingName
|
||||
|
@ -32,6 +32,7 @@
|
||||
<script type="text/javascript">
|
||||
var Fablab = Fablab || {};
|
||||
|
||||
Fablab.machinesModule = ('<%= Setting.get('machines_module') %>' === 'true');
|
||||
Fablab.plansModule = ('<%= Setting.get('plans_module') %>' === 'true');
|
||||
Fablab.spacesModule = ('<%= Setting.get('spaces_module') %>' === 'true');
|
||||
Fablab.trainingsModule = ('<%= Setting.get('trainings_module') %>' === 'true');
|
||||
|
@ -111,6 +111,8 @@ en:
|
||||
slots_of: "of"
|
||||
minutes: "minutes"
|
||||
deleted_user: "Deleted user"
|
||||
select_type: "Please select a type to continue"
|
||||
no_modules_available: "No reservable module available. Please enable at least one module (machines, spaces or trainings) in the Customization section."
|
||||
# import external iCal calendar
|
||||
icalendar:
|
||||
icalendar_import: "iCalendar import"
|
||||
@ -1360,6 +1362,10 @@ en:
|
||||
duration_minutes: "Duration (in minutes)"
|
||||
default_slot_duration_info: "Machine and space availabilities are divided in multiple slots of this duration. This value can be overridden per availability."
|
||||
modules: "Modules"
|
||||
machines: "Machines"
|
||||
machines_info_html: "<p>Machines are the resources which are available for booking. A machine can be, <em>for example</em>, a 3D printer or a laser cutter.</p>"
|
||||
enable_machines: "Enable the machines"
|
||||
machines_module: "machines module"
|
||||
spaces: "Spaces"
|
||||
spaces_info_html: "<p>A space can be, for example, a woodshop or a meeting room. Their particularity is that they can be booked by several people at the same time.</p><p><strong>Warning:</strong> It is not recommended to disable spaces if at least one space reservation was made on the system.</p>"
|
||||
enable_spaces: "Enable the spaces"
|
||||
|
@ -581,3 +581,4 @@ en:
|
||||
pinterest: "pinterest"
|
||||
lastfm: "lastfm"
|
||||
flickr: "flickr"
|
||||
machines_module: "Machines module"
|
||||
|
@ -891,6 +891,8 @@ Setting.set('wallet_module', true) unless Setting.find_by(name: 'wallet_module')
|
||||
|
||||
Setting.set('statistics_module', true) unless Setting.find_by(name: 'statistics_module').try(:value)
|
||||
|
||||
Setting.set('machines_module', true) unless Setting.find_by(name: 'machines_module').try(:value)
|
||||
|
||||
Setting.set('upcoming_events_shown', 'until_start') unless Setting.find_by(name: 'upcoming_events_shown').try(:value)
|
||||
|
||||
Setting.set('trainings_module', true) unless Setting.find_by(name: 'trainings_module').try(:value)
|
||||
|
Loading…
x
Reference in New Issue
Block a user