mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-01-29 18:52:22 +01:00
Merge branch 'tour' into dev
This commit is contained in:
commit
147a78de96
@ -1,5 +1,5 @@
|
||||
|
||||
Fab-Manager uses some external components, which are licenced under the
|
||||
Fab-manager uses some external components, which are licenced under the
|
||||
terms of the following licences:
|
||||
|
||||
- [Apache 2 license](http://www.apache.org/licenses/LICENSE-2.0):
|
||||
|
20
CHANGELOG.md
20
CHANGELOG.md
@ -1,4 +1,4 @@
|
||||
# Changelog Fab Manager
|
||||
# Changelog Fab-manager
|
||||
|
||||
- Ability to create and delete periodic calendar availabilities (recurrence)
|
||||
- Ability to fully customize the home page
|
||||
@ -21,12 +21,16 @@
|
||||
- Improved user experience in defining slots in the calendar management
|
||||
- Improved notification email to the member when a rolling subscription is taken
|
||||
- Notify all admins on the creation of a refund invoice
|
||||
- Helper links between admin sections of the scheduling process
|
||||
- Calendar management: improved legend display and visual behavior
|
||||
- Reorganized left menu
|
||||
- Create machine availabilities: select all/none in a click
|
||||
- Prevent event reservation in the past [Taiga#127]
|
||||
- Removed the need of twitter API keys to display the last tweet on the home page
|
||||
- Handle Ctrl^C in upgrade scripts
|
||||
- Updated moment-timezone
|
||||
- Updated angular-ui-bootstrap from v0.14 to v1.2
|
||||
- Updated caxlsx to 3.0.1 and rails_axlsx to rails_caxlsx
|
||||
- Option to disable developers analytics
|
||||
- Added the a "cron" tab in Sidekiq web-ui to watch scheduled tasks
|
||||
- Integration of Crowdin "in-context" translation management system
|
||||
@ -35,10 +39,16 @@
|
||||
- Unified translations syntax to use ICU MessageFormat
|
||||
- Refactored front-end translations keys with unified paths
|
||||
- Updated and refactored README and documentations
|
||||
- Harmonized Fab-manager typography and case
|
||||
- Fix a bug: unable to remove the picture from a training
|
||||
- Fix a bug: no alerts on errors during admin creation
|
||||
- Fix a bug: replaces all Time.now by DateTime.current to prevent time zones issues [Taiga#134]
|
||||
- Fix a bug: logs are not printed in staging environment
|
||||
- Fix a bug: theme colors must be selected twice before the changes became effective
|
||||
- Fix a bug: datepicker does not work in profile completion screen
|
||||
- Fix a bug: unable to select a group in profile completion screen
|
||||
- Fix a bug: in some cases, bogus admin notification on profile completed
|
||||
- Fix a bug: with Firefox browser, the texts in date inputs are shifted to the bottom
|
||||
- Fix a bug: sometimes when browsing the invoices section, the translations are missing
|
||||
- Fix a security issue: updated loofah to fix [CVE-2019-15587](https://nvd.nist.gov/vuln/detail/CVE-2019-15587)
|
||||
- Fix a security issue: updated angular to 1.7.9 to fix [CVE-2019-10768](https://nvd.nist.gov/vuln/detail/CVE-2019-10768)
|
||||
@ -224,7 +234,7 @@
|
||||
- Improved date checks before closing an accounting period
|
||||
- Paginate list of coupons
|
||||
- Allow filtering coupons list
|
||||
- Fix a bug: when VAT has changed during fab-manager's lifecycle, this may not be reflected in archives
|
||||
- Fix a bug: when VAT has changed during Fab-manager's lifecycle, this may not be reflected in archives
|
||||
- Fix a bug: using a quote in event category's name results in angular $parse:syntax Error
|
||||
|
||||
## v3.0.1 2019 April 1st
|
||||
@ -257,7 +267,7 @@
|
||||
- [TODO DEPLOY] `rake fablab:setup:chain_invoices_records`
|
||||
- [TODO DEPLOY] `rake fablab:setup:chain_history_values_records`
|
||||
- [TODO DEPLOY] add `DISK_SPACE_MB_ALERT` and `SUPERADMIN_EMAIL` environment variables (see [doc/environment.md](doc/environment.md) for configuration details)
|
||||
- [TODO DEPLOY] add the `accounting` volume to the fab-manager's image in [docker-compose.yml](docker/docker-compose.yml)
|
||||
- [TODO DEPLOY] add the `accounting` volume to the Fab-manager's image in [docker-compose.yml](docker/docker-compose.yml)
|
||||
|
||||
## v2.8.4 2019 March 18
|
||||
|
||||
@ -396,7 +406,7 @@
|
||||
- Ability to share trainings on social medias
|
||||
- Fix a bug: a reminder notification were sent for canceled reservations
|
||||
- Fix a bug: sharing an event on facebook has HTML tags in the description
|
||||
- Set Stripe API version, all fab-managers has to use this version because codebase relies on it
|
||||
- Set Stripe API version, all Fab-managers has to use this version because codebase relies on it
|
||||
- Fix a security issue: OmniAuth < 1.3.2 has a security vulnerability described in [CVE-2017-18076](https://nvd.nist.gov/vuln/detail/CVE-2017-18076)
|
||||
- Fix a security issue: rack-protection < 1.5.5 has a security vulnerability described in [CVE-2018-1000119](https://nvd.nist.gov/vuln/detail/CVE-2018-1000119)
|
||||
- Fix a security issue: http gem < 0.7.3 has a security vulnerability described in [CVE-2015-1828](https://nvd.nist.gov/vuln/detail/CVE-2015-1828), updates twitter gem as a dependency
|
||||
@ -667,7 +677,7 @@
|
||||
- Project images will show in full-size on a click
|
||||
- Add a checkbox "I accept to receive informations from the FabLab" on Sign-up dialog and user's profile
|
||||
- Share project with Facebook/Twitter
|
||||
- Display fab-manager's version in "Powered by" label, when logged as admin
|
||||
- Display Fab-manager's version in "Powered by" label, when logged as admin
|
||||
- Load translation locales from subdirectories
|
||||
- Add wallet to user, client can pay total/partial reservation or subscription by wallet
|
||||
- Public calendar for show all trainings/machines/events
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Contributing to FabManager
|
||||
# Contributing to Fab-manager
|
||||
|
||||
♥ [FabManager](http://www.fab-manager.com) and want to get involved?
|
||||
♥ [Fab-manager](http://www.fab-manager.com) and want to get involved?
|
||||
Thanks! There are plenty of ways you can help!
|
||||
|
||||
Please take a moment to review this document in order to make the contribution process easy and effective for everyone
|
||||
|
2
Gemfile
2
Gemfile
@ -137,8 +137,8 @@ gem 'apipie-rails'
|
||||
gem 'has_secure_token'
|
||||
|
||||
# XLS files generation
|
||||
gem 'axlsx_rails'
|
||||
gem 'caxlsx'
|
||||
gem 'caxlsx_rails'
|
||||
gem 'rubyzip', '>= 1.3.0'
|
||||
|
||||
gem 'rack-protection', '1.5.5'
|
||||
|
16
Gemfile.lock
16
Gemfile.lock
@ -56,9 +56,6 @@ GEM
|
||||
descendants_tracker (~> 0.0.4)
|
||||
ice_nine (~> 0.11.0)
|
||||
thread_safe (~> 0.3, >= 0.3.1)
|
||||
axlsx_rails (0.6.0)
|
||||
actionpack (>= 3.1)
|
||||
caxlsx (>= 3.0)
|
||||
bcrypt (3.1.13)
|
||||
binding_of_caller (0.7.3)
|
||||
debug_inspector (>= 0.0.1)
|
||||
@ -73,11 +70,14 @@ GEM
|
||||
activesupport (>= 3.2.0)
|
||||
json (>= 1.7)
|
||||
mime-types (>= 1.16)
|
||||
caxlsx (3.0.0)
|
||||
caxlsx (3.0.1)
|
||||
htmlentities (~> 4.3, >= 4.3.4)
|
||||
mimemagic (~> 0.3)
|
||||
nokogiri (~> 1.8, >= 1.8.2)
|
||||
rubyzip (~> 1.2, >= 1.2.1)
|
||||
nokogiri (~> 1.10, >= 1.10.4)
|
||||
rubyzip (>= 1.3.0, < 3)
|
||||
caxlsx_rails (0.6.2)
|
||||
actionpack (>= 3.1)
|
||||
caxlsx (>= 3.0)
|
||||
chroma (0.0.1)
|
||||
chunky_png (1.3.4)
|
||||
cldr-plurals-runtime-rb (1.0.1)
|
||||
@ -215,7 +215,7 @@ GEM
|
||||
message_format (0.0.3)
|
||||
twitter_cldr (~> 3.1)
|
||||
mime-types (2.99.3)
|
||||
mimemagic (0.3.3)
|
||||
mimemagic (0.3.4)
|
||||
mini_magick (4.9.4)
|
||||
mini_mime (1.0.2)
|
||||
mini_portile2 (2.4.0)
|
||||
@ -449,11 +449,11 @@ DEPENDENCIES
|
||||
api-pagination
|
||||
apipie-rails
|
||||
awesome_print
|
||||
axlsx_rails
|
||||
bootstrap-sass (>= 3.4.1)
|
||||
byebug
|
||||
carrierwave
|
||||
caxlsx
|
||||
caxlsx_rails
|
||||
chroma
|
||||
compass-rails (= 2.0.4)
|
||||
coveralls
|
||||
|
24
README.md
24
README.md
@ -1,6 +1,6 @@
|
||||
# FabManager
|
||||
# Fab-manager
|
||||
|
||||
FabManager is the Fab Lab management solution. It provides a comprehensive, web-based, open-source tool to simplify your administrative tasks and your marker's projects.
|
||||
Fab-manager is the Fab Lab management solution. It provides a comprehensive, web-based, open-source tool to simplify your administrative tasks and your marker's projects.
|
||||
|
||||
[![Coverage Status](https://coveralls.io/repos/github/sleede/fab-manager/badge.svg)](https://coveralls.io/github/sleede/fab-manager)
|
||||
[![Docker pulls](https://img.shields.io/docker/pulls/sleede/fab-manager.svg)](https://hub.docker.com/r/sleede/fab-manager/)
|
||||
@ -24,7 +24,7 @@ FabManager is the Fab Lab management solution. It provides a comprehensive, web-
|
||||
<a name="software-stack"></a>
|
||||
## Software stack
|
||||
|
||||
FabManager is a Ruby on Rails / AngularJS web application that runs on the following software:
|
||||
Fab-manager is a Ruby on Rails / AngularJS web application that runs on the following software:
|
||||
|
||||
- Ubuntu LTS 14.04+ / Debian 8+
|
||||
- Ruby 2.3
|
||||
@ -41,13 +41,13 @@ Contributions are welcome. Please read [the contribution guidelines](CONTRIBUTIN
|
||||
<a name="setup-a-production-environment"></a>
|
||||
## Setup a production environment
|
||||
|
||||
To run fab-manager as a production application, this is highly recommended to use [Docker-compose](https://docs.docker.com/compose/overview/).
|
||||
To run Fab-manager as a production application, this is highly recommended to use [Docker-compose](https://docs.docker.com/compose/overview/).
|
||||
The procedure to follow is described in the [docker-compose readme](doc/docker-compose_readme.md).
|
||||
|
||||
<a name="setup-a-development-environment"></a>
|
||||
## Setup a development environment
|
||||
|
||||
In you intend to run fab-manager on your local machine to contribute to the project development, you can set it up by following the [development readme](doc/development_readme.md).
|
||||
In you intend to run Fab-manager on your local machine to contribute to the project development, you can set it up by following the [development readme](doc/development_readme.md).
|
||||
This procedure relies on docker to set-up the dependencies.
|
||||
|
||||
Optionally, you can use a virtual development environment that relies on Vagrant and Virtual Box by following the [virtual machine instructions](virtual-machine.md).
|
||||
@ -55,7 +55,7 @@ Optionally, you can use a virtual development environment that relies on Vagrant
|
||||
<a name="i18n"></a>
|
||||
## Internationalization (i18n)
|
||||
|
||||
The FabManager application can only run in a single language but this language can easily be changed.
|
||||
The Fab-manager application can only run in a single language but this language can easily be changed.
|
||||
|
||||
Please refer to the [translation readme](doc/translation_readme.md) for instructions about configuring the language or to contribute to the translation.
|
||||
|
||||
@ -64,17 +64,17 @@ Please refer to the [translation readme](doc/translation_readme.md) for instruct
|
||||
|
||||
**This configuration is optional.**
|
||||
|
||||
You can configure your fab-manager to synchronize every project with the [Open Projects platform](https://github.com/sleede/openlab-projects).
|
||||
It's very simple and straightforward and in return, your users will be able to search over projects from all fab-manager instances from within your platform.
|
||||
You can configure your Fab-manager to synchronize every project with the [Open Projects platform](https://github.com/sleede/openlab-projects).
|
||||
It's very simple and straightforward and in return, your users will be able to search over projects from all Fab-manager instances from within your platform.
|
||||
The deal is fair, you share your projects and as reward you benefits from projects of the whole community.
|
||||
|
||||
If you want to try it, you can visit [this fab-manager](https://fablab.lacasemate.fr/#!/projects) and see projects from different fab-managers.
|
||||
If you want to try it, you can visit [this Fab-manager](https://fablab.lacasemate.fr/#!/projects) and see projects from different Fab-managers.
|
||||
|
||||
To start using this awesome feature, there are a few steps:
|
||||
- send a mail to **contact@fab-manager.com** asking for your Open Projects client's credentials and giving them the name of your fab-manager, they will give you an `OPENLAB_APP_ID` and an `OPENLAB_APP_SECRET`
|
||||
- send a mail to **contact@fab-manager.com** asking for your Open Projects client's credentials and giving them the name of your Fab-manager, they will give you an `OPENLAB_APP_ID` and an `OPENLAB_APP_SECRET`
|
||||
- fill in the value of the keys in your environment file
|
||||
- start your fab-manager app
|
||||
- export your projects to open-projects (if you already have projects created on your fab-manager, unless you can skip that part) executing this command: `bundle exec rake fablab:openlab:bulk_export`
|
||||
- start your Fab-manager app
|
||||
- export your projects to open-projects (if you already have projects created on your Fab-manager, unless you can skip that part) executing this command: `bundle exec rake fablab:openlab:bulk_export`
|
||||
|
||||
**IMPORTANT: please run your server in production mode.**
|
||||
|
||||
|
@ -20,9 +20,10 @@ angular.module('application', ['ngCookies', 'ngResource', 'ngSanitize', 'ui.rout
|
||||
'ui.select', 'ui.calendar', 'angularMoment', 'Devise', 'DeviseModal', 'angular-growl', 'xeditable',
|
||||
'checklist-model', 'unsavedChanges', 'angular-loading-bar', 'ngTouch', 'angular-google-analytics',
|
||||
'angularUtils.directives.dirDisqus', 'summernote', 'elasticsearch', 'angular-medium-editor', 'naif.base64',
|
||||
'minicolors', 'pascalprecht.translate', 'ngFitText', 'ngAside', 'ngCapsLock', 'vcRecaptcha', 'ui.codemirror'])
|
||||
.config(['$httpProvider', 'AuthProvider', 'growlProvider', 'unsavedWarningsConfigProvider', 'AnalyticsProvider', 'uibDatepickerPopupConfig', '$provide', '$translateProvider',
|
||||
function ($httpProvider, AuthProvider, growlProvider, unsavedWarningsConfigProvider, AnalyticsProvider, uibDatepickerPopupConfig, $provide, $translateProvider) {
|
||||
'minicolors', 'pascalprecht.translate', 'ngFitText', 'ngAside', 'ngCapsLock', 'vcRecaptcha', 'ui.codemirror',
|
||||
'bm.uiTour'])
|
||||
.config(['$httpProvider', 'AuthProvider', 'growlProvider', 'unsavedWarningsConfigProvider', 'AnalyticsProvider', 'uibDatepickerPopupConfig', '$provide', '$translateProvider', 'TourConfigProvider',
|
||||
function ($httpProvider, AuthProvider, growlProvider, unsavedWarningsConfigProvider, AnalyticsProvider, uibDatepickerPopupConfig, $provide, $translateProvider, TourConfigProvider) {
|
||||
// Google analytics
|
||||
// first we check the user acceptance
|
||||
const cookiesConsent = document.cookie.replace(/(?:(?:^|.*;\s*)fab-manager-cookies-consent\s*=\s*([^;]*).*$)|^.*$/, '$1');
|
||||
@ -63,6 +64,8 @@ angular.module('application', ['ngCookies', 'ngResource', 'ngSanitize', 'ui.rout
|
||||
$translateProvider.useMessageFormatInterpolation();
|
||||
// Set the langage of the instance (from ruby configuration)
|
||||
$translateProvider.preferredLanguage(Fablab.locale);
|
||||
// End the tour when the user clicks the forward or back buttons of the browser
|
||||
TourConfigProvider.enableNavigationInterceptors();
|
||||
}]).run(['$rootScope', '$log', 'AuthService', 'Auth', 'amMoment', '$state', 'editableOptions', 'Analytics',
|
||||
function ($rootScope, $log, AuthService, Auth, amMoment, $state, editableOptions, Analytics) {
|
||||
// Angular-moment (date-time manipulations library)
|
||||
|
@ -21,7 +21,7 @@
|
||||
//= require angular-cookies
|
||||
//= require angular-touch
|
||||
//= require @uirouter/angularjs/release/angular-ui-router
|
||||
//= require angular-ui-bootstrap/ui-bootstrap-tpls
|
||||
//= require angular-ui-bootstrap/dist/ui-bootstrap-tpls
|
||||
//= require ui-select/dist/select
|
||||
//= require moment/moment
|
||||
//= require moment-timezone/builds/moment-timezone-with-data-2012-2022
|
||||
@ -72,6 +72,11 @@
|
||||
//= require codemirror/mode/css/css
|
||||
//= require codemirror/mode/sass/sass
|
||||
//= require angular-ui-codemirror/src/ui-codemirror
|
||||
//= require angular-hotkeys/build/hotkeys
|
||||
//= require hone/dist/hone
|
||||
//= require tether/dist/js/tether
|
||||
//= require angular-bind-html-compile/angular-bind-html-compile
|
||||
//= require angular-ui-tour/dist/angular-ui-tour
|
||||
//= require_tree ./controllers
|
||||
//= require_tree ./services
|
||||
//= require_tree ./directives
|
||||
|
@ -18,9 +18,9 @@
|
||||
* Controller used in the calendar management page
|
||||
*/
|
||||
|
||||
Application.Controllers.controller('AdminCalendarController', ['$scope', '$state', '$uibModal', 'moment', 'Availability', 'Slot', 'Setting', 'Export', 'growl', 'dialogs', 'bookingWindowStart', 'bookingWindowEnd', 'machinesPromise', '_t', 'uiCalendarConfig', 'CalendarConfig',
|
||||
function ($scope, $state, $uibModal, moment, Availability, Slot, Setting, Export, growl, dialogs, bookingWindowStart, bookingWindowEnd, machinesPromise, _t, uiCalendarConfig, CalendarConfig) {
|
||||
/* PRIVATE STATIC CONSTANTS */
|
||||
Application.Controllers.controller('AdminCalendarController', ['$scope', '$state', '$uibModal', 'moment', 'Availability', 'Slot', 'Setting', 'Export', 'growl', 'dialogs', 'bookingWindowStart', 'bookingWindowEnd', 'machinesPromise', '_t', 'uiCalendarConfig', 'CalendarConfig', 'Member', 'uiTourService',
|
||||
function ($scope, $state, $uibModal, moment, Availability, Slot, Setting, Export, growl, dialogs, bookingWindowStart, bookingWindowEnd, machinesPromise, _t, uiCalendarConfig, CalendarConfig, Member, uiTourService) {
|
||||
/* PRIVATE STATIC CONSTANTS */
|
||||
|
||||
// The calendar is divided in slots of 30 minutes
|
||||
const BASE_SLOT = '00:30:00';
|
||||
@ -252,14 +252,89 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Setup the feature-tour for the admin/calendar page.
|
||||
* This is intended as a contextual help (when pressing F1)
|
||||
*/
|
||||
$scope.setupCalendarTour = function () {
|
||||
// get the tour defined by the ui-tour directive
|
||||
const uitour = uiTourService.getTourByName('calendar');
|
||||
uitour.createStep({
|
||||
selector: 'body',
|
||||
stepId: 'welcome',
|
||||
order: 0,
|
||||
title: _t('app.admin.tour.calendar.welcome.title'),
|
||||
content: _t('app.admin.tour.calendar.welcome.content'),
|
||||
placement: 'bottom',
|
||||
orphan: true
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.admin-calendar .fc-view-container',
|
||||
stepId: 'agenda',
|
||||
order: 1,
|
||||
title: _t('app.admin.tour.calendar.agenda.title'),
|
||||
content: _t('app.admin.tour.calendar.agenda.content'),
|
||||
placement: 'right'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.admin-calendar .export-xls-button',
|
||||
stepId: 'export',
|
||||
order: 2,
|
||||
title: _t('app.admin.tour.calendar.export.title'),
|
||||
content: _t('app.admin.tour.calendar.export.content'),
|
||||
placement: 'left'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.heading .import-ics-button',
|
||||
stepId: 'import',
|
||||
order: 3,
|
||||
title: _t('app.admin.tour.calendar.import.title'),
|
||||
content: _t('app.admin.tour.calendar.import.content'),
|
||||
placement: 'left'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: 'body',
|
||||
stepId: 'conclusion',
|
||||
order: 4,
|
||||
title: _t('app.admin.tour.conclusion.title'),
|
||||
content: _t('app.admin.tour.conclusion.content'),
|
||||
placement: 'bottom',
|
||||
orphan: true
|
||||
});
|
||||
// on tour end, save the status in database
|
||||
uitour.on('ended', function () {
|
||||
if (uitour.getStatus() === uitour.Status.ON && $scope.currentUser.profile.tours.indexOf('calendar') < 0) {
|
||||
Member.completeTour({ id: $scope.currentUser.id }, { tour: 'calendar' }, function (res) {
|
||||
$scope.currentUser.profile.tours = res.tours;
|
||||
});
|
||||
}
|
||||
});
|
||||
// if the user has never seen the tour, show him now
|
||||
if (Fablab.featureTourDisplay !== 'manual' && $scope.currentUser.profile.tours.indexOf('calendar') < 0) {
|
||||
uitour.start();
|
||||
}
|
||||
// start this tour when an user press F1 - this is contextual help
|
||||
window.addEventListener('keydown', handleF1);
|
||||
}
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
// listen the $destroy event of the controller to remove the F1 key binding
|
||||
$scope.$on('$destroy', function () {
|
||||
window.removeEventListener('keydown', handleF1);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Return an enumerable meaninful string for the gender of the provider user
|
||||
* @param user {Object} Database user record
|
||||
* @return {string} 'male' or 'female'
|
||||
*/
|
||||
var getGender = function (user) {
|
||||
const getGender = function (user) {
|
||||
if (user.statistic_profile) {
|
||||
if (user.statistic_profile.gender === 'true') { return 'male'; } else { return 'female'; }
|
||||
} else { return 'other'; }
|
||||
@ -268,7 +343,7 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
// Triggered when the admin drag on the agenda to create a new reservable slot.
|
||||
// @see http://fullcalendar.io/docs/selection/select_callback/
|
||||
//
|
||||
var calendarSelectCb = function (start, end, jsEvent, view) {
|
||||
const calendarSelectCb = function (start, end, jsEvent, view) {
|
||||
start = moment.tz(start.toISOString(), Fablab.timezone);
|
||||
end = moment.tz(end.toISOString(), Fablab.timezone);
|
||||
|
||||
@ -329,7 +404,7 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
* Triggered when the admin clicks on a availability slot in the agenda.
|
||||
* @see http://fullcalendar.io/docs/mouse/eventClick/
|
||||
*/
|
||||
var calendarEventClickCb = function (event, jsEvent, view) {
|
||||
const calendarEventClickCb = function (event, jsEvent, view) {
|
||||
$scope.availability = event;
|
||||
|
||||
if ($scope.availabilityDom) {
|
||||
@ -352,7 +427,7 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
* Append the event tag into the block, just after the event title.
|
||||
* @see http://fullcalendar.io/docs/event_rendering/eventRender/
|
||||
*/
|
||||
var eventRenderCb = function (event, element) {
|
||||
const eventRenderCb = function (event, element) {
|
||||
if (event.available_type !== 'event') {
|
||||
element.find('.fc-content').prepend('<span class="remove-event">x </span>');
|
||||
}
|
||||
@ -387,6 +462,21 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
$scope.availability = null;
|
||||
$scope.availabilityDom = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback used to trigger the feature tour when the user press the F1 key.
|
||||
* @param e {KeyboardEvent}
|
||||
*/
|
||||
const handleF1 = function (e) {
|
||||
if (e.key === 'F1') {
|
||||
e.preventDefault();
|
||||
const tour = uiTourService.getTourByName('calendar');
|
||||
if (tour) { tour.start(); }
|
||||
}
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize();
|
||||
}
|
||||
|
||||
]);
|
||||
@ -396,7 +486,7 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
*/
|
||||
Application.Controllers.controller('CreateEventModalController', ['$scope', '$uibModalInstance', '$sce', 'moment', 'start', 'end', 'machinesPromise', 'Availability', 'trainingsPromise', 'spacesPromise', 'tagsPromise', 'growl', '_t',
|
||||
function ($scope, $uibModalInstance, $sce, moment, start, end, machinesPromise, Availability, trainingsPromise, spacesPromise, tagsPromise, growl, _t) {
|
||||
// $uibModal parameter
|
||||
// $uibModal parameter
|
||||
$scope.start = start;
|
||||
|
||||
// $uibModal parameter
|
||||
@ -463,6 +553,9 @@ Application.Controllers.controller('CreateEventModalController', ['$scope', '$ui
|
||||
// localized name(s) of the selected tag(s)
|
||||
$scope.tagsName = '';
|
||||
|
||||
// make the duration available for display
|
||||
$scope.slotDuration = Fablab.slotDuration;
|
||||
|
||||
/**
|
||||
* Adds or removes the provided machine from the current slot
|
||||
* @param machine {Object}
|
||||
|
@ -153,8 +153,8 @@ class EventsController {
|
||||
/**
|
||||
* Controller used in the events listing page (admin view)
|
||||
*/
|
||||
Application.Controllers.controller('AdminEventsController', ['$scope', '$state', 'dialogs', '$uibModal', 'growl', 'Event', 'Category', 'EventTheme', 'AgeRange', 'PriceCategory', 'eventsPromise', 'categoriesPromise', 'themesPromise', 'ageRangesPromise', 'priceCategoriesPromise', '_t',
|
||||
function ($scope, $state, dialogs, $uibModal, growl, Event, Category, EventTheme, AgeRange, PriceCategory, eventsPromise, categoriesPromise, themesPromise, ageRangesPromise, priceCategoriesPromise, _t) {
|
||||
Application.Controllers.controller('AdminEventsController', ['$scope', '$state', 'dialogs', '$uibModal', 'growl', 'Event', 'Category', 'EventTheme', 'AgeRange', 'PriceCategory', 'eventsPromise', 'categoriesPromise', 'themesPromise', 'ageRangesPromise', 'priceCategoriesPromise', '_t', 'Member', 'uiTourService',
|
||||
function ($scope, $state, dialogs, $uibModal, growl, Event, Category, EventTheme, AgeRange, PriceCategory, eventsPromise, categoriesPromise, themesPromise, ageRangesPromise, priceCategoriesPromise, _t, Member, uiTourService) {
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// By default, the pagination mode is activated to limit the page size
|
||||
@ -189,6 +189,9 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
$scope.eventsScope =
|
||||
{ selected: '' };
|
||||
|
||||
// default tab: events list
|
||||
$scope.tabs = { active: 0 };
|
||||
|
||||
/**
|
||||
* Adds a bucket of events to the bottom of the page, grouped by month
|
||||
*/
|
||||
@ -371,12 +374,127 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
return $scope.page = 1;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Setup the feature-tour for the admin/events page.
|
||||
* This is intended as a contextual help (when pressing F1)
|
||||
*/
|
||||
$scope.setupEventsTour = function () {
|
||||
// get the tour defined by the ui-tour directive
|
||||
const uitour = uiTourService.getTourByName('events');
|
||||
uitour.createStep({
|
||||
selector: 'body',
|
||||
stepId: 'welcome',
|
||||
order: 0,
|
||||
title: _t('app.admin.tour.events.welcome.title'),
|
||||
content: _t('app.admin.tour.events.welcome.content'),
|
||||
placement: 'bottom',
|
||||
orphan: true
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.events-management .events-list',
|
||||
stepId: 'list',
|
||||
order: 1,
|
||||
title: _t('app.admin.tour.events.list.title'),
|
||||
content: _t('app.admin.tour.events.list.content'),
|
||||
placement: 'top'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.events-management .events-list-filter',
|
||||
stepId: 'filter',
|
||||
order: 2,
|
||||
title: _t('app.admin.tour.events.filter.title'),
|
||||
content: _t('app.admin.tour.events.filter.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.events-management .events-categories',
|
||||
stepId: 'categories',
|
||||
order: 3,
|
||||
title: _t('app.admin.tour.events.categories.title'),
|
||||
content: _t('app.admin.tour.events.categories.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.events-management .events-themes',
|
||||
stepId: 'themes',
|
||||
order: 4,
|
||||
title: _t('app.admin.tour.events.themes.title'),
|
||||
content: _t('app.admin.tour.events.themes.content'),
|
||||
placement: 'top'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.events-management .events-age-ranges',
|
||||
stepId: 'ages',
|
||||
order: 5,
|
||||
title: _t('app.admin.tour.events.ages.title'),
|
||||
content: _t('app.admin.tour.events.ages.content'),
|
||||
placement: 'top'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.events-management .prices-tab',
|
||||
stepId: 'prices',
|
||||
order: 6,
|
||||
title: _t('app.admin.tour.events.prices.title'),
|
||||
content: _t('app.admin.tour.events.prices.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: 'body',
|
||||
stepId: 'conclusion',
|
||||
order: 7,
|
||||
title: _t('app.admin.tour.conclusion.title'),
|
||||
content: _t('app.admin.tour.conclusion.content'),
|
||||
placement: 'bottom',
|
||||
orphan: true
|
||||
});
|
||||
// on step change, change the active tab if needed
|
||||
uitour.on('stepChanged', function (nextStep) {
|
||||
if (nextStep.stepId === 'list' || nextStep.stepId === 'filter') { $scope.tabs.active = 0; }
|
||||
if (nextStep.stepId === 'categories' || nextStep.stepId === 'ages') { $scope.tabs.active = 1; }
|
||||
if (nextStep.stepId === 'prices') { $scope.tabs.active = 2; }
|
||||
});
|
||||
// on tour end, save the status in database
|
||||
uitour.on('ended', function () {
|
||||
if (uitour.getStatus() === uitour.Status.ON && $scope.currentUser.profile.tours.indexOf('events') < 0) {
|
||||
Member.completeTour({ id: $scope.currentUser.id }, { tour: 'events' }, function (res) {
|
||||
$scope.currentUser.profile.tours = res.tours;
|
||||
});
|
||||
}
|
||||
});
|
||||
// if the user has never seen the tour, show him now
|
||||
if (Fablab.featureTourDisplay !== 'manual' && $scope.currentUser.profile.tours.indexOf('events') < 0) {
|
||||
uitour.start();
|
||||
}
|
||||
// start this tour when an user press F1 - this is contextual help
|
||||
window.addEventListener('keydown', handleF1);
|
||||
}
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () { paginationCheck(eventsPromise, $scope.events); };
|
||||
const initialize = function () {
|
||||
paginationCheck(eventsPromise, $scope.events);
|
||||
|
||||
// listen the $destroy event of the controller to remove the F1 key binding
|
||||
$scope.$on('$destroy', function () {
|
||||
window.removeEventListener('keydown', handleF1);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback used to trigger the feature tour when the user press the F1 key.
|
||||
* @param e {KeyboardEvent}
|
||||
*/
|
||||
const handleF1 = function (e) {
|
||||
if (e.key === 'F1') {
|
||||
e.preventDefault();
|
||||
const tour = uiTourService.getTourByName('events');
|
||||
if (tour) { tour.start(); }
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if all events are already displayed OR if the button 'load more events'
|
||||
@ -384,7 +502,7 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
* @param lastEvents {Array} last events loaded onto the diplay (ie. last "page")
|
||||
* @param events {Array} full list of events displayed on the page (not only the last retrieved)
|
||||
*/
|
||||
var paginationCheck = function (lastEvents, events) {
|
||||
const paginationCheck = function (lastEvents, events) {
|
||||
if (lastEvents.length > 0) {
|
||||
if (events.length >= lastEvents[0].nb_total_events) {
|
||||
return $scope.paginateActive = false;
|
||||
@ -401,7 +519,7 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
* @param name {string} 'category', 'theme' or 'age_range'
|
||||
* @return {[Object, Array]} model and datastore
|
||||
*/
|
||||
var getModel = function (name) {
|
||||
const getModel = function (name) {
|
||||
switch (name) {
|
||||
case 'category': return [Category, $scope.categories];
|
||||
case 'theme': return [EventTheme, $scope.themes];
|
||||
|
@ -17,8 +17,8 @@
|
||||
/**
|
||||
* Controller used in the admin invoices listing page
|
||||
*/
|
||||
Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'Invoice', 'AccountingPeriod', 'invoices', 'closedPeriods', '$uibModal', 'growl', '$filter', 'Setting', 'settings', '_t',
|
||||
function ($scope, $state, Invoice, AccountingPeriod, invoices, closedPeriods, $uibModal, growl, $filter, Setting, settings, _t) {
|
||||
Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'Invoice', 'AccountingPeriod', 'invoices', 'closedPeriods', '$uibModal', 'growl', '$filter', 'Setting', 'settings', '_t', 'Member', 'uiTourService',
|
||||
function ($scope, $state, Invoice, AccountingPeriod, invoices, closedPeriods, $uibModal, growl, $filter, Setting, settings, _t, Member, uiTourService) {
|
||||
/* PRIVATE STATIC CONSTANTS */
|
||||
|
||||
// number of invoices loaded each time we click on 'load more...'
|
||||
@ -28,11 +28,10 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
|
||||
// default active tab
|
||||
$scope.tabs = {
|
||||
listing: { active: !Fablab.withoutInvoices },
|
||||
settings: { active: Fablab.withoutInvoices }
|
||||
active: Fablab.withoutInvoices ? 1 : 0
|
||||
};
|
||||
|
||||
// List of all users invoices
|
||||
// List of all invoices
|
||||
$scope.invoices = invoices;
|
||||
|
||||
// Invoices filters
|
||||
@ -246,7 +245,7 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate an order nmuber sample from the parametrized model
|
||||
* Generate an order number sample from the parametrized model
|
||||
* @returns {string} invoice reference sample
|
||||
*/
|
||||
$scope.mkNumber = function () {
|
||||
@ -560,6 +559,127 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the feature-tour for the admin/invoices page.
|
||||
* This is intended as a contextual help (when pressing F1)
|
||||
*/
|
||||
$scope.setupInvoicesTour = function () {
|
||||
// get the tour defined by the ui-tour directive
|
||||
const uitour = uiTourService.getTourByName('invoices');
|
||||
uitour.createStep({
|
||||
selector: 'body',
|
||||
stepId: 'welcome',
|
||||
order: 0,
|
||||
title: _t('app.admin.tour.invoices.welcome.title'),
|
||||
content: _t('app.admin.tour.invoices.welcome.content'),
|
||||
placement: 'bottom',
|
||||
orphan: true
|
||||
});
|
||||
if (!Fablab.withoutInvoices) {
|
||||
uitour.createStep({
|
||||
selector: '.invoices-management .invoices-list',
|
||||
stepId: 'list',
|
||||
order: 1,
|
||||
title: _t('app.admin.tour.invoices.list.title'),
|
||||
content: _t('app.admin.tour.invoices.list.content'),
|
||||
placement: 'top'
|
||||
});
|
||||
if ($scope.invoices.length > 0) {
|
||||
uitour.createStep({
|
||||
selector: '.invoices-management .invoices-list .chained-indicator',
|
||||
stepId: 'chained',
|
||||
order: 2,
|
||||
title: _t('app.admin.tour.invoices.chained.title'),
|
||||
content: _t('app.admin.tour.invoices.chained.content'),
|
||||
placement: 'right'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.invoices-management .invoices-list .download-button',
|
||||
stepId: 'download',
|
||||
order: 3,
|
||||
title: _t('app.admin.tour.invoices.download.title'),
|
||||
content: _t('app.admin.tour.invoices.download.content'),
|
||||
placement: 'left'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.invoices-management .invoices-list .refund-button',
|
||||
stepId: 'refund',
|
||||
order: 4,
|
||||
title: _t('app.admin.tour.invoices.refund.title'),
|
||||
content: _t('app.admin.tour.invoices.refund.content'),
|
||||
placement: 'left'
|
||||
});
|
||||
}
|
||||
}
|
||||
uitour.createStep({
|
||||
selector: '.invoices-management .invoices-settings',
|
||||
stepId: 'settings',
|
||||
order: 5,
|
||||
title: _t('app.admin.tour.invoices.settings.title'),
|
||||
content: _t('app.admin.tour.invoices.settings.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.invoices-management .accounting-codes-tab',
|
||||
stepId: 'codes',
|
||||
order: 6,
|
||||
title: _t('app.admin.tour.invoices.codes.title'),
|
||||
content: _t('app.admin.tour.invoices.codes.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.heading .export-accounting-button',
|
||||
stepId: 'export',
|
||||
order: 7,
|
||||
title: _t('app.admin.tour.invoices.export.title'),
|
||||
content: _t('app.admin.tour.invoices.export.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.heading .close-accounting-periods-button',
|
||||
stepId: 'periods',
|
||||
order: 8,
|
||||
title: _t('app.admin.tour.invoices.periods.title'),
|
||||
content: _t('app.admin.tour.invoices.periods.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: 'body',
|
||||
stepId: 'conclusion',
|
||||
order: 9,
|
||||
title: _t('app.admin.tour.conclusion.title'),
|
||||
content: _t('app.admin.tour.conclusion.content'),
|
||||
placement: 'bottom',
|
||||
orphan: true
|
||||
});
|
||||
// on step change, change the active tab if needed
|
||||
uitour.on('stepChanged', function (nextStep) {
|
||||
if (nextStep.stepId === 'list' || nextStep.stepId === 'settings') {
|
||||
$scope.tabs.active = 0;
|
||||
}
|
||||
if (nextStep.stepId === 'settings') {
|
||||
$scope.tabs.active = 1;
|
||||
}
|
||||
if (nextStep.stepId === 'codes' || nextStep.stepId === 'export') {
|
||||
$scope.tabs.active = 2;
|
||||
}
|
||||
});
|
||||
// on tour end, save the status in database
|
||||
uitour.on('ended', function () {
|
||||
if (uitour.getStatus() === uitour.Status.ON && $scope.currentUser.profile.tours.indexOf('invoices') < 0) {
|
||||
Member.completeTour({ id: $scope.currentUser.id }, { tour: 'invoices' }, function (res) {
|
||||
$scope.currentUser.profile.tours = res.tours;
|
||||
});
|
||||
}
|
||||
});
|
||||
// if the user has never seen the tour, show him now
|
||||
if (Fablab.featureTourDisplay !== 'manual' && $scope.currentUser.profile.tours.indexOf('invoices') < 0) {
|
||||
uitour.start();
|
||||
}
|
||||
// start this tour when an user press F1 - this is contextual help
|
||||
window.addEventListener('keydown', handleF1);
|
||||
}
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
/**
|
||||
@ -586,7 +706,7 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
};
|
||||
|
||||
// Watch the logo, when a change occurs, save it
|
||||
return $scope.$watch('invoice.logo', function () {
|
||||
$scope.$watch('invoice.logo', function () {
|
||||
if ($scope.invoice.logo && $scope.invoice.logo.filesize) {
|
||||
return Setting.update(
|
||||
{ name: 'invoice_logo' },
|
||||
@ -599,6 +719,11 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// listen the $destroy event of the controller to remove the F1 key binding
|
||||
$scope.$on('$destroy', function () {
|
||||
window.removeEventListener('keydown', handleF1);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@ -666,6 +791,18 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback used to trigger the feature tour when the user press the F1 key.
|
||||
* @param e {KeyboardEvent}
|
||||
*/
|
||||
const handleF1 = function (e) {
|
||||
if (e.key === 'F1') {
|
||||
e.preventDefault();
|
||||
const tour = uiTourService.getTourByName('invoices');
|
||||
if (tour) { tour.start(); }
|
||||
}
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize();
|
||||
}
|
||||
|
@ -126,8 +126,8 @@ class MembersController {
|
||||
/**
|
||||
* Controller used in the members/groups management page
|
||||
*/
|
||||
Application.Controllers.controller('AdminMembersController', ['$scope', '$sce', 'membersPromise', 'adminsPromise', 'growl', 'Admin', 'dialogs', '_t', 'Member', 'Export',
|
||||
function ($scope, $sce, membersPromise, adminsPromise, growl, Admin, dialogs, _t, Member, Export) {
|
||||
Application.Controllers.controller('AdminMembersController', ['$scope', '$sce', 'membersPromise', 'adminsPromise', 'growl', 'Admin', 'dialogs', '_t', 'Member', 'Export', 'uiTourService',
|
||||
function ($scope, $sce, membersPromise, adminsPromise, growl, Admin, dialogs, _t, Member, Export, uiTourService) {
|
||||
/* PRIVATE STATIC CONSTANTS */
|
||||
|
||||
// number of users loaded each time we click on 'load more...'
|
||||
@ -163,6 +163,9 @@ Application.Controllers.controller('AdminMembersController', ['$scope', '$sce',
|
||||
// Admins ordering/sorting. Default: not sorted
|
||||
$scope.orderAdmin = null;
|
||||
|
||||
// default tab: members list
|
||||
$scope.tabs = { active: 0 };
|
||||
|
||||
/**
|
||||
* Change the members ordering criterion to the one provided
|
||||
* @param orderBy {string} ordering criterion
|
||||
@ -289,6 +292,148 @@ Application.Controllers.controller('AdminMembersController', ['$scope', '$sce',
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Setup the feature-tour for the admin/members page.
|
||||
* This is intended as a contextual help (when pressing F1)
|
||||
*/
|
||||
$scope.setupMembersTour = function () {
|
||||
// get the tour defined by the ui-tour directive
|
||||
const uitour = uiTourService.getTourByName('members');
|
||||
uitour.createStep({
|
||||
selector: 'body',
|
||||
stepId: 'welcome',
|
||||
order: 0,
|
||||
title: _t('app.admin.tour.members.welcome.title'),
|
||||
content: _t('app.admin.tour.members.welcome.content'),
|
||||
placement: 'bottom',
|
||||
orphan: true
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.members-management .members-list',
|
||||
stepId: 'list',
|
||||
order: 1,
|
||||
title: _t('app.admin.tour.members.list.title'),
|
||||
content: _t('app.admin.tour.members.list.content'),
|
||||
placement: 'top'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.members-management .search-members',
|
||||
stepId: 'search',
|
||||
order: 2,
|
||||
title: _t('app.admin.tour.members.search.title'),
|
||||
content: _t('app.admin.tour.members.search.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.members-management .filter-members',
|
||||
stepId: 'filter',
|
||||
order: 3,
|
||||
title: _t('app.admin.tour.members.filter.title'),
|
||||
content: _t('app.admin.tour.members.filter.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
if ($scope.members.length > 0) {
|
||||
uitour.createStep({
|
||||
selector: '.members-management .members-list .buttons',
|
||||
stepId: 'actions',
|
||||
order: 4,
|
||||
title: _t('app.admin.tour.members.actions.title'),
|
||||
content: _t('app.admin.tour.members.actions.content'),
|
||||
placement: 'left'
|
||||
});
|
||||
}
|
||||
uitour.createStep({
|
||||
selector: '.members-management .exports-buttons',
|
||||
stepId: 'exports',
|
||||
order: 5,
|
||||
title: _t('app.admin.tour.members.exports.title'),
|
||||
content: _t('app.admin.tour.members.exports.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.heading .import-members',
|
||||
stepId: 'import',
|
||||
order: 6,
|
||||
title: _t('app.admin.tour.members.import.title'),
|
||||
content: _t('app.admin.tour.members.import.content'),
|
||||
placement: 'left'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.members-management .admins-tab',
|
||||
stepId: 'admins',
|
||||
order: 7,
|
||||
title: _t('app.admin.tour.members.admins.title'),
|
||||
content: _t('app.admin.tour.members.admins.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.members-management .groups-tab',
|
||||
stepId: 'groups',
|
||||
order: 8,
|
||||
title: _t('app.admin.tour.members.groups.title'),
|
||||
content: _t('app.admin.tour.members.groups.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.members-management .labels-tab',
|
||||
stepId: 'labels',
|
||||
order: 9,
|
||||
title: _t('app.admin.tour.members.labels.title'),
|
||||
content: _t('app.admin.tour.members.labels.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.members-management .sso-tab',
|
||||
stepId: 'sso',
|
||||
order: 10,
|
||||
title: _t('app.admin.tour.members.sso.title'),
|
||||
content: _t('app.admin.tour.members.sso.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: 'body',
|
||||
stepId: 'conclusion',
|
||||
order: 11,
|
||||
title: _t('app.admin.tour.conclusion.title'),
|
||||
content: _t('app.admin.tour.conclusion.content'),
|
||||
placement: 'bottom',
|
||||
orphan: true
|
||||
});
|
||||
// on step change, change the active tab if needed
|
||||
uitour.on('stepChanged', function (nextStep) {
|
||||
if (nextStep.stepId === 'list' || nextStep.stepId === 'import') {
|
||||
$scope.tabs.active = 0;
|
||||
}
|
||||
if (nextStep.stepId === 'admins') {
|
||||
$scope.tabs.active = 1;
|
||||
}
|
||||
if (nextStep.stepId === 'groups') {
|
||||
$scope.tabs.active = 2;
|
||||
}
|
||||
if (nextStep.stepId === 'labels') {
|
||||
$scope.tabs.active = 3;
|
||||
}
|
||||
if (nextStep.stepId === 'sso') {
|
||||
$scope.tabs.active = 4;
|
||||
}
|
||||
});
|
||||
// on tour end, save the status in database
|
||||
uitour.on('ended', function () {
|
||||
if (uitour.getStatus() === uitour.Status.ON && $scope.currentUser.profile.tours.indexOf('members') < 0) {
|
||||
Member.completeTour({ id: $scope.currentUser.id }, { tour: 'members' }, function (res) {
|
||||
$scope.currentUser.profile.tours = res.tours;
|
||||
});
|
||||
}
|
||||
});
|
||||
// if the user has never seen the tour, show him now
|
||||
if (Fablab.featureTourDisplay !== 'manual' && $scope.currentUser.profile.tours.indexOf('members') < 0) {
|
||||
uitour.start();
|
||||
}
|
||||
// start this tour when an user press F1 - this is contextual help
|
||||
window.addEventListener('keydown', handleF1);
|
||||
}
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
/**
|
||||
@ -298,6 +443,9 @@ Application.Controllers.controller('AdminMembersController', ['$scope', '$sce',
|
||||
if (!membersPromise[0] || (membersPromise[0].maxMembers <= $scope.members.length)) {
|
||||
return $scope.member.noMore = true;
|
||||
}
|
||||
$scope.$on('$destroy', function () {
|
||||
window.removeEventListener('keydown', handleF1);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@ -350,6 +498,18 @@ Application.Controllers.controller('AdminMembersController', ['$scope', '$sce',
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback used to trigger the feature tour when the user press the F1 key.
|
||||
* @param e {KeyboardEvent}
|
||||
*/
|
||||
const handleF1 = function (e) {
|
||||
if (e.key === 'F1') {
|
||||
e.preventDefault();
|
||||
const tour = uiTourService.getTourByName('members');
|
||||
if (tour) { tour.start(); }
|
||||
}
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize();
|
||||
}
|
||||
|
@ -10,9 +10,9 @@
|
||||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
Application.Controllers.controller('OpenAPIClientsController', ['$scope', 'clientsPromise', 'growl', 'OpenAPIClient', 'dialogs', '_t',
|
||||
function ($scope, clientsPromise, growl, OpenAPIClient, dialogs, _t) {
|
||||
/* PUBLIC SCOPE */
|
||||
Application.Controllers.controller('OpenAPIClientsController', ['$scope', 'clientsPromise', 'growl', 'OpenAPIClient', 'dialogs', '_t', 'Member', 'uiTourService',
|
||||
function ($scope, clientsPromise, growl, OpenAPIClient, dialogs, _t, Member, uiTourService) {
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// clients list
|
||||
$scope.clients = clientsPromise;
|
||||
@ -74,7 +74,7 @@ Application.Controllers.controller('OpenAPIClientsController', ['$scope', 'clien
|
||||
})
|
||||
);
|
||||
|
||||
return $scope.resetToken = client =>
|
||||
$scope.resetToken = client =>
|
||||
dialogs.confirm({
|
||||
resolve: {
|
||||
object () {
|
||||
@ -91,6 +91,82 @@ Application.Controllers.controller('OpenAPIClientsController', ['$scope', 'clien
|
||||
return growl.success(_t('app.admin.open_api_clients.access_successfully_revoked'));
|
||||
})
|
||||
);
|
||||
|
||||
/**
|
||||
* Setup the feature-tour for the admin/open_api_clients page.
|
||||
* This is intended as a contextual help (when pressing F1)
|
||||
*/
|
||||
$scope.setupOpenAPITour = function () {
|
||||
// get the tour defined by the ui-tour directive
|
||||
const uitour = uiTourService.getTourByName('open-api');
|
||||
uitour.createStep({
|
||||
selector: 'body',
|
||||
stepId: 'welcome',
|
||||
order: 0,
|
||||
title: _t('app.admin.tour.open_api.welcome.title'),
|
||||
content: _t('app.admin.tour.open_api.welcome.content'),
|
||||
placement: 'bottom',
|
||||
orphan: true
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.heading .documentation-button',
|
||||
stepId: 'doc',
|
||||
order: 1,
|
||||
title: _t('app.admin.tour.open_api.doc.title'),
|
||||
content: _t('app.admin.tour.open_api.doc.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: 'body',
|
||||
stepId: 'conclusion',
|
||||
order: 2,
|
||||
title: _t('app.admin.tour.conclusion.title'),
|
||||
content: _t('app.admin.tour.conclusion.content'),
|
||||
placement: 'bottom',
|
||||
orphan: true
|
||||
});
|
||||
// on tour end, save the status in database
|
||||
uitour.on('ended', function () {
|
||||
if (uitour.getStatus() === uitour.Status.ON && $scope.currentUser.profile.tours.indexOf('open-api') < 0) {
|
||||
Member.completeTour({ id: $scope.currentUser.id }, { tour: 'open-api' }, function (res) {
|
||||
$scope.currentUser.profile.tours = res.tours;
|
||||
});
|
||||
}
|
||||
});
|
||||
// if the user has never seen the tour, and if the display behavior is not configured to manual triggering only, show the tour now
|
||||
if (Fablab.featureTourDisplay !== 'manual' && $scope.currentUser.profile.tours.indexOf('open-api') < 0) {
|
||||
uitour.start();
|
||||
}
|
||||
// start this tour when an user press F1 - this is contextual help
|
||||
window.addEventListener('keydown', handleF1);
|
||||
};
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
// listen the $destroy event of the controller to remove the F1 key binding
|
||||
$scope.$on('$destroy', function () {
|
||||
window.removeEventListener('keydown', handleF1);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback used to trigger the feature tour when the user press the F1 key.
|
||||
* @param e {KeyboardEvent}
|
||||
*/
|
||||
const handleF1 = function (e) {
|
||||
if (e.key === 'F1') {
|
||||
e.preventDefault();
|
||||
const tour = uiTourService.getTourByName('open-api');
|
||||
if (tour) { tour.start(); }
|
||||
}
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize();
|
||||
}
|
||||
|
||||
]);
|
||||
|
@ -18,9 +18,10 @@
|
||||
/**
|
||||
* Controller used in the prices edition page
|
||||
*/
|
||||
Application.Controllers.controller('EditPricingController', ['$scope', '$state', '$uibModal', '$filter', 'TrainingsPricing', 'Credit', 'Pricing', 'Plan', 'Coupon', 'plans', 'groups', 'growl', 'machinesPricesPromise', 'Price', 'dialogs', 'trainingsPricingsPromise', 'trainingsPromise', 'machineCreditsPromise', 'machinesPromise', 'trainingCreditsPromise', 'couponsPromise', 'spacesPromise', 'spacesPricesPromise', 'spacesCreditsPromise', '_t',
|
||||
function ($scope, $state, $uibModal, $filter, TrainingsPricing, Credit, Pricing, Plan, Coupon, plans, groups, growl, machinesPricesPromise, Price, dialogs, trainingsPricingsPromise, trainingsPromise, machineCreditsPromise, machinesPromise, trainingCreditsPromise, couponsPromise, spacesPromise, spacesPricesPromise, spacesCreditsPromise, _t) {
|
||||
/* PUBLIC SCOPE */
|
||||
Application.Controllers.controller('EditPricingController', ['$scope', '$state', '$uibModal', '$filter', 'TrainingsPricing', 'Credit', 'Pricing', 'Plan', 'Coupon', 'plans', 'groups', 'growl', 'machinesPricesPromise', 'Price', 'dialogs', 'trainingsPricingsPromise', 'trainingsPromise', 'machineCreditsPromise', 'machinesPromise', 'trainingCreditsPromise', 'couponsPromise', 'spacesPromise', 'spacesPricesPromise', 'spacesCreditsPromise', '_t', 'Member', 'uiTourService',
|
||||
function ($scope, $state, $uibModal, $filter, TrainingsPricing, Credit, Pricing, Plan, Coupon, plans, groups, growl, machinesPricesPromise, Price, dialogs, trainingsPricingsPromise, trainingsPromise, machineCreditsPromise, machinesPromise, trainingCreditsPromise, couponsPromise, spacesPromise, spacesPricesPromise, spacesCreditsPromise, _t, Member, uiTourService) {
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// List of machines prices (not considering any plan)
|
||||
$scope.machinesPrices = machinesPricesPromise;
|
||||
|
||||
@ -84,7 +85,7 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
|
||||
// Default: we do not filter coupons
|
||||
$scope.filter = {
|
||||
coupon: 'all',
|
||||
coupon: 'all'
|
||||
};
|
||||
|
||||
// Available status for filtering coupons
|
||||
@ -96,6 +97,16 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
'active'
|
||||
];
|
||||
|
||||
// default tab: plans list
|
||||
$scope.tabs = { active: 0 };
|
||||
|
||||
/**
|
||||
* Retrieve a training price from all the trainings prices
|
||||
* @param trainingsPricings {Array<Object>} all trainings prices
|
||||
* @param trainingId {number}
|
||||
* @param groupId {number}
|
||||
* @returns {float}
|
||||
*/
|
||||
$scope.findTrainingsPricing = function (trainingsPricings, trainingId, groupId) {
|
||||
for (let trainingsPricing of Array.from(trainingsPricings)) {
|
||||
if ((trainingsPricing.training_id === trainingId) && (trainingsPricing.group_id === groupId)) {
|
||||
@ -104,6 +115,12 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the price of a training for the given parameters
|
||||
* @param data {float} the new price
|
||||
* @param trainingsPricing {Object} the training pricing to update
|
||||
* @returns {Promise|string}
|
||||
*/
|
||||
$scope.updateTrainingsPricing = function (data, trainingsPricing) {
|
||||
if (data != null) {
|
||||
return TrainingsPricing.update({ id: trainingsPricing.id }, { trainings_pricing: { amount: data } }).$promise;
|
||||
@ -600,6 +617,106 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the feature-tour for the admin/pricing page.
|
||||
* This is intended as a contextual help (when pressing F1)
|
||||
*/
|
||||
$scope.setupPricingTour = function () {
|
||||
// get the tour defined by the ui-tour directive
|
||||
const uitour = uiTourService.getTourByName('pricing');
|
||||
uitour.createStep({
|
||||
selector: 'body',
|
||||
stepId: 'welcome',
|
||||
order: 0,
|
||||
title: _t('app.admin.tour.pricing.welcome.title'),
|
||||
content: _t('app.admin.tour.pricing.welcome.content'),
|
||||
placement: 'bottom',
|
||||
orphan: true
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.plans-pricing .new-plan-button',
|
||||
stepId: 'new_plan',
|
||||
order: 1,
|
||||
title: _t('app.admin.tour.pricing.new_plan.title'),
|
||||
content: _t('app.admin.tour.pricing.new_plan.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.plans-pricing .trainings-tab',
|
||||
stepId: 'trainings',
|
||||
order: 2,
|
||||
title: _t('app.admin.tour.pricing.trainings.title'),
|
||||
content: _t('app.admin.tour.pricing.trainings.content'),
|
||||
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 (!Fablab.withoutSpaces) {
|
||||
uitour.createStep({
|
||||
selector: '.plans-pricing .spaces-tab',
|
||||
stepId: 'spaces',
|
||||
order: 4,
|
||||
title: _t('app.admin.tour.pricing.spaces.title'),
|
||||
content: _t('app.admin.tour.pricing.spaces.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
}
|
||||
uitour.createStep({
|
||||
selector: '.plans-pricing .credits-tab',
|
||||
stepId: 'credits',
|
||||
order: 5,
|
||||
title: _t('app.admin.tour.pricing.credits.title'),
|
||||
content: _t('app.admin.tour.pricing.credits.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.plans-pricing .coupons-tab',
|
||||
stepId: 'coupons',
|
||||
order: 6,
|
||||
title: _t('app.admin.tour.pricing.coupons.title'),
|
||||
content: _t('app.admin.tour.pricing.coupons.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: 'body',
|
||||
stepId: 'conclusion',
|
||||
order: 7,
|
||||
title: _t('app.admin.tour.conclusion.title'),
|
||||
content: _t('app.admin.tour.conclusion.content'),
|
||||
placement: 'bottom',
|
||||
orphan: true
|
||||
});
|
||||
// on step change, change the active tab if needed
|
||||
uitour.on('stepChanged', function (nextStep) {
|
||||
if (nextStep.stepId === 'new_plan') { $scope.tabs.active = 0; }
|
||||
if (nextStep.stepId === 'trainings') { $scope.tabs.active = 1; }
|
||||
if (nextStep.stepId === 'machines') { $scope.tabs.active = 2; }
|
||||
if (nextStep.stepId === 'spaces') { $scope.tabs.active = 3; }
|
||||
if (nextStep.stepId === 'credits') { $scope.tabs.active = 4; }
|
||||
if (nextStep.stepId === 'coupons') { $scope.tabs.active = 5; }
|
||||
});
|
||||
// on tour end, save the status in database
|
||||
uitour.on('ended', function () {
|
||||
if (uitour.getStatus() === uitour.Status.ON && $scope.currentUser.profile.tours.indexOf('pricing') < 0) {
|
||||
Member.completeTour({ id: $scope.currentUser.id }, { tour: 'pricing' }, function (res) {
|
||||
$scope.currentUser.profile.tours = res.tours;
|
||||
});
|
||||
}
|
||||
});
|
||||
// if the user has never seen the tour, show him now
|
||||
if (Fablab.featureTourDisplay !== 'manual' && $scope.currentUser.profile.tours.indexOf('pricing') < 0) {
|
||||
uitour.start();
|
||||
}
|
||||
// start this tour when an user press F1 - this is contextual help
|
||||
window.addEventListener('keydown', handleF1);
|
||||
}
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
/**
|
||||
@ -608,6 +725,11 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
const initialize = function () {
|
||||
$scope.trainingCreditsGroups = groupCreditsByPlan($scope.trainingCredits);
|
||||
|
||||
// listen the $destroy event of the controller to remove the F1 key binding
|
||||
$scope.$on('$destroy', function () {
|
||||
window.removeEventListener('keydown', handleF1);
|
||||
});
|
||||
|
||||
// adds empty array for plan which hasn't any credits yet
|
||||
return (function () {
|
||||
const result = [];
|
||||
@ -622,6 +744,18 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
})();
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback used to trigger the feature tour when the user press the F1 key.
|
||||
* @param e {KeyboardEvent}
|
||||
*/
|
||||
const handleF1 = function (e) {
|
||||
if (e.key === 'F1') {
|
||||
e.preventDefault();
|
||||
const tour = uiTourService.getTourByName('pricing');
|
||||
if (tour) { tour.start(); }
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve an item index by its ID from the given array of objects
|
||||
* @param items {Array<{id:number}>}
|
||||
|
@ -12,9 +12,9 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
Application.Controllers.controller('ProjectElementsController', ['$scope', '$state', 'Component', 'Licence', 'Theme', 'componentsPromise', 'licencesPromise', 'themesPromise',
|
||||
function ($scope, $state, Component, Licence, Theme, componentsPromise, licencesPromise, themesPromise) {
|
||||
// Materials list (plastic, wood ...)
|
||||
Application.Controllers.controller('ProjectElementsController', ['$scope', '$state', 'Component', 'Licence', 'Theme', 'componentsPromise', 'licencesPromise', 'themesPromise', '_t', 'Member', 'uiTourService',
|
||||
function ($scope, $state, Component, Licence, Theme, componentsPromise, licencesPromise, themesPromise, _t, Member, uiTourService) {
|
||||
// Materials list (plastic, wood ...)
|
||||
$scope.components = componentsPromise;
|
||||
|
||||
// Licences list (Creative Common ...)
|
||||
@ -149,12 +149,88 @@ Application.Controllers.controller('ProjectElementsController', ['$scope', '$sta
|
||||
* @param rowform {Object} see http://vitalets.github.io/angular-xeditable/
|
||||
* @param index {number} licence index in the $scope.licences array
|
||||
*/
|
||||
return $scope.cancelLicence = function (rowform, index) {
|
||||
$scope.cancelLicence = function (rowform, index) {
|
||||
if ($scope.licences[index].id != null) {
|
||||
return rowform.$cancel();
|
||||
} else {
|
||||
return $scope.licences.splice(index, 1);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Setup the feature-tour for the admin/project_elements page.
|
||||
* This is intended as a contextual help (when pressing F1)
|
||||
*/
|
||||
$scope.setupProjectElementsTour = function () {
|
||||
// get the tour defined by the ui-tour directive
|
||||
const uitour = uiTourService.getTourByName('project-elements');
|
||||
uitour.createStep({
|
||||
selector: 'body',
|
||||
stepId: 'welcome',
|
||||
order: 0,
|
||||
title: _t('app.admin.tour.project_elements.welcome.title'),
|
||||
content: _t('app.admin.tour.project_elements.welcome.content'),
|
||||
placement: 'bottom',
|
||||
orphan: true
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.heading .abuses-button',
|
||||
stepId: 'abuses',
|
||||
order: 1,
|
||||
title: _t('app.admin.tour.project_elements.abuses.title'),
|
||||
content: _t('app.admin.tour.project_elements.abuses.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: 'body',
|
||||
stepId: 'conclusion',
|
||||
order: 2,
|
||||
title: _t('app.admin.tour.conclusion.title'),
|
||||
content: _t('app.admin.tour.conclusion.content'),
|
||||
placement: 'bottom',
|
||||
orphan: true
|
||||
});
|
||||
// on tour end, save the status in database
|
||||
uitour.on('ended', function () {
|
||||
if (uitour.getStatus() === uitour.Status.ON && $scope.currentUser.profile.tours.indexOf('project-elements') < 0) {
|
||||
Member.completeTour({ id: $scope.currentUser.id }, { tour: 'project-elements' }, function (res) {
|
||||
$scope.currentUser.profile.tours = res.tours;
|
||||
});
|
||||
}
|
||||
});
|
||||
// if the user has never seen the tour, show him now
|
||||
if (Fablab.featureTourDisplay !== 'manual' && $scope.currentUser.profile.tours.indexOf('project-elements') < 0) {
|
||||
uitour.start();
|
||||
}
|
||||
// start this tour when an user press F1 - this is contextual help
|
||||
window.addEventListener('keydown', handleF1);
|
||||
};
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
// listen the $destroy event of the controller to remove the F1 key binding
|
||||
$scope.$on('$destroy', function () {
|
||||
window.removeEventListener('keydown', handleF1);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback used to trigger the feature tour when the user press the F1 key.
|
||||
* @param e {KeyboardEvent}
|
||||
*/
|
||||
const handleF1 = function (e) {
|
||||
if (e.key === 'F1') {
|
||||
e.preventDefault();
|
||||
const tour = uiTourService.getTourByName('project-elements');
|
||||
if (tour) { tour.start(); }
|
||||
}
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize();
|
||||
}
|
||||
]);
|
||||
|
@ -12,8 +12,8 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
Application.Controllers.controller('SettingsController', ['$scope', '$rootScope', '$filter', '$uibModal', 'dialogs', 'Setting', 'growl', 'settingsPromise', 'privacyDraftsPromise', 'cgvFile', 'cguFile', 'logoFile', 'logoBlackFile', 'faviconFile', 'profileImageFile', 'CSRF', '_t',
|
||||
function ($scope, $rootScope, $filter, $uibModal, dialogs, Setting, growl, settingsPromise, privacyDraftsPromise, cgvFile, cguFile, logoFile, logoBlackFile, faviconFile, profileImageFile, CSRF, _t) {
|
||||
Application.Controllers.controller('SettingsController', ['$scope', '$rootScope', '$filter', '$uibModal', 'dialogs', 'Setting', 'growl', 'settingsPromise', 'privacyDraftsPromise', 'cgvFile', 'cguFile', 'logoFile', 'logoBlackFile', 'faviconFile', 'profileImageFile', 'CSRF', '_t', 'Member', 'uiTourService',
|
||||
function ($scope, $rootScope, $filter, $uibModal, dialogs, Setting, growl, settingsPromise, privacyDraftsPromise, cgvFile, cguFile, logoFile, logoBlackFile, faviconFile, profileImageFile, CSRF, _t, Member, uiTourService) {
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// timepickers steps configuration
|
||||
@ -48,6 +48,9 @@ Application.Controllers.controller('SettingsController', ['$scope', '$rootScope'
|
||||
cgv: false
|
||||
};
|
||||
|
||||
// default tab: general
|
||||
$scope.tabs = { active: 0 };
|
||||
|
||||
// full history of privacy policy drafts
|
||||
$scope.privacyDraftsHistory = [];
|
||||
|
||||
@ -151,6 +154,7 @@ Application.Controllers.controller('SettingsController', ['$scope', '$rootScope'
|
||||
`<div id="events">${_t('app.admin.settings.item_events')}</div>`
|
||||
]
|
||||
}
|
||||
$scope.summernoteOptsHomePage.height = 400;
|
||||
|
||||
// codemirror editor
|
||||
$scope.codeMirrorEditor = null;
|
||||
@ -356,6 +360,117 @@ Application.Controllers.controller('SettingsController', ['$scope', '$rootScope'
|
||||
$scope.codeMirrorEditor = editor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the feature-tour for the admin/settings page.
|
||||
* This is intended as a contextual help (when pressing F1)
|
||||
*/
|
||||
$scope.setupSettingsTour = function () {
|
||||
// get the tour defined by the ui-tour directive
|
||||
const uitour = uiTourService.getTourByName('settings');
|
||||
uitour.createStep({
|
||||
selector: 'body',
|
||||
stepId: 'welcome',
|
||||
order: 0,
|
||||
title: _t('app.admin.tour.settings.welcome.title'),
|
||||
content: _t('app.admin.tour.settings.welcome.content'),
|
||||
placement: 'bottom',
|
||||
orphan: true
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.admin-settings .home-page-content h4',
|
||||
stepId: 'home',
|
||||
order: 1,
|
||||
title: _t('app.admin.tour.settings.home.title'),
|
||||
content: _t('app.admin.tour.settings.home.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.admin-settings .home-page-content .note-toolbar .note-insert div',
|
||||
stepId: 'components',
|
||||
order: 2,
|
||||
title: _t('app.admin.tour.settings.components.title'),
|
||||
content: _t('app.admin.tour.settings.components.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.admin-settings .home-page-content .note-toolbar .btn-codeview',
|
||||
stepId: 'codeview',
|
||||
order: 3,
|
||||
title: _t('app.admin.tour.settings.codeview.title'),
|
||||
content: _t('app.admin.tour.settings.codeview.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.admin-settings .reset-button',
|
||||
stepId: 'reset',
|
||||
order: 4,
|
||||
title: _t('app.admin.tour.settings.reset.title'),
|
||||
content: _t('app.admin.tour.settings.reset.content'),
|
||||
placement: 'left'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.admin-settings .home-page-style',
|
||||
stepId: 'css',
|
||||
order: 5,
|
||||
title: _t('app.admin.tour.settings.css.title'),
|
||||
content: _t('app.admin.tour.settings.css.content'),
|
||||
placement: 'top'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.admin-settings .about-page-tab',
|
||||
stepId: 'about',
|
||||
order: 6,
|
||||
title: _t('app.admin.tour.settings.about.title'),
|
||||
content: _t('app.admin.tour.settings.about.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.admin-settings .privacy-page-tab',
|
||||
stepId: 'privacy',
|
||||
order: 7,
|
||||
title: _t('app.admin.tour.settings.privacy.title'),
|
||||
content: _t('app.admin.tour.settings.privacy.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.admin-settings .history-select',
|
||||
stepId: 'draft',
|
||||
order: 8,
|
||||
title: _t('app.admin.tour.settings.draft.title'),
|
||||
content: _t('app.admin.tour.settings.draft.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: 'body',
|
||||
stepId: 'conclusion',
|
||||
order: 9,
|
||||
title: _t('app.admin.tour.conclusion.title'),
|
||||
content: _t('app.admin.tour.conclusion.content'),
|
||||
placement: 'bottom',
|
||||
orphan: true
|
||||
});
|
||||
// on step change, change the active tab if needed
|
||||
uitour.on('stepChanged', function (nextStep) {
|
||||
if (nextStep.stepId === 'home' || nextStep.stepId === 'css') { $scope.tabs.active = 1; }
|
||||
if (nextStep.stepId === 'about') { $scope.tabs.active = 2; }
|
||||
if (nextStep.stepId === 'privacy' || nextStep.stepId === 'draft') { $scope.tabs.active = 3; }
|
||||
});
|
||||
// on tour end, save the status in database
|
||||
uitour.on('ended', function () {
|
||||
if (uitour.getStatus() === uitour.Status.ON && $scope.currentUser.profile.tours.indexOf('settings') < 0) {
|
||||
Member.completeTour({ id: $scope.currentUser.id }, { tour: 'settings' }, function (res) {
|
||||
$scope.currentUser.profile.tours = res.tours;
|
||||
});
|
||||
}
|
||||
});
|
||||
// if the user has never seen the tour, show him now
|
||||
if (Fablab.featureTourDisplay !== 'manual' && $scope.currentUser.profile.tours.indexOf('settings') < 0) {
|
||||
uitour.start();
|
||||
}
|
||||
// start this tour when an user press F1 - this is contextual help
|
||||
window.addEventListener('keydown', handleF1);
|
||||
}
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
/**
|
||||
@ -406,8 +521,23 @@ Application.Controllers.controller('SettingsController', ['$scope', '$rootScope'
|
||||
$scope.$watch('advancedSettings.open', function (newValue) {
|
||||
if (newValue) $scope.codeMirrorEditor.refresh();
|
||||
})
|
||||
// listen the $destroy event of the controller to remove the F1 key binding
|
||||
$scope.$on('$destroy', function () {
|
||||
window.removeEventListener('keydown', handleF1);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback used to trigger the feature tour when the user press the F1 key.
|
||||
* @param e {KeyboardEvent}
|
||||
*/
|
||||
const handleF1 = function (e) {
|
||||
if (e.key === 'F1') {
|
||||
e.preventDefault();
|
||||
const tour = uiTourService.getTourByName('settings');
|
||||
if (tour) { tour.start(); }
|
||||
}
|
||||
};
|
||||
// init the controller (call at the end !)
|
||||
return initialize();
|
||||
}
|
||||
|
@ -15,8 +15,8 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
Application.Controllers.controller('StatisticsController', ['$scope', '$state', '$rootScope', '$uibModal', 'es', 'Member', '_t', 'membersPromise', 'statisticsPromise',
|
||||
function ($scope, $state, $rootScope, $uibModal, es, Member, _t, membersPromise, statisticsPromise) {
|
||||
Application.Controllers.controller('StatisticsController', ['$scope', '$state', '$rootScope', '$uibModal', 'es', 'Member', '_t', 'membersPromise', 'statisticsPromise', 'uiTourService',
|
||||
function ($scope, $state, $rootScope, $uibModal, es, Member, _t, membersPromise, statisticsPromise, uiTourService) {
|
||||
/* PRIVATE STATIC CONSTANTS */
|
||||
|
||||
// search window size
|
||||
@ -181,11 +181,7 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
if (tab.table) {
|
||||
if ((tab.es_type_key === 'subscription') && $rootScope.fablabWithoutPlans) {
|
||||
return true;
|
||||
} else if ((tab.es_type_key === 'space') && $rootScope.fablabWithoutSpaces) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else return (tab.es_type_key === 'space') && $rootScope.fablabWithoutSpaces;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
@ -342,6 +338,63 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
.result['finally'](null).then(function (info) { console.log(info); });
|
||||
};
|
||||
|
||||
/**
|
||||
* Setup the feature-tour for the admin/statistics page.
|
||||
* This is intended as a contextual help (when pressing F1)
|
||||
*/
|
||||
$scope.setupStatisticsTour = function () {
|
||||
// get the tour defined by the ui-tour directive
|
||||
const uitour = uiTourService.getTourByName('statistics');
|
||||
uitour.createStep({
|
||||
selector: 'body',
|
||||
stepId: 'welcome',
|
||||
order: 0,
|
||||
title: _t('app.admin.tour.statistics.welcome.title'),
|
||||
content: _t('app.admin.tour.statistics.welcome.content'),
|
||||
placement: 'bottom',
|
||||
orphan: true
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.heading .export-button',
|
||||
stepId: 'export',
|
||||
order: 1,
|
||||
title: _t('app.admin.tour.statistics.export.title'),
|
||||
content: _t('app.admin.tour.statistics.export.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.heading .charts-button',
|
||||
stepId: 'trending',
|
||||
order: 2,
|
||||
title: _t('app.admin.tour.statistics.trending.title'),
|
||||
content: _t('app.admin.tour.statistics.trending.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: 'body',
|
||||
stepId: 'conclusion',
|
||||
order: 3,
|
||||
title: _t('app.admin.tour.conclusion.title'),
|
||||
content: _t('app.admin.tour.conclusion.content'),
|
||||
placement: 'bottom',
|
||||
orphan: true
|
||||
});
|
||||
// on tour end, save the status in database
|
||||
uitour.on('ended', function () {
|
||||
if (uitour.getStatus() === uitour.Status.ON && $scope.currentUser.profile.tours.indexOf('statistics') < 0) {
|
||||
Member.completeTour({ id: $scope.currentUser.id }, { tour: 'statistics' }, function (res) {
|
||||
$scope.currentUser.profile.tours = res.tours;
|
||||
});
|
||||
}
|
||||
});
|
||||
// if the user has never seen the tour, show him now
|
||||
if (Fablab.featureTourDisplay !== 'manual' && $scope.currentUser.profile.tours.indexOf('statistics') < 0) {
|
||||
uitour.start();
|
||||
}
|
||||
// start this tour when an user press F1 - this is contextual help
|
||||
window.addEventListener('keydown', handleF1);
|
||||
}
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
/**
|
||||
@ -355,6 +408,22 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
return $scope.preventRefresh = true;
|
||||
}
|
||||
});
|
||||
// listen the $destroy event of the controller to remove the F1 key binding
|
||||
$scope.$on('$destroy', function () {
|
||||
window.removeEventListener('keydown', handleF1);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback used to trigger the feature tour when the user press the F1 key.
|
||||
* @param e {KeyboardEvent}
|
||||
*/
|
||||
const handleF1 = function (e) {
|
||||
if (e.key === 'F1') {
|
||||
e.preventDefault();
|
||||
const tour = uiTourService.getTourByName('statistics');
|
||||
if (tour) { tour.start(); }
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -362,7 +431,7 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
* @param $event {Object} jQuery event object
|
||||
* @param datePicker {Object} settings object of the concerned datepicker. Must have an 'opened' property
|
||||
*/
|
||||
var toggleDatePicker = function ($event, datePicker) {
|
||||
const toggleDatePicker = function ($event, datePicker) {
|
||||
$event.preventDefault();
|
||||
$event.stopPropagation();
|
||||
return datePicker.opened = !datePicker.opened;
|
||||
@ -371,7 +440,7 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
/**
|
||||
* Force update the statistics table, querying elasticSearch according to the current config values
|
||||
*/
|
||||
var refreshStats = function () {
|
||||
const refreshStats = function () {
|
||||
if ($scope.selectedIndex && !$scope.preventRefresh) {
|
||||
$scope.data = [];
|
||||
$scope.sumCA = 0;
|
||||
@ -411,7 +480,7 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
* @param callback {function} function be to run after results were retrieved, it will receive
|
||||
* two parameters : results {Object}, error {String} (if any)
|
||||
*/
|
||||
var queryElasticStats = function (index, type, custom, callback) {
|
||||
const queryElasticStats = function (index, type, custom, callback) {
|
||||
// handle invalid callback
|
||||
if (typeof (callback) !== 'function') {
|
||||
console.error('[statisticsController::queryElasticStats] Error: invalid callback provided');
|
||||
@ -450,7 +519,7 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
* @param intervalEnd {moment} statitics interval ending (moment.js type)
|
||||
* @param sortings {Array|null} elasticSearch criteria for sorting the results
|
||||
*/
|
||||
var buildElasticDataQuery = function (type, custom, ageMin, ageMax, intervalBegin, intervalEnd, sortings) {
|
||||
const buildElasticDataQuery = function (type, custom, ageMin, ageMax, intervalBegin, intervalEnd, sortings) {
|
||||
const q = {
|
||||
'query': {
|
||||
'bool': {
|
||||
@ -525,7 +594,7 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
* @param custom {Object} if custom is empty or undefined, an empty string will be returned
|
||||
* @returns {{match:*}|string}
|
||||
*/
|
||||
var buildElasticCustomCriterion = function (custom) {
|
||||
const buildElasticCustomCriterion = function (custom) {
|
||||
if (custom) {
|
||||
const criterion = {
|
||||
'match': {}
|
||||
@ -546,7 +615,7 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
* Parse the provided criteria array and return the corresponding elasticSearch syntax
|
||||
* @param criteria {Array} array of {key_to_sort:order}
|
||||
*/
|
||||
var buildElasticSortCriteria = function (criteria) {
|
||||
const buildElasticSortCriteria = function (criteria) {
|
||||
const crits = [];
|
||||
angular.forEach(criteria, function (value, key) {
|
||||
if ((typeof value !== 'undefined') && (value !== null) && (value !== 'none')) {
|
||||
@ -562,7 +631,7 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
* Fulfill the list of available options in the custom filter panel. The list will be based on common
|
||||
* properties and on index-specific properties (additional_fields)
|
||||
*/
|
||||
var buildCustomFiltersList = function () {
|
||||
const buildCustomFiltersList = function () {
|
||||
$scope.filters = [
|
||||
{ key: 'date', label: _t('app.admin.statistics.date'), values: ['input_date'] },
|
||||
{ key: 'userId', label: _t('app.admin.statistics.user_id'), values: ['input_number'] },
|
||||
@ -595,7 +664,7 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
* Build and return an object according to the custom filter set by the user, used to request elasticsearch
|
||||
* @return {Object|null}
|
||||
*/
|
||||
var buildCustomFilterQuery = function () {
|
||||
const buildCustomFilterQuery = function () {
|
||||
let custom = null;
|
||||
if (!angular.isUndefinedOrNull($scope.customFilter.criterion) &&
|
||||
!angular.isUndefinedOrNull($scope.customFilter.criterion.key) &&
|
||||
|
@ -150,22 +150,19 @@ Application.Controllers.controller('EditTrainingController', [ '$scope', '$state
|
||||
/**
|
||||
* Controller used in the trainings management page, allowing admins users to see and manage the list of trainings and reservations.
|
||||
*/
|
||||
Application.Controllers.controller('TrainingsAdminController', ['$scope', '$state', '$uibModal', 'Training', 'trainingsPromise', 'machinesPromise', '_t', 'growl', 'dialogs',
|
||||
function ($scope, $state, $uibModal, Training, trainingsPromise, machinesPromise, _t, growl, dialogs) {
|
||||
/* PUBLIC SCOPE */
|
||||
Application.Controllers.controller('TrainingsAdminController', ['$scope', '$state', '$uibModal', 'Training', 'trainingsPromise', 'machinesPromise', '_t', 'growl', 'dialogs', 'Member', 'uiTourService',
|
||||
function ($scope, $state, $uibModal, Training, trainingsPromise, machinesPromise, _t, growl, dialogs, Member, uiTourService) {
|
||||
|
||||
// list of trainings
|
||||
let groupAvailabilities;
|
||||
$scope.trainings = trainingsPromise;
|
||||
|
||||
// simplified list of machines
|
||||
$scope.machines = machinesPromise;
|
||||
|
||||
// Training to monitor, binded with drop-down selection
|
||||
$scope.monitoring =
|
||||
{ training: null };
|
||||
// Training to monitor, bound with drop-down selection
|
||||
$scope.monitoring = { training: null };
|
||||
|
||||
// list of training availabilies, grouped by date
|
||||
// list of training availabilities, grouped by date
|
||||
$scope.groupedAvailabilities = {};
|
||||
|
||||
// default: accordions are not open
|
||||
@ -184,6 +181,9 @@ Application.Controllers.controller('TrainingsAdminController', ['$scope', '$stat
|
||||
'all'
|
||||
];
|
||||
|
||||
// default tab: trainings list
|
||||
$scope.tabs = { active: 0 };
|
||||
|
||||
/**
|
||||
* In the trainings listing tab, return the stringified list of machines associated with the provided training
|
||||
* @param training {Object} Training object, inherited from $resource
|
||||
@ -335,14 +335,107 @@ Application.Controllers.controller('TrainingsAdminController', ['$scope', '$stat
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Setup the feature-tour for the admin/trainings page.
|
||||
* This is intended as a contextual help (when pressing F1)
|
||||
*/
|
||||
$scope.setupTrainingsTour = function () {
|
||||
// get the tour defined by the ui-tour directive
|
||||
const uitour = uiTourService.getTourByName('trainings');
|
||||
uitour.createStep({
|
||||
selector: 'body',
|
||||
stepId: 'welcome',
|
||||
order: 0,
|
||||
title: _t('app.admin.tour.trainings.welcome.title'),
|
||||
content: _t('app.admin.tour.trainings.welcome.content'),
|
||||
placement: 'bottom',
|
||||
orphan: true
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.trainings-monitoring .manage-trainings',
|
||||
stepId: 'trainings',
|
||||
order: 1,
|
||||
title: _t('app.admin.tour.trainings.trainings.title'),
|
||||
content: _t('app.admin.tour.trainings.trainings.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.trainings-monitoring .filter-trainings',
|
||||
stepId: 'filter',
|
||||
order: 2,
|
||||
title: _t('app.admin.tour.trainings.filter.title'),
|
||||
content: _t('app.admin.tour.trainings.filter.content'),
|
||||
placement: 'left'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.trainings-monitoring .post-tracking',
|
||||
stepId: 'tracking',
|
||||
order: 3,
|
||||
title: _t('app.admin.tour.trainings.tracking.title'),
|
||||
content: _t('app.admin.tour.trainings.tracking.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: 'body',
|
||||
stepId: 'conclusion',
|
||||
order: 4,
|
||||
title: _t('app.admin.tour.conclusion.title'),
|
||||
content: _t('app.admin.tour.conclusion.content'),
|
||||
placement: 'bottom',
|
||||
orphan: true
|
||||
});
|
||||
// on step change, change the active tab if needed
|
||||
uitour.on('stepChanged', function (nextStep) {
|
||||
if (nextStep.stepId === 'filter' || nextStep.stepId === 'machines') { $scope.tabs.active = 0; }
|
||||
if (nextStep.stepId === 'tracking') { $scope.tabs.active = 1; }
|
||||
});
|
||||
// on tour end, save the status in database
|
||||
uitour.on('ended', function () {
|
||||
if (uitour.getStatus() === uitour.Status.ON && $scope.currentUser.profile.tours.indexOf('trainings') < 0) {
|
||||
Member.completeTour({ id: $scope.currentUser.id }, { tour: 'trainings' }, function (res) {
|
||||
$scope.currentUser.profile.tours = res.tours;
|
||||
});
|
||||
}
|
||||
});
|
||||
// if the user has never seen the tour, show him now
|
||||
if (Fablab.featureTourDisplay !== 'manual' && $scope.currentUser.profile.tours.indexOf('trainings') < 0) {
|
||||
uitour.start();
|
||||
}
|
||||
// start this tour when an user press F1 - this is contextual help
|
||||
window.addEventListener('keydown', handleF1);
|
||||
}
|
||||
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
// listen the $destroy event of the controller to remove the F1 key binding
|
||||
$scope.$on('$destroy', function () {
|
||||
window.removeEventListener('keydown', handleF1);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback used to trigger the feature tour when the user press the F1 key.
|
||||
* @param e {KeyboardEvent}
|
||||
*/
|
||||
const handleF1 = function (e) {
|
||||
if (e.key === 'F1') {
|
||||
e.preventDefault();
|
||||
const tour = uiTourService.getTourByName('trainings');
|
||||
if (tour) { tour.start(); }
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Group the trainings availabilities by trainings and by dates and return the resulting tree
|
||||
* @param trainings {Array} $scope.trainings is expected here
|
||||
* @returns {Object} Tree constructed as /training_name/year/month/day/[availabilities]
|
||||
*/
|
||||
return groupAvailabilities = function (trainings) {
|
||||
const groupAvailabilities = function (trainings) {
|
||||
const tree = {};
|
||||
for (let training of Array.from(trainings)) {
|
||||
tree[training.name] = {};
|
||||
@ -367,6 +460,9 @@ Application.Controllers.controller('TrainingsAdminController', ['$scope', '$stat
|
||||
}
|
||||
return tree;
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize();
|
||||
}
|
||||
|
||||
]);
|
||||
|
@ -12,8 +12,8 @@
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
|
||||
Application.Controllers.controller('ApplicationController', ['$rootScope', '$scope', '$window', '$locale', 'Session', 'AuthService', 'Auth', '$uibModal', '$state', 'growl', 'Notification', '$interval', 'Setting', '_t', 'Version',
|
||||
function ($rootScope, $scope, $window, $locale, Session, AuthService, Auth, $uibModal, $state, growl, Notification, $interval, Setting, _t, Version) {
|
||||
Application.Controllers.controller('ApplicationController', ['$rootScope', '$scope', '$window', '$locale', '$timeout', 'Session', 'AuthService', 'Auth', '$uibModal', '$state', 'growl', 'Notification', '$interval', 'Setting', '_t', 'Version',
|
||||
function ($rootScope, $scope, $window, $locale, $timeout, Session, AuthService, Auth, $uibModal, $state, growl, Notification, $interval, Setting, _t, Version) {
|
||||
/* PRIVATE STATIC CONSTANTS */
|
||||
|
||||
// User's notifications will get refreshed every 30s
|
||||
@ -37,7 +37,7 @@ Application.Controllers.controller('ApplicationController', ['$rootScope', '$sco
|
||||
$rootScope.currentUser = user;
|
||||
Session.create(user);
|
||||
getNotifications();
|
||||
// fab-manager's app-version
|
||||
// Fab-manager's app-version
|
||||
if (user.role === 'admin') {
|
||||
return $scope.version = Version.get();
|
||||
} else {
|
||||
@ -267,8 +267,12 @@ Application.Controllers.controller('ApplicationController', ['$rootScope', '$sco
|
||||
toggler.toggleClass('active');
|
||||
};
|
||||
|
||||
/**
|
||||
* Open the modal dialog showing that an upgrade is available
|
||||
*/
|
||||
$scope.versionModal = function() {
|
||||
if ($scope.version.up_to_date) return;
|
||||
if ($rootScope.currentUser.role !== 'admin') return;
|
||||
|
||||
$uibModal.open({
|
||||
templateUrl: '<%= asset_path "admin/versions/upgradeModal.html" %>',
|
||||
@ -279,6 +283,20 @@ Application.Controllers.controller('ApplicationController', ['$rootScope', '$sco
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger the contextual help "feature tour".
|
||||
* @param event {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
*/
|
||||
$scope.help = function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
// we wrap the event triggering into a $timeout to prevent conflicting with current $apply
|
||||
$timeout(function () {
|
||||
var evt = new KeyboardEvent('keydown', { key: 'F1' });
|
||||
window.dispatchEvent(evt);
|
||||
});
|
||||
}
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
@ -329,10 +347,10 @@ Application.Controllers.controller('ApplicationController', ['$rootScope', '$sco
|
||||
};
|
||||
|
||||
/**
|
||||
* Retreive once the notifications from the server and display a message popup for each new one.
|
||||
* Retrieve once the notifications from the server and display a message popup for each new one.
|
||||
* Then, periodically check for new notifications.
|
||||
*/
|
||||
var getNotifications = function () {
|
||||
const getNotifications = function () {
|
||||
$rootScope.toCheckNotifications = true;
|
||||
if (!$rootScope.checkNotificationsIsInit && !!$rootScope.currentUser) {
|
||||
setTimeout(function () {
|
||||
@ -373,7 +391,7 @@ Application.Controllers.controller('ApplicationController', ['$rootScope', '$sco
|
||||
/**
|
||||
* Open the modal window allowing the user to log in.
|
||||
*/
|
||||
var openLoginModal = function (toState, toParams, callback) {
|
||||
const openLoginModal = function (toState, toParams, callback) {
|
||||
<% active_provider = AuthProvider.active %>
|
||||
<% if active_provider.providable_type != DatabaseProvider.name %>
|
||||
$window.location.href = '/sso-redirect';
|
||||
@ -480,7 +498,7 @@ Application.Controllers.controller('ApplicationController', ['$rootScope', '$sco
|
||||
* When the status changes, the callback is triggered with the new status as parameter
|
||||
* Inspired by http://stackoverflow.com/questions/1060008/is-there-a-way-to-detect-if-a-browser-window-is-not-currently-active#answer-1060034
|
||||
*/
|
||||
var onPageVisible = function (callback) {
|
||||
const onPageVisible = function (callback) {
|
||||
let hidden = 'hidden';
|
||||
|
||||
const onchange = function (evt) {
|
||||
|
@ -1,28 +1,68 @@
|
||||
'use strict';
|
||||
|
||||
Application.Controllers.controller('HomeController', ['$scope', '$stateParams', 'homeContentPromise',
|
||||
function ($scope, $stateParams, homeContentPromise) {
|
||||
Application.Controllers.controller('HomeController', ['$scope', '$stateParams', 'settingsPromise', 'Member', 'uiTourService', '_t',
|
||||
function ($scope, $stateParams, settingsPromise, Member, uiTourService, _t) {
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// Home page HTML content
|
||||
$scope.homeContent = null;
|
||||
|
||||
// Status of the components in the home page (exists or not?)
|
||||
$scope.status = {
|
||||
news: false,
|
||||
projects: false,
|
||||
twitter: false,
|
||||
members: false,
|
||||
events: false
|
||||
};
|
||||
|
||||
/**
|
||||
* Setup the feature-tour for the home page. (admins only)
|
||||
* This is intended as a contextual help (when pressing F1)
|
||||
*/
|
||||
$scope.setupHomeTour = function () {
|
||||
if ($scope.currentUser && $scope.currentUser.role === 'admin') {
|
||||
setupWelcomeTour();
|
||||
}
|
||||
};
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
// if we recieve a token to reset the password as GET parameter, trigger the
|
||||
// if we receive a token to reset the password as GET parameter, trigger the
|
||||
// changePassword modal from the parent controller
|
||||
if ($stateParams.reset_password_token) {
|
||||
return $scope.$parent.editPassword($stateParams.reset_password_token);
|
||||
}
|
||||
|
||||
// We set the home page content, with the directives replacing the placeholders
|
||||
$scope.homeContent = insertDirectives(homeContentPromise.setting.value);
|
||||
$scope.homeContent = insertDirectives(settingsPromise.home_content);
|
||||
|
||||
// listen the $destroy event of the controller to remove the F1 key binding
|
||||
$scope.$on('$destroy', function () {
|
||||
window.removeEventListener('keydown', handleF1);
|
||||
});
|
||||
|
||||
// for admins, setup the tour on login
|
||||
$scope.$watch('currentUser', function (newValue, oldValue) {
|
||||
if (!oldValue && newValue && newValue.role === 'admin') {
|
||||
const uitour = uiTourService.getTourByName('welcome');
|
||||
if (!uitour.hasStep()) {
|
||||
setupWelcomeTour();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse the provided html and replace the elements with special IDs (#news, #projects, #twitter, #members, #events)
|
||||
* by their respective angular directives
|
||||
* @param html {String} a valid html string, as defined by the summernote editor in admin/settings/home_page
|
||||
* @returns {string} a valid html string containing angular directives for the specified plugins
|
||||
*/
|
||||
const insertDirectives = function (html) {
|
||||
const node = document.createElement('div');
|
||||
node.innerHTML = html.trim();
|
||||
@ -30,31 +70,255 @@ Application.Controllers.controller('HomeController', ['$scope', '$stateParams',
|
||||
node.querySelectorAll('div#news').forEach((newsNode) => {
|
||||
const news = document.createElement('news');
|
||||
newsNode.parentNode.replaceChild(news, newsNode);
|
||||
$scope.status.news = true;
|
||||
});
|
||||
|
||||
node.querySelectorAll('div#projects').forEach((projectsNode) => {
|
||||
const projects = document.createElement('projects');
|
||||
projectsNode.parentNode.replaceChild(projects, projectsNode);
|
||||
$scope.status.projects = true;
|
||||
});
|
||||
|
||||
node.querySelectorAll('div#twitter').forEach((twitterNode) => {
|
||||
const twitter = document.createElement('twitter');
|
||||
twitterNode.parentNode.replaceChild(twitter, twitterNode);
|
||||
$scope.status.twitter = true;
|
||||
});
|
||||
|
||||
node.querySelectorAll('div#members').forEach((membersNode) => {
|
||||
const members = document.createElement('members');
|
||||
membersNode.parentNode.replaceChild(members, membersNode);
|
||||
$scope.status.members = true;
|
||||
});
|
||||
|
||||
node.querySelectorAll('div#events').forEach((eventsNode) => {
|
||||
const events = document.createElement('events');
|
||||
eventsNode.parentNode.replaceChild(events, eventsNode);
|
||||
$scope.status.events = true;
|
||||
});
|
||||
|
||||
return node.outerHTML;
|
||||
};
|
||||
|
||||
/**
|
||||
* Setup the feature-tour for the home page that will present an overview of the whole app.
|
||||
* This is intended as a contextual help.
|
||||
*/
|
||||
const setupWelcomeTour = function () {
|
||||
// get the tour defined by the ui-tour directive
|
||||
const uitour = uiTourService.getTourByName('welcome');
|
||||
// add the steps
|
||||
uitour.createStep({
|
||||
selector: 'body',
|
||||
stepId: 'welcome',
|
||||
order: 0,
|
||||
title: _t('app.public.tour.welcome.welcome.title'),
|
||||
content: _t('app.public.tour.welcome.welcome.content'),
|
||||
placement: 'bottom',
|
||||
orphan: true
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.nav-primary li.home-link',
|
||||
stepId: 'home',
|
||||
order: 1,
|
||||
title: _t('app.public.tour.welcome.home.title'),
|
||||
content: _t('app.public.tour.welcome.home.content'),
|
||||
placement: 'right'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.nav-primary li.public-calendar-link',
|
||||
stepId: 'calendar',
|
||||
order: 2,
|
||||
title: _t('app.public.tour.welcome.calendar.title'),
|
||||
content: _t('app.public.tour.welcome.calendar.content'),
|
||||
placement: 'right'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.nav-primary li.reserve-machine-link',
|
||||
stepId: 'machines',
|
||||
order: 3,
|
||||
title: _t('app.public.tour.welcome.machines.title'),
|
||||
content: _t('app.public.tour.welcome.machines.content'),
|
||||
placement: 'right'
|
||||
});
|
||||
if (!Fablab.withoutSpaces) {
|
||||
uitour.createStep({
|
||||
selector: '.nav-primary li.reserve-space-link',
|
||||
stepId: 'spaces',
|
||||
order: 4,
|
||||
title: _t('app.public.tour.welcome.spaces.title'),
|
||||
content: _t('app.public.tour.welcome.spaces.content'),
|
||||
placement: 'right'
|
||||
});
|
||||
}
|
||||
uitour.createStep({
|
||||
selector: '.nav-primary li.reserve-training-link',
|
||||
stepId: 'trainings',
|
||||
order: 5,
|
||||
title: _t('app.public.tour.welcome.trainings.title'),
|
||||
content: _t('app.public.tour.welcome.trainings.content'),
|
||||
placement: 'right'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.nav-primary li.reserve-event-link',
|
||||
stepId: 'events',
|
||||
order: 6,
|
||||
title: _t('app.public.tour.welcome.events.title'),
|
||||
content: _t('app.public.tour.welcome.events.content'),
|
||||
placement: 'right'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.nav-primary li.projects-gallery-link',
|
||||
stepId: 'projects',
|
||||
order: 7,
|
||||
title: _t('app.public.tour.welcome.projects.title'),
|
||||
content: _t('app.public.tour.welcome.projects.content'),
|
||||
placement: 'right'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.nav-primary li.plans-link',
|
||||
stepId: 'plans',
|
||||
order: 8,
|
||||
title: _t('app.public.tour.welcome.plans.title'),
|
||||
content: _t('app.public.tour.welcome.plans.content'),
|
||||
placement: 'right'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.nav-primary .admin-section',
|
||||
stepId: 'admin',
|
||||
order: 9,
|
||||
title: _t('app.public.tour.welcome.admin.title'),
|
||||
content: _t('app.public.tour.welcome.admin.content'),
|
||||
placement: 'right'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.navbar.header li.about-page-link',
|
||||
stepId: 'about',
|
||||
order: 10,
|
||||
title: _t('app.public.tour.welcome.about.title'),
|
||||
content: _t('app.public.tour.welcome.about.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.navbar.header li.notification-center-link',
|
||||
stepId: 'notifications',
|
||||
order: 11,
|
||||
title: _t('app.public.tour.welcome.notifications.title'),
|
||||
content: _t('app.public.tour.welcome.notifications.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.navbar.header li.user-menu-dropdown',
|
||||
stepId: 'profile',
|
||||
order: 12,
|
||||
title: _t('app.public.tour.welcome.profile.title'),
|
||||
content: _t('app.public.tour.welcome.profile.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
if ($scope.status.news && settingsPromise.home_blogpost) {
|
||||
uitour.createStep({
|
||||
selector: 'news',
|
||||
stepId: 'news',
|
||||
order: 13,
|
||||
title: _t('app.public.tour.welcome.news.title'),
|
||||
content: _t('app.public.tour.welcome.news.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
}
|
||||
if ($scope.status.projects) {
|
||||
uitour.createStep({
|
||||
selector: 'projects',
|
||||
stepId: 'last_projects',
|
||||
order: 14,
|
||||
title: _t('app.public.tour.welcome.last_projects.title'),
|
||||
content: _t('app.public.tour.welcome.last_projects.content'),
|
||||
placement: 'top'
|
||||
});
|
||||
}
|
||||
if ($scope.status.twitter) {
|
||||
uitour.createStep({
|
||||
selector: 'twitter',
|
||||
stepId: 'last_tweet',
|
||||
order: 15,
|
||||
title: _t('app.public.tour.welcome.last_tweet.title'),
|
||||
content: _t('app.public.tour.welcome.last_tweet.content'),
|
||||
placement: 'left'
|
||||
});
|
||||
}
|
||||
if ($scope.status.members) {
|
||||
uitour.createStep({
|
||||
selector: 'members',
|
||||
stepId: 'last_members',
|
||||
order: 16,
|
||||
title: _t('app.public.tour.welcome.last_members.title'),
|
||||
content: _t('app.public.tour.welcome.last_members.content'),
|
||||
placement: 'left'
|
||||
});
|
||||
}
|
||||
if ($scope.status.events) {
|
||||
uitour.createStep({
|
||||
selector: 'events',
|
||||
stepId: 'next_events',
|
||||
order: 17,
|
||||
title: _t('app.public.tour.welcome.next_events.title'),
|
||||
content: _t('app.public.tour.welcome.next_events.content'),
|
||||
placement: 'top'
|
||||
});
|
||||
}
|
||||
uitour.createStep({
|
||||
selector: 'body',
|
||||
stepId: 'customize',
|
||||
order: 18,
|
||||
title: _t('app.public.tour.welcome.customize.title'),
|
||||
content: _t('app.public.tour.welcome.customize.content'),
|
||||
placement: 'bottom',
|
||||
orphan: 'true'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.app-generator .app-version',
|
||||
stepId: 'version',
|
||||
order: 19,
|
||||
title: _t('app.public.tour.welcome.version.title'),
|
||||
content: _t('app.public.tour.welcome.version.content'),
|
||||
placement: 'top'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: 'body',
|
||||
stepId: 'conclusion',
|
||||
order: 20,
|
||||
title: _t('app.public.tour.conclusion.title'),
|
||||
content: _t('app.public.tour.conclusion.content'),
|
||||
placement: 'bottom',
|
||||
orphan: true
|
||||
});
|
||||
// on tour end, save the status in database
|
||||
uitour.on('ended', function () {
|
||||
if (uitour.getStatus() === uitour.Status.ON && $scope.currentUser.profile.tours.indexOf('welcome') < 0) {
|
||||
Member.completeTour({ id: $scope.currentUser.id }, { tour: 'welcome' }, function (res) {
|
||||
$scope.currentUser.profile.tours = res.tours;
|
||||
});
|
||||
}
|
||||
});
|
||||
// if the user has never seen the tour, show him now
|
||||
if (Fablab.featureTourDisplay !== 'manual' && $scope.currentUser.profile.tours.indexOf('welcome') < 0) {
|
||||
uitour.start();
|
||||
}
|
||||
// start this tour when an user press F1 - this is contextual help
|
||||
window.addEventListener('keydown', handleF1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback used to trigger the feature tour when the user press the F1 key.
|
||||
* @param e {KeyboardEvent}
|
||||
*/
|
||||
const handleF1 = function (e) {
|
||||
if (e.key === 'F1') {
|
||||
e.preventDefault();
|
||||
const tour = uiTourService.getTourByName('welcome');
|
||||
if (tour) { tour.start(); }
|
||||
}
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize();
|
||||
}
|
||||
|
@ -180,8 +180,10 @@ const _reserveMachine = function (machine, e) {
|
||||
/**
|
||||
* Controller used in the public listing page, allowing everyone to see the list of machines
|
||||
*/
|
||||
Application.Controllers.controller('MachinesController', ['$scope', '$state', '_t', 'Machine', '$uibModal', 'machinesPromise',
|
||||
function ($scope, $state, _t, Machine, $uibModal, machinesPromise) {
|
||||
Application.Controllers.controller('MachinesController', ['$scope', '$state', '_t', 'Machine', '$uibModal', 'machinesPromise', 'Member', 'uiTourService',
|
||||
function ($scope, $state, _t, Machine, $uibModal, machinesPromise, Member, uiTourService) {
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// Retrieve the list of machines
|
||||
$scope.machines = machinesPromise;
|
||||
|
||||
@ -205,11 +207,92 @@ Application.Controllers.controller('MachinesController', ['$scope', '$state', '_
|
||||
$scope.machineFiltering = 'enabled';
|
||||
|
||||
// Available options for filtering machines by status
|
||||
return $scope.filterDisabled = [
|
||||
$scope.filterDisabled = [
|
||||
'enabled',
|
||||
'disabled',
|
||||
'all'
|
||||
];
|
||||
|
||||
/**
|
||||
* Setup the feature-tour for the machines page. (admins only)
|
||||
* This is intended as a contextual help (when pressing F1)
|
||||
*/
|
||||
$scope.setupMachinesTour = function () {
|
||||
// setup the tour for admins only
|
||||
if ($scope.currentUser && $scope.currentUser.role === 'admin') {
|
||||
// get the tour defined by the ui-tour directive
|
||||
const uitour = uiTourService.getTourByName('machines');
|
||||
uitour.createStep({
|
||||
selector: 'body',
|
||||
stepId: 'welcome',
|
||||
order: 0,
|
||||
title: _t('app.public.tour.machines.welcome.title'),
|
||||
content: _t('app.public.tour.machines.welcome.content'),
|
||||
placement: 'bottom',
|
||||
orphan: true
|
||||
});
|
||||
if ($scope.machines.length > 0) {
|
||||
uitour.createStep({
|
||||
selector: '.machines-list .show-button',
|
||||
stepId: 'view',
|
||||
order: 1,
|
||||
title: _t('app.public.tour.machines.view.title'),
|
||||
content: _t('app.public.tour.machines.view.content'),
|
||||
placement: 'top'
|
||||
});
|
||||
}
|
||||
uitour.createStep({
|
||||
selector: 'body',
|
||||
stepId: 'conclusion',
|
||||
order: 2,
|
||||
title: _t('app.public.tour.conclusion.title'),
|
||||
content: _t('app.public.tour.conclusion.content'),
|
||||
placement: 'bottom',
|
||||
orphan: true
|
||||
});
|
||||
// on tour end, save the status in database
|
||||
uitour.on('ended', function () {
|
||||
if (uitour.getStatus() === uitour.Status.ON && $scope.currentUser.profile.tours.indexOf('machines') < 0) {
|
||||
Member.completeTour({ id: $scope.currentUser.id }, { tour: 'machines' }, function (res) {
|
||||
$scope.currentUser.profile.tours = res.tours;
|
||||
});
|
||||
}
|
||||
});
|
||||
// if the user has never seen the tour, show him now
|
||||
if (Fablab.featureTourDisplay !== 'manual' && $scope.currentUser.profile.tours.indexOf('machines') < 0) {
|
||||
uitour.start();
|
||||
}
|
||||
// start this tour when an user press F1 - this is contextual help
|
||||
window.addEventListener('keydown', handleF1);
|
||||
}
|
||||
}
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
// listen the $destroy event of the controller to remove the F1 key binding
|
||||
$scope.$on('$destroy', function () {
|
||||
window.removeEventListener('keydown', handleF1);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback used to trigger the feature tour when the user press the F1 key.
|
||||
* @param e {KeyboardEvent}
|
||||
*/
|
||||
const handleF1 = function (e) {
|
||||
if (e.key === 'F1') {
|
||||
e.preventDefault();
|
||||
const tour = uiTourService.getTourByName('machines');
|
||||
if (tour) { tour.start(); }
|
||||
}
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize();
|
||||
}
|
||||
]);
|
||||
|
||||
|
@ -19,34 +19,42 @@ Application.Controllers.controller('MainNavController', ['$scope', function ($sc
|
||||
{
|
||||
state: 'app.public.home',
|
||||
linkText: 'app.public.common.home',
|
||||
linkIcon: 'home'
|
||||
linkIcon: 'home',
|
||||
class: 'home-link'
|
||||
},
|
||||
{ class: 'menu-spacer' },
|
||||
{
|
||||
state: 'app.public.calendar',
|
||||
linkText: 'app.public.common.public_calendar',
|
||||
linkIcon: 'calendar',
|
||||
class: 'public-calendar-link'
|
||||
},
|
||||
|
||||
{
|
||||
state: 'app.public.machines_list',
|
||||
linkText: 'app.public.common.reserve_a_machine',
|
||||
linkIcon: 'cogs'
|
||||
linkIcon: 'cogs',
|
||||
class: 'reserve-machine-link'
|
||||
},
|
||||
{
|
||||
state: 'app.public.trainings_list',
|
||||
linkText: 'app.public.common.trainings_registrations',
|
||||
linkIcon: 'graduation-cap'
|
||||
linkIcon: 'graduation-cap',
|
||||
class: 'reserve-training-link'
|
||||
},
|
||||
{
|
||||
state: 'app.public.events_list',
|
||||
linkText: 'app.public.common.events_registrations',
|
||||
linkIcon: 'tags'
|
||||
},
|
||||
{
|
||||
state: 'app.public.calendar',
|
||||
linkText: 'app.public.common.public_calendar',
|
||||
linkIcon: 'calendar'
|
||||
linkIcon: 'tags',
|
||||
class: 'reserve-event-link'
|
||||
},
|
||||
{ class: 'menu-spacer' },
|
||||
{
|
||||
state: 'app.public.projects_list',
|
||||
linkText: 'app.public.common.projects_gallery',
|
||||
linkIcon: 'th'
|
||||
}
|
||||
linkIcon: 'th',
|
||||
class: 'projects-gallery-link'
|
||||
},
|
||||
{ class: 'menu-spacer' }
|
||||
|
||||
];
|
||||
|
||||
@ -54,70 +62,74 @@ Application.Controllers.controller('MainNavController', ['$scope', function ($sc
|
||||
$scope.navLinks.push({
|
||||
state: 'app.public.plans',
|
||||
linkText: 'app.public.common.subscriptions',
|
||||
linkIcon: 'credit-card'
|
||||
linkIcon: 'credit-card',
|
||||
class: 'plans-link'
|
||||
});
|
||||
}
|
||||
|
||||
if (!Fablab.withoutSpaces) {
|
||||
$scope.navLinks.splice(3, 0, {
|
||||
$scope.navLinks.splice(4, 0, {
|
||||
state: 'app.public.spaces_list',
|
||||
linkText: 'app.public.common.reserve_a_space',
|
||||
linkIcon: 'rocket'
|
||||
linkIcon: 'rocket',
|
||||
class: 'reserve-space-link'
|
||||
});
|
||||
}
|
||||
|
||||
Fablab.adminNavLinks = Fablab.adminNavLinks || [];
|
||||
const adminNavLinks = [
|
||||
{
|
||||
state: 'app.admin.trainings',
|
||||
linkText: 'app.public.common.trainings_monitoring',
|
||||
linkIcon: 'graduation-cap'
|
||||
},
|
||||
{
|
||||
state: 'app.admin.calendar',
|
||||
linkText: 'app.public.common.manage_the_calendar',
|
||||
linkIcon: 'calendar'
|
||||
},
|
||||
{
|
||||
state: 'app.admin.members',
|
||||
linkText: 'app.public.common.manage_the_users',
|
||||
linkIcon: 'users'
|
||||
},
|
||||
{
|
||||
state: 'app.admin.invoices',
|
||||
linkText: 'app.public.common.manage_the_invoices',
|
||||
linkIcon: 'file-pdf-o'
|
||||
},
|
||||
{
|
||||
state: 'app.admin.pricing',
|
||||
linkText: 'app.public.common.subscriptions_and_prices',
|
||||
linkIcon: 'money'
|
||||
},
|
||||
{
|
||||
state: 'app.admin.events',
|
||||
linkText: 'app.public.common.manage_the_events',
|
||||
linkIcon: 'tags'
|
||||
},
|
||||
{
|
||||
state: 'app.public.machines_list',
|
||||
linkText: 'app.public.common.manage_the_machines',
|
||||
linkIcon: 'cogs'
|
||||
},
|
||||
{
|
||||
state: 'app.admin.project_elements',
|
||||
linkText: 'app.public.common.manage_the_projects_elements',
|
||||
linkIcon: 'tasks'
|
||||
state: 'app.admin.trainings',
|
||||
linkText: 'app.public.common.trainings_monitoring',
|
||||
linkIcon: 'graduation-cap'
|
||||
},
|
||||
{
|
||||
state: 'app.admin.events',
|
||||
linkText: 'app.public.common.manage_the_events',
|
||||
linkIcon: 'tags'
|
||||
},
|
||||
{ class: 'menu-spacer' },
|
||||
{
|
||||
state: 'app.admin.members',
|
||||
linkText: 'app.public.common.manage_the_users',
|
||||
linkIcon: 'users'
|
||||
},
|
||||
{
|
||||
state: 'app.admin.pricing',
|
||||
linkText: 'app.public.common.subscriptions_and_prices',
|
||||
linkIcon: 'money'
|
||||
},
|
||||
{
|
||||
state: 'app.admin.invoices',
|
||||
linkText: 'app.public.common.manage_the_invoices',
|
||||
linkIcon: 'file-pdf-o'
|
||||
},
|
||||
{
|
||||
state: 'app.admin.statistics',
|
||||
linkText: 'app.public.common.statistics',
|
||||
linkIcon: 'bar-chart-o'
|
||||
},
|
||||
{ class: 'menu-spacer' },
|
||||
{
|
||||
state: 'app.admin.settings',
|
||||
linkText: 'app.public.common.customization',
|
||||
linkIcon: 'gear'
|
||||
},
|
||||
{
|
||||
state: 'app.admin.project_elements',
|
||||
linkText: 'app.public.common.manage_the_projects_elements',
|
||||
linkIcon: 'tasks'
|
||||
},
|
||||
{
|
||||
state: 'app.admin.open_api_clients',
|
||||
linkText: 'app.public.common.open_api_clients',
|
||||
@ -128,7 +140,7 @@ Application.Controllers.controller('MainNavController', ['$scope', function ($sc
|
||||
$scope.adminNavLinks = adminNavLinks;
|
||||
|
||||
if (!Fablab.withoutSpaces) {
|
||||
return $scope.adminNavLinks.splice(7, 0, {
|
||||
return $scope.adminNavLinks.splice(4, 0, {
|
||||
state: 'app.public.spaces_list',
|
||||
linkText: 'app.public.common.manage_the_spaces',
|
||||
linkIcon: 'rocket'
|
||||
|
@ -206,7 +206,7 @@ Application.Controllers.controller('CompleteProfileController', ['$scope', '$roo
|
||||
CSRF.setMetaTags();
|
||||
|
||||
// init the birth date to JS object
|
||||
$scope.user.statistic_profile.birthday = moment($scope.user.statistic_profile.birthday).toDate();
|
||||
$scope.user.statistic_profile.birthday = $scope.user.statistic_profile.birthday ? moment($scope.user.statistic_profile.birthday).toDate() : undefined;
|
||||
|
||||
// bind fields protection with sso fields
|
||||
angular.forEach(activeProviderPromise.mapping, function (map) { $scope.preventField[map] = true; });
|
||||
|
@ -98,30 +98,115 @@ class SpacesController {
|
||||
/**
|
||||
* Controller used in the public listing page, allowing everyone to see the list of spaces
|
||||
*/
|
||||
Application.Controllers.controller('SpacesController', ['$scope', '$state', 'spacesPromise', function ($scope, $state, spacesPromise) {
|
||||
// Retrieve the list of spaces
|
||||
$scope.spaces = spacesPromise;
|
||||
Application.Controllers.controller('SpacesController', ['$scope', '$state', 'spacesPromise', '_t', 'Member', 'uiTourService',
|
||||
function ($scope, $state, spacesPromise, _t, Member, uiTourService) {
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
/**
|
||||
* Redirect the user to the space details page
|
||||
*/
|
||||
$scope.showSpace = function (space) { $state.go('app.public.space_show', { id: space.slug }); };
|
||||
// Retrieve the list of spaces
|
||||
$scope.spaces = spacesPromise;
|
||||
|
||||
/**
|
||||
* Callback to book a reservation for the current space
|
||||
*/
|
||||
$scope.reserveSpace = function (space) { $state.go('app.logged.space_reserve', { id: space.slug }); };
|
||||
/**
|
||||
* Redirect the user to the space details page
|
||||
*/
|
||||
$scope.showSpace = function (space) { $state.go('app.public.space_show', { id: space.slug }); };
|
||||
|
||||
// Default: we show only enabled spaces
|
||||
$scope.spaceFiltering = 'enabled';
|
||||
/**
|
||||
* Callback to book a reservation for the current space
|
||||
*/
|
||||
$scope.reserveSpace = function (space) { $state.go('app.logged.space_reserve', { id: space.slug }); };
|
||||
|
||||
// Available options for filtering spaces by status
|
||||
$scope.filterDisabled = [
|
||||
'enabled',
|
||||
'disabled',
|
||||
'all'
|
||||
];
|
||||
}]);
|
||||
// Default: we show only enabled spaces
|
||||
$scope.spaceFiltering = 'enabled';
|
||||
|
||||
// Available options for filtering spaces by status
|
||||
$scope.filterDisabled = [
|
||||
'enabled',
|
||||
'disabled',
|
||||
'all'
|
||||
];
|
||||
|
||||
/**
|
||||
* Setup the feature-tour for the spaces page. (admins only)
|
||||
* This is intended as a contextual help (when pressing F1)
|
||||
*/
|
||||
$scope.setupSpacesTour = function () {
|
||||
// setup the tour for admins only
|
||||
if ($scope.currentUser && $scope.currentUser.role === 'admin') {
|
||||
// get the tour defined by the ui-tour directive
|
||||
const uitour = uiTourService.getTourByName('spaces');
|
||||
uitour.createStep({
|
||||
selector: 'body',
|
||||
stepId: 'welcome',
|
||||
order: 0,
|
||||
title: _t('app.public.tour.spaces.welcome.title'),
|
||||
content: _t('app.public.tour.spaces.welcome.content'),
|
||||
placement: 'bottom',
|
||||
orphan: true
|
||||
});
|
||||
if ($scope.spaces.length > 0) {
|
||||
uitour.createStep({
|
||||
selector: '.spaces-list .show-button',
|
||||
stepId: 'view',
|
||||
order: 1,
|
||||
title: _t('app.public.tour.spaces.view.title'),
|
||||
content: _t('app.public.tour.spaces.view.content'),
|
||||
placement: 'top'
|
||||
});
|
||||
}
|
||||
uitour.createStep({
|
||||
selector: 'body',
|
||||
stepId: 'conclusion',
|
||||
order: 2,
|
||||
title: _t('app.public.tour.conclusion.title'),
|
||||
content: _t('app.public.tour.conclusion.content'),
|
||||
placement: 'bottom',
|
||||
orphan: true
|
||||
});
|
||||
// on tour end, save the status in database
|
||||
uitour.on('ended', function () {
|
||||
if (uitour.getStatus() === uitour.Status.ON && $scope.currentUser.profile.tours.indexOf('spaces') < 0) {
|
||||
Member.completeTour({ id: $scope.currentUser.id }, { tour: 'spaces' }, function (res) {
|
||||
$scope.currentUser.profile.tours = res.tours;
|
||||
});
|
||||
}
|
||||
});
|
||||
// if the user has never seen the tour, show him now
|
||||
if (Fablab.featureTourDisplay !== 'manual' && $scope.currentUser.profile.tours.indexOf('spaces') < 0) {
|
||||
uitour.start();
|
||||
}
|
||||
// start this tour when an user press F1 - this is contextual help
|
||||
window.addEventListener('keydown', handleF1);
|
||||
}
|
||||
}
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
// listen the $destroy event of the controller to remove the F1 key binding
|
||||
$scope.$on('$destroy', function () {
|
||||
window.removeEventListener('keydown', handleF1);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback used to trigger the feature tour when the user press the F1 key.
|
||||
* @param e {KeyboardEvent}
|
||||
*/
|
||||
const handleF1 = function (e) {
|
||||
if (e.key === 'F1') {
|
||||
e.preventDefault();
|
||||
const tour = uiTourService.getTourByName('spaces');
|
||||
if (tour) { tour.start(); }
|
||||
}
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize();
|
||||
}
|
||||
]);
|
||||
|
||||
/**
|
||||
* Controller used in the space creation page (admin)
|
||||
|
12
app/assets/javascripts/directives/post_render.js
Normal file
12
app/assets/javascripts/directives/post_render.js
Normal file
@ -0,0 +1,12 @@
|
||||
Application.Directives.directive('postRender', [ '$timeout',
|
||||
function ($timeout) {
|
||||
return ({
|
||||
restrict: 'A',
|
||||
terminal: false,
|
||||
transclude: false,
|
||||
link: function (scope, element, attrs) {
|
||||
$timeout(scope[attrs.postRender], 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
]);
|
@ -4,9 +4,12 @@ Application.Directives.directive('projects', [ 'Project',
|
||||
restrict: 'E',
|
||||
templateUrl: '<%= asset_path "home/projects.html" %>',
|
||||
link ($scope, element, attributes) {
|
||||
// The last projects published/documented on the plateform
|
||||
// The last projects published/documented on the platform
|
||||
$scope.lastProjects = null;
|
||||
|
||||
// The default slide shown in the carousel
|
||||
$scope.activeSlide = 0;
|
||||
|
||||
// constructor
|
||||
const initialize = function () {
|
||||
Project.lastPublished(function (data) {
|
||||
|
@ -98,7 +98,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
homeContentPromise: ['Setting', function (Setting) { return Setting.get({ name: 'home_content' }).$promise; }]
|
||||
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['home_content', 'home_blogpost']" }).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.public.privacy', {
|
||||
|
@ -1,6 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Member', ['$resource', function ($resource) {
|
||||
Application.Services.factory('Member', ['$resource', '$q', function ($resource, $q) {
|
||||
return $resource('/api/members/:id',
|
||||
{ id: '@id' }, {
|
||||
update: {
|
||||
@ -30,6 +30,20 @@ Application.Services.factory('Member', ['$resource', function ($resource) {
|
||||
mapping: {
|
||||
method: 'GET',
|
||||
url: '/api/members/mapping'
|
||||
},
|
||||
completeTour: {
|
||||
method: 'PATCH',
|
||||
url: '/api/members/:id/complete_tour',
|
||||
params: { id: '@id' },
|
||||
interceptor: {
|
||||
response: function (response) {
|
||||
if (Fablab.featureTourDisplay === 'session') {
|
||||
Fablab.sessionTours.push(response.data.tours[0]);
|
||||
return { tours: Fablab.sessionTours };
|
||||
}
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -673,3 +673,7 @@ padding: 10px;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
input[type=date].form-control {
|
||||
line-height: 25px;
|
||||
}
|
||||
|
@ -89,6 +89,11 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
> li.menu-spacer {
|
||||
height: 1px;
|
||||
margin: 6px 80% 6px 5px;
|
||||
background: linear-gradient(45deg, black, transparent);
|
||||
}
|
||||
ul{
|
||||
display: none;
|
||||
}
|
||||
|
24
app/assets/stylesheets/modules/tour.scss
Normal file
24
app/assets/stylesheets/modules/tour.scss
Normal file
@ -0,0 +1,24 @@
|
||||
.ui-tour-backdrop {
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
fill: rgba(0, 0, 0, 0.5);
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
|
||||
.ui-tour-popup.popover {
|
||||
max-width: 414px;
|
||||
}
|
||||
|
||||
.tour-step-navigation.popover-navigation .btn-group {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
padding: 0 14px;
|
||||
|
||||
.button-placekeeper {
|
||||
width: 90px;
|
||||
height: 30px;
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
@ -5,16 +5,16 @@
|
||||
<a href="#" ng-click="backPrevLocation($event)"><i class="fa fa-long-arrow-left "></i></a>
|
||||
</section>
|
||||
</div>
|
||||
<div class="col-xs-10 b-l b-r-md">
|
||||
<div class="col-md-8 b-l b-r-md">
|
||||
<section class="heading-title">
|
||||
<h1 translate>{{ 'app.admin.calendar.calendar_management' }}</h1>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-1">
|
||||
<div class="col-md-3">
|
||||
<section class="heading-actions wrapper">
|
||||
<a role="button" ui-sref="app.admin.calendar.icalendar" class="btn btn-default b-2x rounded pointer m-t-sm">
|
||||
<i class="fa fa-exchange" aria-hidden="true"></i>
|
||||
<a role="button" ui-sref="app.admin.calendar.icalendar" class="btn btn-lg btn-default rounded m-t-sm text-sm import-ics-button">
|
||||
<i class="fa fa-exchange m-r" aria-hidden="true"></i><span translate>{{ 'app.admin.calendar.external_sync' }}</span>
|
||||
</a>
|
||||
</section>
|
||||
</div>
|
||||
@ -23,7 +23,13 @@
|
||||
</section>
|
||||
|
||||
|
||||
<section class="row no-gutter">
|
||||
<section class="row no-gutter admin-calendar"
|
||||
ui-tour="calendar"
|
||||
ui-tour-backdrop="true"
|
||||
ui-tour-template-url="'<%= asset_path "shared/tour-step-template.html" %>'"
|
||||
ui-tour-use-hotkeys="true"
|
||||
ui-tour-scroll-parent-id="content-main"
|
||||
post-render="setupCalendarTour">
|
||||
|
||||
<div class="col-sm-12 col-md-12 col-lg-9">
|
||||
<div ui-calendar="calendarConfig" ng-model="eventSources" calendar="calendar" class="wrapper-lg"></div>
|
||||
@ -40,7 +46,7 @@
|
||||
|
||||
<div class="col-sm-12 col-md-12 col-lg-3">
|
||||
<div class="m text-center">
|
||||
<a class="btn btn-default"
|
||||
<a class="btn btn-default export-xls-button"
|
||||
ng-href="api/availabilities/export_index.xlsx"
|
||||
target="export-frame"
|
||||
ng-click="alertExport('index')"
|
||||
|
@ -37,6 +37,9 @@
|
||||
<input type="checkbox" ng-click="toggleSelection(machine)" ng-model="selectedMachinesBinding[machine.id]"> {{machine.name}} <span class="text-xs">(id {{machine.id}})</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="alert alert-info m-b-none text-xs wrapper-sm">
|
||||
<i class="fa fa-lightbulb-o m-r" aria-hidden="true"></i> <a ui-sref="app.public.machines_list" ng-click="cancel()" translate> {{ 'app.admin.calendar.manage_machines' }}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-show="availability.available_type == 'training'">
|
||||
@ -50,6 +53,9 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="alert alert-info m-b-none text-xs wrapper-sm m-t">
|
||||
<i class="fa fa-lightbulb-o m-r" aria-hidden="true"></i> <a ui-sref="app.public.trainings_list" ng-click="cancel()" translate> {{ 'app.admin.calendar.manage_trainings' }}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-show="availability.available_type == 'space'">
|
||||
@ -63,6 +69,9 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="alert alert-info m-b-none text-xs wrapper-sm m-t">
|
||||
<i class="fa fa-lightbulb-o m-r" aria-hidden="true"></i> <a ui-sref="app.public.spaces_list" ng-click="cancel()" translate> {{ 'app.admin.calendar.manage_spaces' }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-body" ng-show="step === 3">
|
||||
@ -159,6 +168,7 @@
|
||||
<ul>
|
||||
<li ng-repeat="slot in occurrences">{{slot.start_at | amDateFormat:'L LT'}} - {{slot.end_at | amDateFormat:'LT'}}</li>
|
||||
</ul>
|
||||
<div class="alert alert-warning" translate translate-values="{DURATION: slotDuration}"> {{ 'app.admin.calendar.divided_in_slots' }} </div>
|
||||
<div>
|
||||
<span class="underline" translate>{{ 'app.admin.calendar.reservable' }}</span>
|
||||
<span ng-bind-html="reservableName"></span>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<div class="m-t">
|
||||
<h3 translate>{{ 'app.admin.events.categories' }}</h3>
|
||||
<h3 class="events-categories" translate>{{ 'app.admin.events.categories' }}</h3>
|
||||
<p translate>{{ 'app.admin.events.at_least_one_category_is_required' }}</p>
|
||||
<button type="button" class="btn btn-warning m-b m-t" ng-click="addElement('category')" translate>{{ 'app.admin.events.add_a_category' }}</button>
|
||||
<table class="table">
|
||||
@ -39,7 +39,7 @@
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h3 translate>{{ 'app.admin.events.themes' }}</h3>
|
||||
<h3 class="events-themes" translate>{{ 'app.admin.events.themes' }}</h3>
|
||||
<button type="button" class="btn btn-warning m-b m-t" ng-click="addElement('theme')" translate>{{ 'app.admin.events.add_a_theme' }}</button>
|
||||
<table class="table">
|
||||
<thead>
|
||||
@ -78,7 +78,7 @@
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h3 translate>{{ 'app.admin.events.age_ranges' }}</h3>
|
||||
<h3 class="events-age-ranges" translate>{{ 'app.admin.events.age_ranges' }}</h3>
|
||||
<button type="button" class="btn btn-warning m-b m-t" ng-click="addElement('age_range')" translate>{{ 'app.admin.events.add_a_range' }}</button>
|
||||
<table class="table">
|
||||
<thead>
|
||||
|
@ -18,19 +18,25 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="m-lg">
|
||||
<section class="m-lg events-management"
|
||||
ui-tour="events"
|
||||
ui-tour-backdrop="true"
|
||||
ui-tour-template-url="'<%= asset_path "shared/tour-step-template.html" %>'"
|
||||
ui-tour-use-hotkeys="true"
|
||||
ui-tour-scroll-parent-id="content-main"
|
||||
post-render="setupEventsTour">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<uib-tabset justified="true">
|
||||
<uib-tab heading="{{ 'app.admin.events.events_monitoring' | translate }}">
|
||||
<uib-tabset justified="true" active="tabs.active">
|
||||
<uib-tab heading="{{ 'app.admin.events.events_monitoring' | translate }}" index="0">
|
||||
<ng-include src="'<%= asset_path "admin/events/monitoring.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'app.admin.events.manage_filters' | translate }}">
|
||||
<uib-tab heading="{{ 'app.admin.events.manage_filters' | translate }}" index="1">
|
||||
<ng-include src="'<%= asset_path "admin/events/filters.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'app.admin.events.manage_prices_categories' | translate }}">
|
||||
<uib-tab heading="{{ 'app.admin.events.manage_prices_categories' | translate }}" index="2" class="prices-tab">
|
||||
<ng-include src="'<%= asset_path "admin/events/prices.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
</uib-tabset>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<div class="col-md-6 m-b m-t">
|
||||
<select ng-model="eventsScope.selected" class="form-control" ng-change="changeScope()">
|
||||
<select ng-model="eventsScope.selected" class="form-control events-list-filter" ng-change="changeScope()">
|
||||
<option value="" translate>{{ 'app.admin.events.all_events' }}</option>
|
||||
<option value="passed" translate>{{ 'app.admin.events.passed_events' }}</option>
|
||||
<option value="future" translate>{{ 'app.admin.events.events_to_come' }}</option>
|
||||
@ -7,7 +7,7 @@
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<table class="table">
|
||||
<table class="table events-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:30%" translate>{{ 'app.admin.events.title' }}</th>
|
||||
|
@ -5,26 +5,32 @@
|
||||
<a href="#" ng-click="backPrevLocation($event)"><i class="fa fa-long-arrow-left "></i></a>
|
||||
</section>
|
||||
</div>
|
||||
<div class="col-xs-10 col-sm-10 col-md-8 b-l">
|
||||
<div class="col-xs-10 col-sm-10 col-md-8 b-l b-r">
|
||||
<section class="heading-title">
|
||||
<h1 translate>{{ 'app.admin.invoices.invoices' }}</h1>
|
||||
</section>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-12 col-md-3 b-t hide-b-md">
|
||||
<div class="col-xs-12 col-sm-12 col-md-3">
|
||||
<section class="heading-actions wrapper">
|
||||
<a class="btn btn-default rounded m-t-sm" ng-click="toggleExportModal()"><i class="fa fa-book"></i></a>
|
||||
<a class="btn btn-default rounded m-t-sm export-accounting-button" ng-click="toggleExportModal()"><i class="fa fa-book"></i></a>
|
||||
<iframe name="export-frame" height="0" width="0" class="none" id="accounting-export-frame"></iframe>
|
||||
<a class="btn btn-lg btn-default rounded m-t-sm text-sm" ng-click="closeAnAccountingPeriod()"><i class="fa fa-calendar-check-o"></i> {{ 'app.admin.invoices.accounting_periods' | translate }}</a>
|
||||
<a class="btn btn-lg btn-default rounded m-t-sm text-sm close-accounting-periods-button" ng-click="closeAnAccountingPeriod()"><i class="fa fa-calendar-check-o"></i> {{ 'app.admin.invoices.accounting_periods' | translate }}</a>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="m-lg">
|
||||
<section class="m-lg invoices-management"
|
||||
ui-tour="invoices"
|
||||
ui-tour-backdrop="true"
|
||||
ui-tour-template-url="'<%= asset_path "shared/tour-step-template.html" %>'"
|
||||
ui-tour-use-hotkeys="true"
|
||||
ui-tour-scroll-parent-id="content-main"
|
||||
post-render="setupInvoicesTour">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<uib-tabset justified="true">
|
||||
<uib-tab heading="{{ 'app.admin.invoices.invoices_list' | translate }}" ng-hide="fablabWithoutInvoices" active="tabs.listing.active">
|
||||
<uib-tabset justified="true" active="tabs.active">
|
||||
<uib-tab heading="{{ 'app.admin.invoices.invoices_list' | translate }}" ng-hide="fablabWithoutInvoices" index="0">
|
||||
<h3 class="m-t-xs"><i class="fa fa-filter"></i> {{ 'app.admin.invoices.filter_invoices' | translate }}</h3>
|
||||
|
||||
<div class="row">
|
||||
@ -60,7 +66,7 @@
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
|
||||
<table class="table" ng-if="invoices.length > 0">
|
||||
<table class="table invoices-list" ng-if="invoices.length > 0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:5%"></th>
|
||||
@ -77,7 +83,7 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="invoice in invoices">
|
||||
<td>
|
||||
<td class="chained-indicator">
|
||||
<i class="fa fa-link chained" ng-show="invoice.chained_footprint"/>
|
||||
<i class="fa fa-chain-broken broken" ng-hide="invoice.chained_footprint"/>
|
||||
</td>
|
||||
@ -90,13 +96,13 @@
|
||||
<span ng-hide="invoice.user_id">{{ invoice.name }}</span>
|
||||
<td>
|
||||
<div class="buttons">
|
||||
<a class="btn btn-default" ng-href="api/invoices/{{invoice.id}}/download" target="_blank" ng-if="!invoice.is_avoir">
|
||||
<a class="btn btn-default download-button" ng-href="api/invoices/{{invoice.id}}/download" target="_blank" ng-if="!invoice.is_avoir">
|
||||
<i class="fa fa-file-pdf-o"></i> {{ 'app.admin.invoices.download_the_invoice' | translate }}
|
||||
</a>
|
||||
<a class="btn btn-default" ng-href="api/invoices/{{invoice.id}}/download" target="_blank" ng-if="invoice.is_avoir">
|
||||
<i class="fa fa-file-pdf-o"></i> {{ 'app.admin.invoices.download_the_credit_note' | translate }}
|
||||
</a>
|
||||
<a class="btn btn-default" ng-click="generateAvoirForInvoice(invoice)" ng-if="(!invoice.has_avoir || invoice.has_avoir == 'partial') && !invoice.is_avoir && !invoice.prevent_refund && !isDateClosed(invoice.created_at)">
|
||||
<a class="btn btn-default refund-button" ng-click="generateAvoirForInvoice(invoice)" ng-if="(!invoice.has_avoir || invoice.has_avoir == 'partial') && !invoice.is_avoir && !invoice.prevent_refund && !isDateClosed(invoice.created_at)">
|
||||
<i class="fa fa-reply"></i> {{ 'app.admin.invoices.credit_note' | translate }}
|
||||
</a>
|
||||
</div>
|
||||
@ -116,102 +122,102 @@
|
||||
|
||||
|
||||
|
||||
<uib-tab heading="{{ 'app.admin.invoices.invoicing_settings' | translate }}" active="tabs.settings.active">
|
||||
<div class="alert alert-warning p-md m-t" role="alert" ng-show="fablabWithoutInvoices">
|
||||
<i class="fa fa-warning m-r"></i>
|
||||
<span translate>{{ 'app.admin.invoices.warning_invoices_disabled' }}</span>
|
||||
</div>
|
||||
<form class="invoice-placeholder">
|
||||
<div class="invoice-logo">
|
||||
<img src="data:image/png;base64," data-src="holder.js/100%x100%/text:/font:FontAwesome/icon" bs-holder ng-if="!invoice.logo" class="img-responsive">
|
||||
<img base-sixty-four-image="invoice.logo" ng-if="invoice.logo && invoice.logo.base64">
|
||||
<div class="tools-box">
|
||||
<div class="btn-group">
|
||||
<div class="btn btn-default btn-file">
|
||||
<i class="fa fa-edit"></i> {{ 'app.admin.invoices.change_logo' | translate }}
|
||||
<input type="file" accept="image/png,image/jpeg,image/x-png,image/pjpeg" name="invoice[logo][attachment]" ng-model="invoice.logo" base-sixty-four-input>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="invoice-buyer-infos">
|
||||
<strong translate>{{ 'app.admin.invoices.john_smith' }}</strong>
|
||||
<div translate>{{ 'app.admin.invoices.john_smith_at_example_com' }}</div>
|
||||
<uib-tab heading="{{ 'app.admin.invoices.invoicing_settings' | translate }}" index="1" class="invoices-settings">
|
||||
<div class="alert alert-warning p-md m-t" role="alert" ng-show="fablabWithoutInvoices">
|
||||
<i class="fa fa-warning m-r"></i>
|
||||
<span translate>{{ 'app.admin.invoices.warning_invoices_disabled' }}</span>
|
||||
</div>
|
||||
<div class="invoice-reference invoice-editable" ng-click="openEditReference()">{{ 'app.admin.invoices.invoice_reference_' | translate }} {{mkReference()}}</div>
|
||||
<div class="invoice-code invoice-editable" ng-show="invoice.code.active" ng-click="openEditCode()">{{ 'app.admin.invoices.code_' | translate }} {{invoice.code.model}}</div>
|
||||
<div class="invoice-code invoice-activable" ng-show="!invoice.code.active" ng-click="openEditCode()" translate>{{ 'app.admin.invoices.code_disabled' }}</div>
|
||||
<div class="invoice-order invoice-editable" ng-click="openEditInvoiceNb()"> {{ 'app.admin.invoices.order_num' | translate }} {{mkNumber()}}</div>
|
||||
<div class="invoice-date">{{ 'app.admin.invoices.invoice_issued_on_DATE_at_TIME' | translate:{DATE:(today | amDateFormat:'L'), TIME:(today | amDateFormat:'LT')} }}</div>
|
||||
<div class="invoice-object">
|
||||
{{ 'app.admin.invoices.object_reservation_of_john_smith_on_DATE_at_TIME' | translate:{DATE:(inOneWeek | amDateFormat:'L'), TIME:(inOneWeek | amDateFormat:'LT')} }}
|
||||
</div>
|
||||
<div class="invoice-data">
|
||||
{{ 'app.admin.invoices.order_summary' | translate }}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th translate>{{ 'app.admin.invoices.details' }}</th>
|
||||
<th class="right" translate>{{ 'app.admin.invoices.amount' }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{ 'app.admin.invoices.machine_booking-3D_printer' | translate }} {{inOneWeek | amDateFormat:'LLL'}} - {{inOneWeekAndOneHour | amDateFormat:'LT'}}</td>
|
||||
<td class="right">{{30.0 | currency}}</td>
|
||||
</tr>
|
||||
<form class="invoice-placeholder">
|
||||
<div class="invoice-logo">
|
||||
<img src="data:image/png;base64," data-src="holder.js/100%x100%/text:/font:FontAwesome/icon" bs-holder ng-if="!invoice.logo" class="img-responsive">
|
||||
<img base-sixty-four-image="invoice.logo" ng-if="invoice.logo && invoice.logo.base64">
|
||||
<div class="tools-box">
|
||||
<div class="btn-group">
|
||||
<div class="btn btn-default btn-file">
|
||||
<i class="fa fa-edit"></i> {{ 'app.admin.invoices.change_logo' | translate }}
|
||||
<input type="file" accept="image/png,image/jpeg,image/x-png,image/pjpeg" name="invoice[logo][attachment]" ng-model="invoice.logo" base-sixty-four-input>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="invoice-buyer-infos">
|
||||
<strong translate>{{ 'app.admin.invoices.john_smith' }}</strong>
|
||||
<div translate>{{ 'app.admin.invoices.john_smith_at_example_com' }}</div>
|
||||
</div>
|
||||
<div class="invoice-reference invoice-editable" ng-click="openEditReference()">{{ 'app.admin.invoices.invoice_reference_' | translate }} {{mkReference()}}</div>
|
||||
<div class="invoice-code invoice-editable" ng-show="invoice.code.active" ng-click="openEditCode()">{{ 'app.admin.invoices.code_' | translate }} {{invoice.code.model}}</div>
|
||||
<div class="invoice-code invoice-activable" ng-show="!invoice.code.active" ng-click="openEditCode()" translate>{{ 'app.admin.invoices.code_disabled' }}</div>
|
||||
<div class="invoice-order invoice-editable" ng-click="openEditInvoiceNb()"> {{ 'app.admin.invoices.order_num' | translate }} {{mkNumber()}}</div>
|
||||
<div class="invoice-date">{{ 'app.admin.invoices.invoice_issued_on_DATE_at_TIME' | translate:{DATE:(today | amDateFormat:'L'), TIME:(today | amDateFormat:'LT')} }}</div>
|
||||
<div class="invoice-object">
|
||||
{{ 'app.admin.invoices.object_reservation_of_john_smith_on_DATE_at_TIME' | translate:{DATE:(inOneWeek | amDateFormat:'L'), TIME:(inOneWeek | amDateFormat:'LT')} }}
|
||||
</div>
|
||||
<div class="invoice-data">
|
||||
{{ 'app.admin.invoices.order_summary' | translate }}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th translate>{{ 'app.admin.invoices.details' }}</th>
|
||||
<th class="right" translate>{{ 'app.admin.invoices.amount' }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{ 'app.admin.invoices.machine_booking-3D_printer' | translate }} {{inOneWeek | amDateFormat:'LLL'}} - {{inOneWeekAndOneHour | amDateFormat:'LT'}}</td>
|
||||
<td class="right">{{30.0 | currency}}</td>
|
||||
</tr>
|
||||
|
||||
<tr class="invoice-total" ng-class="{'bold vat-line':invoice.VAT.active}">
|
||||
<td ng-show="!invoice.VAT.active" translate>{{ 'app.admin.invoices.total_amount' }}</td>
|
||||
<td ng-show="invoice.VAT.active" translate>{{ 'app.admin.invoices.total_including_all_taxes' }}</td>
|
||||
<td class="right">{{30.0 | currency}}</td>
|
||||
</tr>
|
||||
<tr class="invoice-total" ng-class="{'bold vat-line':invoice.VAT.active}">
|
||||
<td ng-show="!invoice.VAT.active" translate>{{ 'app.admin.invoices.total_amount' }}</td>
|
||||
<td ng-show="invoice.VAT.active" translate>{{ 'app.admin.invoices.total_including_all_taxes' }}</td>
|
||||
<td class="right">{{30.0 | currency}}</td>
|
||||
</tr>
|
||||
|
||||
<tr class="invoice-vat invoice-activable" ng-click="openEditVAT()" ng-show="!invoice.VAT.active">
|
||||
<td translate>{{ 'app.admin.invoices.VAT_disabled' }}</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr class="invoice-vat invoice-activable" ng-click="openEditVAT()" ng-show="!invoice.VAT.active">
|
||||
<td translate>{{ 'app.admin.invoices.VAT_disabled' }}</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr class="invoice-vat invoice-editable vat-line italic" ng-click="openEditVAT()" ng-show="invoice.VAT.active">
|
||||
<td>{{ 'app.admin.invoices.including_VAT' | translate }} {{invoice.VAT.rate}} %</td>
|
||||
<td>{{30-(30/(invoice.VAT.rate/100+1)) | currency}}</td>
|
||||
</tr>
|
||||
<tr class="invoice-ht vat-line italic" ng-show="invoice.VAT.active">
|
||||
<td translate>{{ 'app.admin.invoices.including_total_excluding_taxes' }}</td>
|
||||
<td>{{30/(invoice.VAT.rate/100+1) | currency}}</td>
|
||||
</tr>
|
||||
<tr class="invoice-payed vat-line bold" ng-show="invoice.VAT.active">
|
||||
<td translate>{{ 'app.admin.invoices.including_amount_payed_on_ordering' }}</td>
|
||||
<td>{{30.0 | currency}}</td>
|
||||
</tr>
|
||||
<tr class="invoice-vat invoice-editable vat-line italic" ng-click="openEditVAT()" ng-show="invoice.VAT.active">
|
||||
<td>{{ 'app.admin.invoices.including_VAT' | translate }} {{invoice.VAT.rate}} %</td>
|
||||
<td>{{30-(30/(invoice.VAT.rate/100+1)) | currency}}</td>
|
||||
</tr>
|
||||
<tr class="invoice-ht vat-line italic" ng-show="invoice.VAT.active">
|
||||
<td translate>{{ 'app.admin.invoices.including_total_excluding_taxes' }}</td>
|
||||
<td>{{30/(invoice.VAT.rate/100+1) | currency}}</td>
|
||||
</tr>
|
||||
<tr class="invoice-payed vat-line bold" ng-show="invoice.VAT.active">
|
||||
<td translate>{{ 'app.admin.invoices.including_amount_payed_on_ordering' }}</td>
|
||||
<td>{{30.0 | currency}}</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
<p class="invoice-payment" translate translate-values="{DATE:(today | amDateFormat:'L'), TIME:(today | amDateFormat:'LT'), AMOUNT:(30.0 | currency)}">
|
||||
{{ 'app.admin.invoices.settlement_by_debit_card_on_DATE_at_TIME_for_an_amount_of_AMOUNT' }}
|
||||
</p>
|
||||
</div>
|
||||
<div medium-editor class="invoice-text invoice-editable" ng-model="invoice.text.content"
|
||||
options='{
|
||||
"placeholder": "{{ "app.admin.invoices.important_notes" | translate }}",
|
||||
"buttons": ["underline"]
|
||||
}'
|
||||
ng-blur="textEditEnd($event)">
|
||||
</div>
|
||||
<div medium-editor class="invoice-legals invoice-editable" ng-model="invoice.legals.content"
|
||||
options='{
|
||||
"placeholder": "{{ "app.admin.invoices.address_and_legal_information" | translate }}",
|
||||
"buttons": ["bold", "underline"]
|
||||
}'
|
||||
ng-blur="legalsEditEnd($event)">
|
||||
</div>
|
||||
</form>
|
||||
</tbody>
|
||||
</table>
|
||||
<p class="invoice-payment" translate translate-values="{DATE:(today | amDateFormat:'L'), TIME:(today | amDateFormat:'LT'), AMOUNT:(30.0 | currency)}">
|
||||
{{ 'app.admin.invoices.settlement_by_debit_card_on_DATE_at_TIME_for_an_amount_of_AMOUNT' }}
|
||||
</p>
|
||||
</div>
|
||||
<div medium-editor class="invoice-text invoice-editable" ng-model="invoice.text.content"
|
||||
options='{
|
||||
"placeholder": "{{ "app.admin.invoices.important_notes" | translate }}",
|
||||
"buttons": ["underline"]
|
||||
}'
|
||||
ng-blur="textEditEnd($event)">
|
||||
</div>
|
||||
<div medium-editor class="invoice-legals invoice-editable" ng-model="invoice.legals.content"
|
||||
options='{
|
||||
"placeholder": "{{ "app.admin.invoices.address_and_legal_information" | translate }}",
|
||||
"buttons": ["bold", "underline"]
|
||||
}'
|
||||
ng-blur="legalsEditEnd($event)">
|
||||
</div>
|
||||
</form>
|
||||
</uib-tab>
|
||||
|
||||
|
||||
|
||||
|
||||
<uib-tab heading="{{ 'app.admin.invoices.accounting_codes' | translate }}">
|
||||
<uib-tab heading="{{ 'app.admin.invoices.accounting_codes' | translate }}" index="2" class="accounting-codes-tab">
|
||||
<div class="panel panel-default m-t-md accounting-codes">
|
||||
<div class="panel-body">
|
||||
<div class="row">
|
||||
|
@ -12,7 +12,7 @@
|
||||
</div>
|
||||
<div class="col-xs-1 col-xs-offset-1 col-md-offset-2 b-l">
|
||||
<section class="heading-actions wrapper">
|
||||
<a role="button" class="btn btn-default b-2x rounded m-t-sm" ui-sref="app.admin.members_import">
|
||||
<a role="button" class="btn btn-default b-2x rounded m-t-sm import-members" ui-sref="app.admin.members_import">
|
||||
<i class="fa fa-cloud-upload"></i>
|
||||
</a>
|
||||
</section>
|
||||
@ -21,28 +21,34 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="m-lg">
|
||||
<section class="m-lg members-management"
|
||||
ui-tour="members"
|
||||
ui-tour-backdrop="true"
|
||||
ui-tour-template-url="'<%= asset_path "shared/tour-step-template.html" %>'"
|
||||
ui-tour-use-hotkeys="true"
|
||||
ui-tour-scroll-parent-id="content-main"
|
||||
post-render="setupMembersTour">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<uib-tabset justified="true">
|
||||
<uib-tabset justified="true" active="tabs.active">
|
||||
|
||||
<uib-tab heading="{{ 'app.admin.members.members' | translate }}">
|
||||
<uib-tab heading="{{ 'app.admin.members.members' | translate }}" index="0">
|
||||
<ng-include src="'<%= asset_path "admin/members/members.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'app.admin.members.administrators' | translate }}">
|
||||
<uib-tab heading="{{ 'app.admin.members.administrators' | translate }}" class="admins-tab" index="1">
|
||||
<ng-include src="'<%= asset_path "admin/members/administrators.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'app.admin.members.groups' | translate }}">
|
||||
<uib-tab heading="{{ 'app.admin.members.groups' | translate }}" class="groups-tab" index="2">
|
||||
<div ui-view="groups"></div>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'app.admin.members.tags' | translate }}">
|
||||
<uib-tab heading="{{ 'app.admin.members.tags' | translate }}" class="labels-tab" index="3">
|
||||
<div ui-view="tags"></div>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'app.admin.members.authentication' | translate }}">
|
||||
<uib-tab heading="{{ 'app.admin.members.authentication' | translate }}" class="sso-tab" index="4">
|
||||
<div ui-view="authentification"></div>
|
||||
</uib-tab>
|
||||
</uib-tabset>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<div class="col-md-5 m-t-lg">
|
||||
<div class="row">
|
||||
<div class="col-lg-7">
|
||||
<div class="form-group">
|
||||
<div class="form-group search-members">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="fa fa-filter"></i></span>
|
||||
<input type="text" ng-model="member.searchText" class="form-control" placeholder="{{ 'app.admin.members.search_for_an_user' | translate }}" ng-change="updateTextSearch()">
|
||||
@ -9,7 +9,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-5">
|
||||
<div class="form-group">
|
||||
<div class="form-group filter-members">
|
||||
<select ng-model="member.memberFilter" ng-change="updateMemberFilter()" class="form-control">
|
||||
<option ng-repeat="filter in member.memberFilters" value="{{filter}}" translate>{{ 'app.admin.members.group_form.member_filter_'+filter }}</option>
|
||||
</select>
|
||||
@ -19,7 +19,7 @@
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<button type="button" class="btn btn-warning m-t m-b" ui-sref="app.admin.members_new" translate>{{ 'app.admin.members.add_a_new_member' }}</button>
|
||||
<div class="pull-right">
|
||||
<div class="pull-right exports-buttons">
|
||||
<a class="btn btn-default" ng-href="api/members/export_members.xlsx" target="export-frame" ng-click="alertExport('members')">
|
||||
<i class="fa fa-file-excel-o"></i> {{ 'app.admin.members.members' | translate }}
|
||||
</a>
|
||||
@ -32,7 +32,7 @@
|
||||
<iframe name="export-frame" height="0" width="0" class="none"></iframe>
|
||||
</div>
|
||||
|
||||
<table class="table">
|
||||
<table class="table members-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:15%"><a href="" ng-click="setOrderMember('last_name')">{{ 'app.admin.members.surname' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': member.order=='last_name', 'fa fa-sort-alpha-desc': member.order=='-last_name', 'fa fa-arrows-v': member.order }"></i></a></th>
|
||||
@ -41,7 +41,7 @@
|
||||
<th style="width:10%" class="hidden-xs hidden-sm hidden-md"><a href="" ng-click="setOrderMember('phone')">{{ 'app.admin.members.phone' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-numeric-asc': member.order=='phone', 'fa fa-sort-numeric-desc': member.order=='-phone', 'fa fa-arrows-v': member.order }"></i></a></th>
|
||||
<th style="width:20%" class="hidden-xs hidden-sm"><a href="" ng-click="setOrderMember('group')">{{ 'app.admin.members.user_type' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': member.order=='group', 'fa fa-sort-alpha-desc': member.order=='-group', 'fa fa-arrows-v': member.order }"></i></a></th>
|
||||
<th style="width:15%" class="hidden-xs hidden-sm hidden-md"><a href="" ng-click="setOrderMember('plan')">{{ 'app.admin.members.subscription' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': member.order=='plan', 'fa fa-sort-alpha-desc': member.order=='-plan', 'fa fa-arrows-v': member.order }"></i></a></th>
|
||||
<th style="width:10%"></th>
|
||||
<th style="width:10%" class="buttons-col"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -54,19 +54,19 @@
|
||||
<td class="hidden-xs hidden-sm hidden-md">{{ m.subscribed_plan | humanReadablePlanName }}</td>
|
||||
<td>
|
||||
<div class="buttons">
|
||||
<button class="btn btn-default" ui-sref="app.admin.members_edit({id: m.id})">
|
||||
<button class="btn btn-default edit-member" ui-sref="app.admin.members_edit({id: m.id})">
|
||||
<i class="fa fa-edit"></i>
|
||||
</button>
|
||||
<button class="btn btn-danger" ng-click="deleteMember(m.id)">
|
||||
<button class="btn btn-danger delete-member" ng-click="deleteMember(m.id)">
|
||||
<i class="fa fa-trash"></i>
|
||||
</button>
|
||||
<span class="label label-danger text-white" ng-show="m.need_completion" translate>{{ 'app.admin.members.incomplete_profile' }}</span>
|
||||
<span class="label label-danger text-white" ng-show="m.need_completion" translate>{{ 'app.shared.user_admin.incomplete_profile' }}</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="text-center">
|
||||
<button class="btn btn-warning" ng-click="showNextMembers()" ng-hide="member.noMore"><i class="fa fa-search-plus" aria-hidden="true"></i> {{ 'app.admin.members.display_more_users' | translate }}</button>
|
||||
<button class="btn btn-warning show-more" ng-click="showNextMembers()" ng-hide="member.noMore"><i class="fa fa-search-plus" aria-hidden="true"></i> {{ 'app.admin.members.display_more_users' | translate }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
<div class="col-xs-12 col-sm-12 col-md-4 b-t hide-b-md">
|
||||
<section class="heading-actions wrapper">
|
||||
<a href="<%= apipie_apipie_path({version: 'v1'}) %>" target="_blank" class="btn btn-info b-2x rounded m-t-sm">
|
||||
<a href="<%= apipie_apipie_path({version: 'v1'}) %>" target="_blank" class="btn btn-info b-2x rounded m-t-sm documentation-button">
|
||||
<i class="fa fa-book" aria-hidden="true"></i>
|
||||
<span translate>{{ 'app.admin.open_api_clients.api_documentation' }}</span>
|
||||
<span class="exponent"><i class="fa fa-external-link" aria-hidden="true"></i></span>
|
||||
@ -23,7 +23,13 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="m-lg">
|
||||
<section class="m-lg open-api-clients"
|
||||
ui-tour="open-api"
|
||||
ui-tour-backdrop="true"
|
||||
ui-tour-template-url="'<%= asset_path "shared/tour-step-template.html" %>'"
|
||||
ui-tour-use-hotkeys="true"
|
||||
ui-tour-scroll-parent-id="content-main"
|
||||
post-render="setupOpenAPITour">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="col-md-12">
|
||||
|
@ -15,33 +15,39 @@
|
||||
</section>
|
||||
|
||||
|
||||
<section class="m-lg">
|
||||
<section class="m-lg plans-pricing"
|
||||
ui-tour="pricing"
|
||||
ui-tour-backdrop="true"
|
||||
ui-tour-template-url="'<%= asset_path "shared/tour-step-template.html" %>'"
|
||||
ui-tour-use-hotkeys="true"
|
||||
ui-tour-scroll-parent-id="content-main"
|
||||
post-render="setupPricingTour">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-12">
|
||||
<uib-tabset justified="true">
|
||||
<uib-tabset justified="true" active="tabs.active">
|
||||
|
||||
<uib-tab heading="{{ 'app.admin.pricing.subscriptions' | translate }}">
|
||||
<uib-tab heading="{{ 'app.admin.pricing.subscriptions' | translate }}" index="0">
|
||||
<ng-include src="'<%= asset_path "admin/pricing/subscriptions.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'app.admin.pricing.trainings' | translate }}">
|
||||
<uib-tab heading="{{ 'app.admin.pricing.trainings' | translate }}" index="1" class="trainings-tab">
|
||||
<ng-include src="'<%= asset_path "admin/pricing/trainings.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'app.admin.pricing.machine_hours' | translate }}">
|
||||
<uib-tab heading="{{ 'app.admin.pricing.machine_hours' | translate }}" index="2" class="machines-tab">
|
||||
<ng-include src="'<%= asset_path "admin/pricing/machine_hours.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'app.admin.pricing.spaces' | translate }}" ng-hide="fablabWithoutSpaces">
|
||||
<uib-tab heading="{{ 'app.admin.pricing.spaces' | translate }}" ng-hide="fablabWithoutSpaces" index="3" class="spaces-tab">
|
||||
<ng-include src="'<%= asset_path "admin/pricing/spaces.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'app.admin.pricing.credits' | translate }}">
|
||||
<uib-tab heading="{{ 'app.admin.pricing.credits' | translate }}" index="4" class="credits-tab">
|
||||
<ng-include src="'<%= asset_path "admin/pricing/credits.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'app.admin.pricing.coupons' | translate }}">
|
||||
<uib-tab heading="{{ 'app.admin.pricing.coupons' | translate }}" index="5" class="coupons-tab">
|
||||
<ng-include src="'<%= asset_path "admin/pricing/coupons.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
</uib-tabset>
|
||||
|
@ -7,7 +7,7 @@
|
||||
</div>
|
||||
|
||||
<div class="m-t-lg">
|
||||
<button type="button" class="btn btn-warning" ui-sref="app.admin.plans.new">
|
||||
<button type="button" class="btn btn-warning new-plan-button" ui-sref="app.admin.plans.new">
|
||||
<i class="fa fa-plus m-r"></i>
|
||||
<span translate>{{ 'app.admin.pricing.add_a_new_subscription_plan' }}</span>
|
||||
</button>
|
||||
|
@ -12,14 +12,20 @@
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-12 col-md-3 b-t hide-b-md">
|
||||
<section class="heading-actions wrapper">
|
||||
<a class="btn btn-ng btn-warning b-2x rounded m-t-sm upper text-sm" ui-sref="app.admin.manage_abuses" role="button" translate>{{ 'app.admin.project_elements.manage_abuses' }}</a>
|
||||
<a class="btn btn-ng btn-warning b-2x rounded m-t-sm upper text-sm abuses-button" ui-sref="app.admin.manage_abuses" role="button" translate>{{ 'app.admin.project_elements.manage_abuses' }}</a>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
<section class="m-lg">
|
||||
<section class="m-lg project-elements"
|
||||
ui-tour="project-elements"
|
||||
ui-tour-backdrop="true"
|
||||
ui-tour-template-url="'<%= asset_path "shared/tour-step-template.html" %>'"
|
||||
ui-tour-use-hotkeys="true"
|
||||
ui-tour-scroll-parent-id="content-main"
|
||||
post-render="setupProjectElementsTour">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-12">
|
||||
|
@ -3,7 +3,7 @@
|
||||
<div class="row">
|
||||
<div class="col-md-12 home-page-content">
|
||||
<h4 translate>{{ 'app.admin.settings.customize_home_page' }}</h4>
|
||||
<button class="btn btn-default pull-right m-t-n-xl" ng-click="resetHomePage()" title="{{ 'app.admin.settings.reset_home_page' | translate }}"><i class="fa fa-undo"></i></button>
|
||||
<button class="btn btn-default pull-right m-t-n-xl reset-button" ng-click="resetHomePage()" title="{{ 'app.admin.settings.reset_home_page' | translate }}"><i class="fa fa-undo"></i></button>
|
||||
<summernote ng-model="homeContent.value"
|
||||
id="home_content"
|
||||
config="summernoteOptsHomePage">
|
||||
|
@ -14,29 +14,35 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="m-lg admin-settings">
|
||||
<section class="m-lg admin-settings"
|
||||
ui-tour="settings"
|
||||
ui-tour-backdrop="true"
|
||||
ui-tour-template-url="'<%= asset_path "shared/tour-step-template.html" %>'"
|
||||
ui-tour-use-hotkeys="true"
|
||||
ui-tour-scroll-parent-id="content-main"
|
||||
post-render="setupSettingsTour">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-12">
|
||||
<uib-tabset justified="true">
|
||||
<uib-tabset justified="true" active="tabs.active">
|
||||
|
||||
<uib-tab heading="{{ 'app.admin.settings.general' | translate }}">
|
||||
<uib-tab heading="{{ 'app.admin.settings.general' | translate }}" index="0">
|
||||
<ng-include src="'<%= asset_path "admin/settings/general.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'app.admin.settings.home_page' | translate }}">
|
||||
<uib-tab heading="{{ 'app.admin.settings.home_page' | translate }}" index="1">
|
||||
<ng-include src="'<%= asset_path "admin/settings/home_page.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'app.admin.settings.about' | translate }}">
|
||||
<uib-tab heading="{{ 'app.admin.settings.about' | translate }}" index="2" class="about-page-tab">
|
||||
<ng-include src="'<%= asset_path "admin/settings/about.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'app.admin.settings.privacy.title' | translate }}">
|
||||
<uib-tab heading="{{ 'app.admin.settings.privacy.title' | translate }}" index="3" class="privacy-page-tab">
|
||||
<ng-include src="'<%= asset_path "admin/settings/privacy.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'app.admin.settings.reservations' | translate }}">
|
||||
<uib-tab heading="{{ 'app.admin.settings.reservations' | translate }}" index="4">
|
||||
<ng-include src="'<%= asset_path "admin/settings/reservations.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
</uib-tabset>
|
||||
|
@ -1,9 +1,12 @@
|
||||
<div class="panel panel-default m-t-md">
|
||||
<div class="panel-heading">
|
||||
<span class="font-sbold" translate>{{ 'app.admin.settings.privacy.title' }}</span>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4 col-md-offset-1">
|
||||
<select class="form-control m-b" ng-options="d.id as d.name for d in privacyDraftsHistory" ng-model="privacyPolicy.version" ng-change="handlePolicyRevisionChange()">
|
||||
<select class="form-control m-b history-select" ng-options="d.id as d.name for d in privacyDraftsHistory" ng-model="privacyPolicy.version" ng-change="handlePolicyRevisionChange()">
|
||||
<option value="" translate>{{ 'app.admin.settings.privacy.current_policy' }}</option>
|
||||
</select>
|
||||
<div class="text-justify" ng-model="privacyPolicy.bodyTemp" medium-editor options='{"placeholder": "{{ "app.admin.settings.input_the_main_content" | translate }}",
|
||||
@ -25,9 +28,16 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default m-t-md">
|
||||
<div class="panel-heading">
|
||||
<span class="font-sbold" translate>{{ 'app.admin.settings.privacy.analytics.title' }}</span>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="row">
|
||||
<div class="col-md-10 col-md-offset-1 m-t-lg">
|
||||
<div class="col-md-10 col-md-offset-1">
|
||||
<label for="is_recurrent" translate>{{ 'app.admin.settings.fab_analytics' }}</label>
|
||||
<input bs-switch
|
||||
ng-model="fabAnalytics.value"
|
||||
|
@ -12,16 +12,22 @@
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-12 col-md-3 b-t hide-b-md">
|
||||
<section class="heading-actions wrapper">
|
||||
<a class="btn btn-lg btn-default rounded m-t-sm text-sm" ng-click="exportToExcel()"><i class="fa fa-file-excel-o"></i></a>
|
||||
<a class="btn btn-lg btn-default rounded m-t-sm text-sm export-button" ng-click="exportToExcel()"><i class="fa fa-file-excel-o"></i></a>
|
||||
<iframe name="export-frame" height="0" width="0" class="none" id="stats-export-frame"></iframe>
|
||||
<a class="btn btn-lg btn-warning bg-white b-2x rounded m-t-sm upper text-sm" ui-sref="app.admin.stats_graphs" role="button"><i class="fa fa-line-chart"></i> {{ 'app.admin.statistics.evolution' | translate }}</a>
|
||||
<a class="btn btn-lg btn-warning bg-white b-2x rounded m-t-sm upper text-sm charts-button" ui-sref="app.admin.stats_graphs" role="button"><i class="fa fa-line-chart"></i> {{ 'app.admin.statistics.evolution' | translate }}</a>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
<section class="m-lg">
|
||||
<section class="m-lg statistics"
|
||||
ui-tour="statistics"
|
||||
ui-tour-backdrop="true"
|
||||
ui-tour-template-url="'<%= asset_path "shared/tour-step-template.html" %>'"
|
||||
ui-tour-use-hotkeys="true"
|
||||
ui-tour-scroll-parent-id="content-main"
|
||||
post-render="setupStatisticsTour">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-12">
|
||||
|
@ -5,28 +5,41 @@
|
||||
<a href="#" ng-click="backPrevLocation($event)"><i class="fa fa-long-arrow-left "></i></a>
|
||||
</section>
|
||||
</div>
|
||||
<div class="col-xs-10 col-sm-10 col-md-8 b-l">
|
||||
<div class="col-xs-10 col-sm-10 col-md-8 b-l b-r">
|
||||
<section class="heading-title">
|
||||
<h1 translate>{{ 'app.admin.trainings.trainings_monitoring' }}</h1>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<section class="heading-actions wrapper">
|
||||
<a role="button" ui-sref="app.admin.calendar" class="btn btn-lg btn-default rounded m-t-sm text-sm">
|
||||
<i class="fa fa-calendar-check-o m-r" aria-hidden="true"></i><span translate>{{ 'app.admin.trainings.plan_session' }}</span>
|
||||
</a>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
<section class="m-lg">
|
||||
<section class="m-lg trainings-monitoring"
|
||||
ui-tour="trainings"
|
||||
ui-tour-backdrop="true"
|
||||
ui-tour-template-url="'<%= asset_path "shared/tour-step-template.html" %>'"
|
||||
ui-tour-use-hotkeys="true"
|
||||
ui-tour-scroll-parent-id="content-main"
|
||||
post-render="setupTrainingsTour">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-12">
|
||||
<uib-tabset justified="true">
|
||||
<uib-tab heading="{{ 'app.admin.trainings.trainings' | translate }}">
|
||||
<uib-tabset justified="true" active="tabs.active">
|
||||
<uib-tab heading="{{ 'app.admin.trainings.trainings' | translate }}" index="0" class="manage-trainings">
|
||||
<div class="m-t m-b">
|
||||
<button type="button" class="btn btn-warning" ui-sref="app.admin.trainings_new">
|
||||
<i class="fa fa-plus m-r"></i>
|
||||
<span translate>{{ 'app.admin.trainings.add_a_new_training' }}</span>
|
||||
</button>
|
||||
<div class="form-group pull-right">
|
||||
<div class="form-group pull-right filter-trainings">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="fa fa-filter"></i></span>
|
||||
<select ng-model="trainingFiltering" class="form-control">
|
||||
@ -36,7 +49,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="table">
|
||||
<table class="table trainings-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:20%" translate>{{ 'app.admin.trainings.name' }}</th>
|
||||
@ -65,7 +78,7 @@
|
||||
</table>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'app.admin.trainings.trainings_monitoring' | translate }}">
|
||||
<uib-tab heading="{{ 'app.admin.trainings.trainings_monitoring' | translate }}" class="post-tracking" index="1">
|
||||
<div class="m-lg">
|
||||
<label for="training_select" translate>{{ 'app.admin.trainings.select_a_training' }}</label>
|
||||
<select ng-options="training as training.name for training in trainings" ng-model="monitoring.training" class="form-control" ng-change="selectTrainingToMonitor()" name="training_select">
|
||||
|
@ -1,2 +1,9 @@
|
||||
<div class="home-page" compile="homeContent">
|
||||
<div ui-tour="welcome"
|
||||
ui-tour-backdrop="true"
|
||||
ui-tour-template-url="'<%= asset_path "shared/tour-step-template.html" %>'"
|
||||
ui-tour-use-hotkeys="true"
|
||||
ui-tour-scroll-parent-id="content-main"
|
||||
post-render="setupHomeTour">
|
||||
<div class="home-page" compile="homeContent">
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,8 +1,8 @@
|
||||
<div>
|
||||
<h4 class="text-sm m-t-sm" translate>{{ 'app.public.home.latest_documented_projects' }}</h4>
|
||||
|
||||
<uib-carousel interval="5000" disable-animation="true">
|
||||
<uib-slide class="h480 cover r" ng-repeat="p in lastProjects" active="p.active" style="background-image:url({{p.project_image}});">
|
||||
<uib-carousel interval="5000" disable-animation="true" active="activeSlide">
|
||||
<uib-slide class="h480 cover r" ng-repeat="p in lastProjects track by $index" index="$index" style="background-image:url({{p.project_image}});">
|
||||
<div class="carousel-caption">
|
||||
<h1 class="title"><a ui-sref="app.public.projects_show({id:p.slug})">{{p.name}}</a></h1>
|
||||
</div>
|
||||
|
@ -13,23 +13,36 @@
|
||||
|
||||
<div class="col-xs-12 col-sm-12 col-md-3 b-t hide-b-md" ng-if="isAuthorized('admin')">
|
||||
<section class="heading-actions wrapper">
|
||||
<a class="btn btn-lg btn-warning bg-white b-2x rounded m-t-xs" ui-sref="app.admin.machines_new" role="button" translate>{{ 'app.public.machines_list.add_a_machine' }}</a>
|
||||
<a class="btn btn-lg btn-warning bg-white b-2x rounded m-t-xs" ui-sref="app.admin.machines_new" role="button" translate>{{ 'app.public.machines_list.add_a_machine' }}</a>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
<section class="m-lg">
|
||||
<section class="m-lg machines-list"
|
||||
ui-tour="machines"
|
||||
ui-tour-backdrop="true"
|
||||
ui-tour-template-url="'<%= asset_path "shared/tour-step-template.html" %>'"
|
||||
ui-tour-use-hotkeys="true"
|
||||
ui-tour-scroll-parent-id="content-main"
|
||||
post-render="setupMachinesTour">
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="input-group col-md-3 m-l-lg m-b">
|
||||
<div class="row">
|
||||
<div class="col-md-3 form-group">
|
||||
<div class="input-group m-l-lg m-b">
|
||||
<span class="input-group-addon"><i class="fa fa-filter"></i></span>
|
||||
<select ng-model="machineFiltering" class="form-control">
|
||||
<option ng-repeat="status in filterDisabled" value="{{status}}" translate>{{ 'app.public.machines_list.status_'+status }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 col-md-offset-6 m-t-n row-centered" ng-if="isAuthorized('admin')">
|
||||
<a role="button" ui-sref="app.admin.calendar" class="btn btn-lg btn-default rounded m-t-sm text-sm">
|
||||
<i class="fa fa-calendar-check-o m-r" aria-hidden="true"></i><span translate>{{ 'app.public.machines_list.new_availability' }}</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-xs-12 col-sm-6 col-lg-4 reservable-card" ng-class="{'disabled-reservable' : machine.disabled && machineFiltering === 'all'}" ng-repeat="machine in machines | filterDisabled:machineFiltering">
|
||||
@ -52,7 +65,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="no-padder" ng-class="{'col-sm-6': !machine.disabled}">
|
||||
<div class="btn btn-default btn-block padder-v no-b red" ng-click="showMachine(machine)">
|
||||
<div class="btn btn-default btn-block padder-v no-b red show-button" ng-click="showMachine(machine)">
|
||||
<i class="fa fa-eye m-r-xs"></i>
|
||||
<span class="hidden-sm" translate>{{ 'app.shared.buttons.consult' }}</span>
|
||||
</div>
|
||||
|
@ -77,10 +77,11 @@
|
||||
<i class="fa fa-asterisk" aria-hidden="true"></i>
|
||||
</span>
|
||||
</span>
|
||||
<select ng-model="user.group_id" class="form-control" name="user[group_id]" required>
|
||||
<select ng-model="user.group_id" class="form-control" required>
|
||||
<option value=null translate>{{ 'app.logged.profile_completion.your_user_s_profile' }}</option>
|
||||
<option ng-repeat="group in groups" ng-value="group.id" ng-selected="group.id == user.group_id">{{group.name}}</option>
|
||||
</select>
|
||||
<input type="hidden" name="user[group_id]" ng-value="user.group_id">
|
||||
</div>
|
||||
<span class="help-block" ng-show="userForm['user[group_id]'].$dirty && userForm['user[group_id]'].$error.required" translate>{{ 'app.logged.profile_completion.user_s_profile_is_required' }}</span>
|
||||
</div>
|
||||
|
@ -269,7 +269,7 @@
|
||||
|
||||
<div class="form-group" ng-class="{'has-error': userForm['user[profile_attributes][job]'].$dirty && userForm['user[profile_attributes][job]'].$invalid}">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon help-cursor" title="{{ 'used_for_profile' | translate }}"><i class="fa fa-briefcase"></i> </span>
|
||||
<span class="input-group-addon help-cursor" title="{{ 'app.shared.user.used_for_profile' | translate }}"><i class="fa fa-briefcase"></i> </span>
|
||||
<input type="text"
|
||||
name="user[profile_attributes][job]"
|
||||
ng-model="user.profile.job"
|
||||
|
@ -7,7 +7,7 @@
|
||||
</div>
|
||||
|
||||
<ul class="nav navbar-nav hidden-xs">
|
||||
<li>
|
||||
<li class="about-page-link">
|
||||
<a href class="about-link font-sbold text-sm" ng-click="goabout = !goabout" ui-sref="app.public.about" ng-show="!goabout">
|
||||
<span class="label label-theme rounded text-lg text-white m-r-sm font-ebold">?</span>
|
||||
{{ linkName }}
|
||||
@ -21,10 +21,10 @@
|
||||
|
||||
<!-- Top Nav -->
|
||||
<ul class="nav navbar-nav navbar-right m-n hidden-xs nav-user user">
|
||||
<li class="notification-open" ng-if="isAuthenticated()">
|
||||
<li class="notification-open notification-center-link" ng-if="isAuthenticated()">
|
||||
<a ui-sref="app.logged.notifications"><i class="fa fa-bell fa-2x black"></i> <span class="badge" ng-class="{'bg-red': notifications.unread > 0}">{{notifications.unread}}</span></a>
|
||||
</li>
|
||||
<li class="dropdown user-profile-nav" ng-if="isAuthenticated()" uib-dropdown>
|
||||
<li class="dropdown user-profile-nav user-menu-dropdown" ng-if="isAuthenticated()" uib-dropdown>
|
||||
<a class="dropdown-toggle pointer" uib-dropdown-toggle>
|
||||
<span class="avatar text-center">
|
||||
<fab-user-avatar ng-model="currentUser.profile.user_avatar" avatar-class="thumb-50"></fab-user-avatar>
|
||||
@ -32,7 +32,7 @@
|
||||
<b class="caret"></b>
|
||||
</span>
|
||||
</a>
|
||||
<ul class="uib-dropdown-menu animated fadeInRight">
|
||||
<ul uib-dropdown-menu class="animated fadeInRight">
|
||||
<li><a ui-sref="app.logged.dashboard.profile" translate>{{ 'app.public.common.my_profile' }}</a></li>
|
||||
<li><a ui-sref="app.logged.dashboard.settings" translate>{{ 'app.public.common.my_settings' }}</a></li>
|
||||
<li><a ui-sref="app.logged.dashboard.projects" translate>{{ 'app.public.common.my_projects' }}</a></li>
|
||||
@ -40,7 +40,8 @@
|
||||
<li><a ui-sref="app.logged.dashboard.events" translate>{{ 'app.public.common.my_events' }}</a></li>
|
||||
<li><a ui-sref="app.logged.dashboard.invoices" ng-hide="fablabWithoutInvoices" translate>{{ 'app.public.common.my_invoices' }}</a></li>
|
||||
<li><a ui-sref="app.logged.dashboard.wallet" translate>{{ 'app.public.common.my_wallet' }}</a></li>
|
||||
|
||||
<li class="divider" ng-if="currentUser.role === 'admin'"></li>
|
||||
<li><a class="text-black pointer" ng-click="help($event)" ng-if="currentUser.role === 'admin'"><i class="fa fa-question-circle"></i> <span translate>{{ 'app.public.common.help' }}</span> </a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a class="text-black pointer" ng-click="logout($event)"><i class="fa fa-power-off"></i> {{ 'app.public.common.sign_out' | translate }}</a></li>
|
||||
</ul>
|
||||
|
@ -62,8 +62,8 @@
|
||||
</a>
|
||||
</li>
|
||||
<!-- Common menu entries -->
|
||||
<li class="" ng-repeat="navLink in navLinks" >
|
||||
<a ng-click="toggleNavSize($event)" ui-sref="{{navLink.state}}" ui-sref-active="active" class="auto" data-toggle="class:nav-off-screen" data-target="#nav">
|
||||
<li class="{{navLink.class}}" ng-repeat="navLink in navLinks">
|
||||
<a ng-click="toggleNavSize($event)" ui-sref="{{navLink.state}}" ui-sref-active="active" class="auto" data-toggle="class:nav-off-screen" data-target="#nav" ng-if="navLink.state">
|
||||
<i class="fa fa-{{navLink.linkIcon}} fa-lg"></i>
|
||||
<span>{{navLink.linkText | translate}}</span>
|
||||
</a>
|
||||
@ -72,10 +72,10 @@
|
||||
|
||||
<!-- Admin entries -->
|
||||
<div class="line-s bg-red-dark dk " ng-if="isAuthorized('admin')"></div>
|
||||
<div class="text-xs font-bold text-bordeau hidden-nav-xs padder m-t-lg m-b-sm" ng-if="isAuthorized('admin')" translate>{{ 'app.public.common.admin' }}</div>
|
||||
<div class="text-xs font-bold text-bordeau hidden-nav-xs padder m-t-lg m-b-sm admin-section" ng-if="isAuthorized('admin')" translate>{{ 'app.public.common.admin' }}</div>
|
||||
<ul class="nav" ng-if="isAuthorized('admin')">
|
||||
<li class="" ng-repeat="navLink in adminNavLinks">
|
||||
<a ng-click="toggleNavSize($event)" ga ui-sref="{{navLink.state}}" ui-sref-active="active" class="auto" data-toggle="class:nav-off-screen" data-target="#nav">
|
||||
<li class="{{navLink.class}}" ng-repeat="navLink in adminNavLinks">
|
||||
<a ng-click="toggleNavSize($event)" ga ui-sref="{{navLink.state}}" ui-sref-active="active" class="auto" data-toggle="class:nav-off-screen" data-target="#nav" ng-if="navLink.state">
|
||||
<i class="fa fa-{{navLink.linkIcon}} fa-lg"></i>
|
||||
<span>{{navLink.linkText | translate}}</span>
|
||||
</a>
|
||||
|
12
app/assets/templates/shared/tour-step-template.html
Normal file
12
app/assets/templates/shared/tour-step-template.html
Normal file
@ -0,0 +1,12 @@
|
||||
<div>
|
||||
<div class="popover-content tour-step-content" bind-html-compile="tourStep.trustedContent || tourStep.content"></div>
|
||||
<div class="popover-navigation tour-step-navigation">
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-sm btn-default" ng-if="tourStep.isPrev()" ng-click="tour.prev()" translate>⮜ {{ 'app.shared.tour.previous' }}</button>
|
||||
<div class="button-placekeeper" ng-if="!tourStep.isPrev()"></div>
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="tour.end()" translate>{{ 'app.shared.tour.end' }}</button>
|
||||
<button type="button" class="btn btn-sm btn-default" ng-if="tourStep.isNext()" ng-click="tour.next()" translate>{{ 'app.shared.tour.next' }} ⮞</button>
|
||||
<div class="button-placekeeper" ng-if="!tourStep.isNext()"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -20,14 +20,27 @@
|
||||
</section>
|
||||
|
||||
|
||||
<section class="m-lg">
|
||||
<section class="m-lg spaces-list"
|
||||
ui-tour="spaces"
|
||||
ui-tour-backdrop="true"
|
||||
ui-tour-template-url="'<%= asset_path "shared/tour-step-template.html" %>'"
|
||||
ui-tour-use-hotkeys="true"
|
||||
ui-tour-scroll-parent-id="content-main"
|
||||
post-render="setupSpacesTour">
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="input-group col-md-3 m-l-lg m-b">
|
||||
<span class="input-group-addon"><i class="fa fa-filter"></i></span>
|
||||
<select ng-model="spaceFiltering" class="form-control">
|
||||
<option ng-repeat="status in filterDisabled" value="{{status}}" translate>{{ 'app.public.spaces_list.status_'+status }}</option>
|
||||
</select>
|
||||
<div class="row">
|
||||
<div class="col-md-3 form-group">
|
||||
<div class="input-group m-l-lg m-b">
|
||||
<span class="input-group-addon"><i class="fa fa-filter"></i></span>
|
||||
<select ng-model="spaceFiltering" class="form-control">
|
||||
<option ng-repeat="status in filterDisabled" value="{{status}}" translate>{{ 'app.public.spaces_list.status_'+status }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 col-md-offset-6 m-t-n row-centered" ng-if="isAuthorized('admin')">
|
||||
<a role="button" ui-sref="app.admin.calendar" class="btn btn-lg btn-default rounded m-t-sm text-sm">
|
||||
<i class="fa fa-calendar-check-o m-r" aria-hidden="true"></i><span translate>{{ 'app.public.spaces_list.new_availability' }}</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -53,7 +66,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="no-padder" ng-class="{'col-sm-6': !space.disabled}">
|
||||
<div class="btn btn-default btn-block padder-v no-b red" ng-click="showSpace(space)">
|
||||
<div class="btn btn-default btn-block padder-v no-b red show-button" ng-click="showSpace(space)">
|
||||
<i class="fa fa-eye m-r-xs"></i>
|
||||
<span class="hidden-sm" translate>{{ 'app.shared.buttons.consult' }}</span>
|
||||
</div>
|
||||
|
@ -3,7 +3,7 @@
|
||||
# API Controller for resources of type User with role 'member'
|
||||
class API::MembersController < API::ApiController
|
||||
before_action :authenticate_user!, except: [:last_subscribed]
|
||||
before_action :set_member, only: %i[update destroy merge]
|
||||
before_action :set_member, only: %i[update destroy merge complete_tour]
|
||||
respond_to :json
|
||||
|
||||
def index
|
||||
@ -189,6 +189,19 @@ class API::MembersController < API::ApiController
|
||||
@members = User.includes(:profile)
|
||||
end
|
||||
|
||||
def complete_tour
|
||||
authorize @member
|
||||
|
||||
if Rails.application.secrets.feature_tour_display == 'session'
|
||||
render json: { tours: [params[:tour]] }
|
||||
else
|
||||
tours = "#{@member.profile.tours} #{params[:tour]}"
|
||||
@member.profile.update_attributes(tours: tours.strip)
|
||||
|
||||
render json: { tours: @member.profile.tours.split }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_member
|
||||
|
@ -1,7 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# API Controller for resources of type Stylesheet
|
||||
# Stylesheets are used to customize the appearance of fab-manager
|
||||
# Stylesheets are used to customize the appearance of Fab-manager
|
||||
class API::StylesheetsController < API::ApiController
|
||||
caches_page :show # magic happens here
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
require 'version'
|
||||
|
||||
# API Controller to get the fab-manager version
|
||||
# API Controller to get the Fab-manager version
|
||||
class API::VersionController < API::ApiController
|
||||
before_action :authenticate_user!
|
||||
|
||||
|
@ -8,7 +8,7 @@ class HealthController < ActionController::Base
|
||||
require 'version'
|
||||
|
||||
render json: {
|
||||
name: 'Fab-Manager',
|
||||
name: 'Fab-manager',
|
||||
status: 'running',
|
||||
dependencies: {
|
||||
postgresql: HealthService.database?,
|
||||
@ -20,7 +20,7 @@ class HealthController < ActionController::Base
|
||||
version: Version.up_to_date?
|
||||
},
|
||||
stats: HealthService.stats,
|
||||
tagline: 'Manage the DIY'
|
||||
tagline: 'The platform to manage your fablab or your coworking space.'
|
||||
}
|
||||
end
|
||||
end
|
||||
|
@ -1,6 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Stylesheet is a cached CSS file that allows to easily customize the interface of Fab-Manager with some configurable colors and
|
||||
# Stylesheet is a cached CSS file that allows to easily customize the interface of Fab-manager with some configurable colors and
|
||||
# a picture for the background of the user's profile.
|
||||
# There's only one stylesheet record in the database, which is updated on each colour change.
|
||||
class Stylesheet < ActiveRecord::Base
|
||||
|
@ -31,6 +31,10 @@ class UserPolicy < ApplicationPolicy
|
||||
user.id == record.id
|
||||
end
|
||||
|
||||
def complete_tour?
|
||||
user.id == record.id
|
||||
end
|
||||
|
||||
%w[list create mapping].each do |action|
|
||||
define_method "#{action}?" do
|
||||
user.admin?
|
||||
|
@ -60,7 +60,7 @@ class HealthService
|
||||
return false unless key
|
||||
|
||||
public_key = OpenSSL::PKey::RSA.new(key)
|
||||
Base64.encode64(public_key.public_encrypt(stats))
|
||||
Base64.encode64(public_key.public_encrypt(row_stats.to_json.to_s))
|
||||
end
|
||||
|
||||
# availabilities for the last week
|
||||
|
@ -21,6 +21,7 @@ json.profile do
|
||||
json.website member.profile.website
|
||||
json.job member.profile.job
|
||||
json.extract! member.profile, :facebook, :twitter, :google_plus, :viadeo, :linkedin, :instagram, :youtube, :vimeo, :dailymotion, :github, :echosciences, :pinterest, :lastfm, :flickr
|
||||
json.tours member.profile.tours&.split || []
|
||||
end
|
||||
|
||||
json.invoicing_profile do
|
||||
|
@ -1,5 +1,8 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
default_provider = AuthProvider.find_by(providable_type: DatabaseProvider.name).name
|
||||
json.title notification.notification_type
|
||||
json.description t('.account_imported_from_PROVIDER_UID_has_completed_its_information_html',
|
||||
PROVIDER: notification.attached_object.provider,
|
||||
UID: notification.attached_object.uid)
|
||||
PROVIDER: notification.attached_object.provider || default_provider,
|
||||
UID: notification.attached_object.uid || notification.attached_object.id)
|
||||
json.url notification_url(notification, format: :json)
|
||||
|
@ -30,6 +30,7 @@
|
||||
Fablab.phoneRequired = ('<%= Rails.application.secrets.phone_required %>' === 'true');
|
||||
Fablab.eventsInCalendar = ('<%= Rails.application.secrets.events_in_calendar %>' === 'true');
|
||||
Fablab.slotDuration = parseInt("<%= ApplicationHelper::SLOT_DURATION %>", 10);
|
||||
Fablab.featureTourDisplay = "<%= Rails.application.secrets.feature_tour_display %>";
|
||||
Fablab.disqusShortname = "<%= Rails.application.secrets.disqus_shortname %>";
|
||||
Fablab.defaultHost = "<%= Rails.application.secrets.default_host %>";
|
||||
Fablab.gaId = "<%= Rails.application.secrets.google_analytics_id %>";
|
||||
@ -61,6 +62,9 @@
|
||||
Fablab.recaptchaSiteKey = "<%= RecaptchaService.site_key %>";
|
||||
<% end %>
|
||||
Fablab.userConfirmationNeededToSignIn = ('<%= Rails.application.secrets.user_confirmation_needed_to_sign_in %>' === 'true');
|
||||
|
||||
// feature tour (used when feature_tour_display = session)
|
||||
Fablab.sessionTours = [];
|
||||
</script>
|
||||
|
||||
<%= stylesheet_link_tag 'application', media: 'all' %>
|
||||
@ -89,7 +93,9 @@
|
||||
<![endif]-->
|
||||
</head>
|
||||
|
||||
<body ng-controller="ApplicationController" ng-init="setCurrentUser(<%= current_user ? current_user.to_json : 'null' %>)" ng-cloak>
|
||||
<body ng-controller="ApplicationController"
|
||||
ng-init="setCurrentUser(<%= current_user ? current_user.to_json : 'null' %>)"
|
||||
ng-cloak>
|
||||
<div growl></div>
|
||||
|
||||
<%= flash_messages %>
|
||||
@ -124,7 +130,7 @@
|
||||
<i class="fa fa-refresh pointer" aria-label="Upgrade required" ng-show="!version.up_to_date && !version.security"></i>
|
||||
<i class="fa fa-warning pointer" aria-label="Security upgrade required" ng-show="!version.up_to_date && version.security"></i>
|
||||
</span>
|
||||
<span class="text-sm">Powered by <a href="http://www.fab-manager.com" target="_blank">Fab Manager</a></span>
|
||||
<span class="text-sm">Powered by <a href="http://www.fab-manager.com" target="_blank">Fab-manager</a></span>
|
||||
</div>
|
||||
|
||||
<%= javascript_include_tag 'application' %>
|
||||
|
@ -37,7 +37,7 @@ json.totals do
|
||||
end
|
||||
|
||||
json.software do
|
||||
json.name 'Fab-Manager'
|
||||
json.name 'Fab-manager'
|
||||
json.version software_version
|
||||
json.code_checksum code_checksum
|
||||
end
|
||||
|
@ -26,8 +26,9 @@ USER_CONFIRMATION_NEEDED_TO_SIGN_IN: 'false'
|
||||
|
||||
EVENTS_IN_CALENDAR: 'false'
|
||||
SLOT_DURATION: '60'
|
||||
FEATURE_TOUR_DISPLAY: 'once'
|
||||
|
||||
DEFAULT_MAIL_FROM: Fab Manager Demo <noreply@fab-manager.com>
|
||||
DEFAULT_MAIL_FROM: Fab-manager Demo <noreply@fab-manager.com>
|
||||
|
||||
# Configure carefully!
|
||||
DEFAULT_HOST: 'localhost:5000'
|
||||
|
@ -42,6 +42,9 @@ en:
|
||||
select_some_machines: "Select some machines"
|
||||
select_all: "All"
|
||||
select_none: "None"
|
||||
manage_machines: "Click here to add or remove machines."
|
||||
manage_spaces: "Click here to add or remove spaces."
|
||||
manage_trainings: "Click here to add or remove trainings."
|
||||
number_of_tickets: "Number of tickets: "
|
||||
adjust_the_opening_hours: "Adjust the opening hours"
|
||||
to_time: "to" # eg. from 18:00 to 21:00
|
||||
@ -58,6 +61,7 @@ en:
|
||||
select_nb_period: "Please select a number of periods for the recurrence"
|
||||
select_end_date: "Please select the date of the last occurrence"
|
||||
about_to_create: "You are about to create the following {TYPE, select, machines{machine} training{training} space{space} other{other}} {NUMBER, plural, one{slot} other{slots}}:"
|
||||
divided_in_slots: "This slot will be open for booking in {DURATION}-minutes increments. Contact your system administrator to change this setting."
|
||||
reservable: "Reservable(s):"
|
||||
labels: "Label(s):"
|
||||
none: "None"
|
||||
@ -89,10 +93,11 @@ en:
|
||||
view_reservations: "View reservations"
|
||||
legend: "legend"
|
||||
and: "and"
|
||||
external_sync: "Calendar synchronization"
|
||||
|
||||
icalendar:
|
||||
icalendar_import: "iCalendar import"
|
||||
intro: "Fab-manager allows to automatically import calendar events, at RFC 5545 iCalendar format, from external URL. These URL are synchronized every nights and the events are shown in the public calendar."
|
||||
intro: "Fab-manager allows to automatically import calendar events, at RFC 5545 iCalendar format, from external URL. These URL are synchronized every hours and the events are shown in the public calendar. You can trigger a synchronisation too, by clicking on the corresponding button, in front of each import."
|
||||
new_import: "New ICS import"
|
||||
color: "Colour"
|
||||
text_color: "Text colour"
|
||||
@ -127,6 +132,7 @@ en:
|
||||
trainings:
|
||||
# track and monitor the trainings
|
||||
trainings_monitoring: "Trainings monitoring"
|
||||
plan_session: "Schedule a new session"
|
||||
trainings: "Trainings"
|
||||
add_a_new_training: "Add a new training"
|
||||
name: "Name"
|
||||
@ -797,8 +803,8 @@ en:
|
||||
statistics: "Statistics"
|
||||
evolution: "Evolution"
|
||||
age_filter: "Age filter"
|
||||
from_age: "From" # context: age. eg: from 8 to 40 years old
|
||||
to_age: "to" # context: age. eg: from 8 to 40 years old
|
||||
from_age: "From" # eg. from 8 to 40 years old
|
||||
to_age: "to" # eg. from 8 to 40 years old
|
||||
_years_old: "years old"
|
||||
start: "Start:"
|
||||
end: "End:"
|
||||
@ -1000,10 +1006,11 @@ en:
|
||||
publish_will_notify: "Publish a new version will send a notification to every users."
|
||||
publish: "Publish"
|
||||
users_notified: "Platform users will be notified of the update."
|
||||
about_analytics: "I agree to share anonymous data with the development team to help improve Fab-Manager."
|
||||
about_analytics: "I agree to share anonymous data with the development team to help improve Fab-manager."
|
||||
read_more: "Which data do we collect?"
|
||||
analytics:
|
||||
intro_analytics_html: "You'll find below a detailed view of all the data, Fab-Manager will collect <strong>if permission is granted.</strong>"
|
||||
title: "Application improvement"
|
||||
intro_analytics_html: "You'll find below a detailed view of all the data, Fab-manager will collect <strong>if permission is granted.</strong>"
|
||||
version: "Application version"
|
||||
members: "Number of members"
|
||||
admins: "Number of administrators"
|
||||
@ -1056,3 +1063,192 @@ en:
|
||||
report_will_be_destroyed: "Once the report has been processed, it will be deleted. This can't be undone, continue?"
|
||||
report_removed: "The report has been deleted"
|
||||
failed_to_remove: "An error occurred, unable to delete the report"
|
||||
|
||||
tour:
|
||||
conclusion:
|
||||
title: "Thank you for your attention"
|
||||
content: "<p>If you want to restart this contextual help, press <strong>F1</strong> at any time or click on [? Help] from the user's menu.</p><p>If you need additional help, you can <a href='https://github.com/sleede/fab-manager/raw/master/doc/fr/guide_utilisation_fab_manager_v4.2.pdf' target='_blank'>check the user guide</a> (only in French for now).</p><p>The Fab-manager's team also provides personalized support (help with getting started, help with installation, customization, etc.), <a href='mailto:contact@fab-manager.com'>contact-us</a> for more info.</p>"
|
||||
trainings:
|
||||
welcome:
|
||||
title: "Trainings"
|
||||
content: "Here you can create, modify and delete trainings. It is also the place where you can validate the training courses followed by your members."
|
||||
trainings:
|
||||
title: "Manage trainings"
|
||||
content: "<p>When creating a training, you can define a default number of places. However, the number of actual places may be modified for each session.</p><p>The training sessions are scheduled from the administrator tab [Calendar].</p><p>Another thing: it is possible to associate one or more machines with a training. This makes it a prerequisite for the reservation of these machines.</p>"
|
||||
filter:
|
||||
title: "Filter"
|
||||
content: "By default, only active courses are displayed here. Display the others by choosing another filter here."
|
||||
tracking:
|
||||
title: "Trainings monitoring"
|
||||
content: "Once a training session is finished, you can validate the training for the members present from this screen. This validation is essential to allow them to use the associated machines, if applicable."
|
||||
calendar:
|
||||
welcome:
|
||||
title: "Calendar"
|
||||
content: "From this screen, you can plan the slots during which training, machines and spaces will be bookable by members."
|
||||
agenda:
|
||||
title: "The calendar"
|
||||
content: "Click in the calendar to start creating a new availability range. You can directly select the entire time range desired by maintaining your click."
|
||||
export:
|
||||
title: "Export"
|
||||
content: "Start generating an Excel file, listing all the availability slots created in the calendar."
|
||||
import:
|
||||
title: "Import external calendars"
|
||||
content: "Allows you to import calendars from an external source in iCal format."
|
||||
members:
|
||||
welcome:
|
||||
title: "Users"
|
||||
content: "Here you can create, modify and delete members and administrators. You can also manage groups, labels, import / export with spreadsheet files and connect SSO software."
|
||||
list:
|
||||
title: "Members list"
|
||||
content: "By default, this table lists all the members of your Fab-manager. You can sort the list in a different order by clicking on the header of each column."
|
||||
search:
|
||||
title: "Find a user"
|
||||
content: "This input field allows you to search for any text on all of the columns in the table below."
|
||||
filter:
|
||||
title: "Filter the list"
|
||||
content: "<p>Filter the list below to display only users who have not confirmed their email address or inactive accounts for more than 3 years.</p><p>Please notice that the GDPR requires that you delete any accounts inactive for more than 3 years.</p>"
|
||||
actions:
|
||||
title: "Members actions"
|
||||
content: "<p>The buttons in this column allow you to display and modify all of the member's parameters, or to delete them irreversibly.</p><p>In the event of a deletion, the billing information will be kept for 10 years and statistical data will also be kept anonymously.</p>"
|
||||
exports:
|
||||
title: "Export"
|
||||
content: "Each of these buttons starts the generation of an Excel file listing all the members, subscriptions or reservations, current and past."
|
||||
import:
|
||||
title: "Import members"
|
||||
content: "Allows you to import a list of members to create in Fab-manager, from a CSV file."
|
||||
admins:
|
||||
title: "Manage administrators"
|
||||
content: "In the same way as the members, manage the administrators of your Fab-manager here.<br>The administrators can take reservations for any member as well as modify all the parameters of the software."
|
||||
groups:
|
||||
title: "Manage groups"
|
||||
content: "Groups allow you to better segment your price list."
|
||||
labels:
|
||||
title: "Manage tags"
|
||||
content: "The labels allow you to reserve certain slots for users associated with these same labels."
|
||||
sso:
|
||||
title: "Single Sign-On"
|
||||
content: "Here you can set up and manage a single authentication system (SSO)."
|
||||
invoices:
|
||||
welcome:
|
||||
title: "Invoices"
|
||||
content: "<p>Here you will be able to download invoices and credit notes issued, as well as manage everything related to accounting and invoicing.</p><p>If you use third-party software to manage your invoices, it is possible to deactivate the billing module. For this, contact your system administrator.</p>"
|
||||
list:
|
||||
title: "Invoices list"
|
||||
content: "By default, this table lists all the invoices and credit notes issued by Fab-manager. You can sort the list in a different order by clicking on the header of each column."
|
||||
chained:
|
||||
title: "Chaining indicator"
|
||||
content: "<p>This icon ensures the inalterability of the accounting data of the invoice on this line, in accordance with the French finance law of 2018 against VAT fraud.</p><p>If a red icon appears instead of this one , please contact technical support immediately.</p>"
|
||||
download:
|
||||
title: "Download"
|
||||
content: "Click here to download the invoice in PDF format."
|
||||
refund:
|
||||
title: "Credit note"
|
||||
content: "Allows you to generate a credit note for the invoice on this line or some of its sub-elements. <strong>Warning:</strong> This will only generate the accounting document, the actual refund of the user will always be your responsibility."
|
||||
settings:
|
||||
title: "Settings"
|
||||
content: "<p>Here you can modify the parameters for invoices generation. Click on the item you are interested in to start editing.</p><p>In particular, this is where you can set if you are subject to VAT and the applicable rate.</p>"
|
||||
codes:
|
||||
title: "Accounting codes"
|
||||
content: "Set the accounting codes here for all kinds of entries generated by the software. This setting is only required if you use the accounting export functionality."
|
||||
export:
|
||||
title: "Accounting export"
|
||||
content: "Once the codes have been configured, click here to access the interface allowing you to export the entries to a third-party accounting software."
|
||||
periods:
|
||||
title: "Close accounting periods"
|
||||
content: "<p>The regulations of your country may require you to close your accounts regularly. The interface accessible from this button allows you to do this.</p> <p><strong>In France,</strong> if you are subject to VAT anti-fraud law <a href='https://bofip.impots.gouv.fr/bofip/10691-PGP.html' target='_blank'>BOI-TVA-DECLA-30-10-30-20160803</a>, this closing is mandatory at least once a year.</p><p>As a reminder, if you have to use a certified software (<a href='https://www.impots.gouv.fr/portail/suis-je-oblige-davoir-un-logiciel-de-caisse-securise' target='_blank'>take the test here</a>), you are under the legal obligation to provide a certificate of compliance of the software. <a href='mailto:contact@fab-manager.com'>Contact-us<a/> to get it.</p>"
|
||||
pricing:
|
||||
welcome:
|
||||
title: "Subscriptions & Prices"
|
||||
content: "Manage subscription plans and prices for the various services you offer to your members."
|
||||
new_plan:
|
||||
title: "New subscription plan"
|
||||
content: "Create subscription plans to offer preferential prices on machines and spaces to regular users."
|
||||
trainings:
|
||||
title: "Trainings"
|
||||
content: "Define training prices here, by user group."
|
||||
machines:
|
||||
title: "Machines"
|
||||
content: "Define here the prices of the machine slots, by user group. These prices will be applied to users who do not have subscriptions."
|
||||
spaces:
|
||||
title: "Espaces"
|
||||
content: "In the same way, define here the prices of the spaces slots, for the users without subscriptions."
|
||||
credits:
|
||||
title: "Credits"
|
||||
content: "<p>Credits allow you to give certain services for free to users who subscribe to a plan.</p><p>You can, for example, offer 2 hours of 3D printer for all annual subscriptions; or training of your choice for student subscribers, etc.</p>"
|
||||
coupons:
|
||||
title: "Coupons"
|
||||
content: "Create and manage promotional coupons allowing to offer punctual discounts to their holders."
|
||||
events:
|
||||
welcome:
|
||||
title: "Events"
|
||||
content: "Create events, track their reservations and organize them from this page."
|
||||
list:
|
||||
title: "The events"
|
||||
content: "This list displays all past or future events, as well as the number of reservations for each of them."
|
||||
filter:
|
||||
title: "Filter events"
|
||||
content: "Only display upcoming events in the list below; or on the contrary, only those already passed."
|
||||
categories:
|
||||
title: "Categories"
|
||||
content: "Categories help your users know what type of event it is. A category is required for each of the newly created events."
|
||||
themes:
|
||||
title: "Themes"
|
||||
content: "<p>Themes are an additional (and optional) categorization of your events. They can group together different events of very different forms.</p><p>For example, a two-day course about marquetry and an evening workshop about the handling of the wood planer, can be found in the theme « carpentry ».</p>"
|
||||
ages:
|
||||
title: "Age groups"
|
||||
content: "This other optional filter will help your users find events suited to their profile."
|
||||
prices:
|
||||
title: "Pricing categories"
|
||||
content: "The price of events does not depend on groups or subscriptions, but on the categories you define on this page."
|
||||
project_elements:
|
||||
welcome:
|
||||
title: "Projects"
|
||||
content: "Here you can define all the elements that will be available for members to document the projects they carry out."
|
||||
abuses:
|
||||
title: "Manage reports"
|
||||
content: "<p>Access here the management of reports.</p><p>Visitors can signal projects, for example for copyright infringement or for hate speech.</p><p>GDPR requires you to delete this reporting data once the required actions have been taken.</p>"
|
||||
statistics:
|
||||
welcome:
|
||||
title: "Statistics"
|
||||
content: "<p>From here, you will be able to access many statistics on your members and their uses within your Fab Lab.</p><p>In accordance with GDPR, users who have deleted their account continue to be reported in the statistics, but anonymously.</p>"
|
||||
export:
|
||||
title: "Export data"
|
||||
content: "You can choose to export all or part of the statistical data to an Excel file."
|
||||
trending:
|
||||
title: "Evolution"
|
||||
content: "Visualize the evolution over time of the main uses of your Fab Lab, thanks to graphs and curves."
|
||||
settings:
|
||||
welcome:
|
||||
title: "Application customization"
|
||||
content: "From here, you can configure the general settings of Fab-manager as well as customize various elements of the interface."
|
||||
home:
|
||||
title: "Customize home page"
|
||||
content: "<p>This WYSIWYG editor allows you to customize the appearance of the home page while using different components (last tweet, brief, etc.).</p><p><strong>Warning:</strong> Keep in mind that any uncontrolled changes can break the appearance of the home page.</p>"
|
||||
components:
|
||||
title: "Insert a component"
|
||||
content: "Click here to insert a pre-existing component into the home page."
|
||||
codeview:
|
||||
title: "Display HTML code"
|
||||
content: "This button allows you to directly view and modify the code of the home page. This is the recommended way to proceed, but it requires prior knowledge of HTML."
|
||||
reset:
|
||||
title: "Go back"
|
||||
content: "At any time, you can restore the original home page by clicking here."
|
||||
css:
|
||||
title: "Customize the style sheet"
|
||||
content: "For advanced users, it is possible to define a custom style sheet (CSS) for the home page."
|
||||
about:
|
||||
title: "About"
|
||||
content: "Fully personalize this page to present your activity."
|
||||
privacy:
|
||||
title: "Privacy policy"
|
||||
content: "<p>EExplain here how you use the data you collect about your members.</p><p>GDPR requires that a confidentiality policy is defined, as well as a data protection officer.</p>"
|
||||
draft:
|
||||
title: "Draft"
|
||||
content: "Click here to view a privacy policy draft with holes, which you just need to read and complete."
|
||||
open_api:
|
||||
welcome:
|
||||
title: "OpenAPI"
|
||||
content: "Fab-manager offers an open API allowing third-party software to deal simply with its data. This screen allows you to grant accesses to this API."
|
||||
doc:
|
||||
title: "Documentation"
|
||||
content: "Click here to access the API online documentation."
|
||||
|
@ -6,9 +6,11 @@ es:
|
||||
declare_a_new_machine: "Declara una nueva máquina"
|
||||
watch_out_when_creating_a_new_machine_its_prices_are_initialized_at_0_for_all_subscriptions: "Cuidado al crear una nueva máquina, los precios están inicializados a 0 para todas las subscripciones."
|
||||
consider_changing_them_before_creating_any_reservation_slot: "Considera cambiarlos antes de crear cualquier ranura de reserva."
|
||||
|
||||
machines_edit:
|
||||
#machine edition
|
||||
machine_edit: "Editar una máquina"
|
||||
|
||||
calendar:
|
||||
#manage the trainings & machines slots
|
||||
calendar_management: "Administración de calendario"
|
||||
@ -40,6 +42,9 @@ es:
|
||||
select_some_machines: "Seleccione algunas máquinas"
|
||||
select_all: "Todas"
|
||||
select_none: "No"
|
||||
manage_machines: "Click here to add or remove machines."
|
||||
manage_spaces: "Click here to add or remove spaces."
|
||||
manage_trainings: "Click here to add or remove trainings."
|
||||
number_of_tickets: "Número de tickets: "
|
||||
adjust_the_opening_hours: "Ajustar el horario de apertura"
|
||||
to_time: a
|
||||
@ -56,6 +61,7 @@ es:
|
||||
select_nb_period: "Please select a number of periods for the recurrence"
|
||||
select_end_date: "Please select the date of the last occurrence"
|
||||
about_to_create: "Está a punto de crear los horarios siguientes: {TYPE, select, machines{machine} training{training} space{space} other{other}} {NUMBER, plural, one{slot} other{slots}}:"
|
||||
divided_in_slots: "This slot will be open for booking in {DURATION}-minutes increments. Contact your system administrator to change this setting."
|
||||
reservable: "Reservable(s):"
|
||||
labels: "Etiqueta(s):"
|
||||
none: "Ninguna"
|
||||
@ -87,9 +93,11 @@ es:
|
||||
view_reservations: "Ver reservas"
|
||||
legend: "leyenda"
|
||||
and: "y"
|
||||
external_sync: "Calendar synchronization"
|
||||
|
||||
icalendar:
|
||||
icalendar_import: "iCalendar import"
|
||||
intro: "Fab-manager allows to automatically import calendar events, at RFC 5545 iCalendar format, from external URL. These URL are synchronized every nights and the events are shown in the public calendar."
|
||||
intro: "Fab-manager allows to automatically import calendar events, at RFC 5545 iCalendar format, from external URL. These URL are synchronized every hours and the events are shown in the public calendar. You can trigger a synchronisation too, by clicking on the corresponding button, in front of each import."
|
||||
new_import: "New ICS import"
|
||||
color: "Colour"
|
||||
text_color: "Text colour"
|
||||
@ -107,6 +115,7 @@ es:
|
||||
confirmation_required: "Confirmation required"
|
||||
confirm_delete_import: "Do you really want to delete this iCalendar import?"
|
||||
delete_success: "iCalendar import successfully deleted"
|
||||
|
||||
project_elements:
|
||||
#management of the projects' components
|
||||
name: "Name"
|
||||
@ -119,9 +128,11 @@ es:
|
||||
description: "Description"
|
||||
add_a_new_licence: "Agregar una nueva licencia"
|
||||
manage_abuses: "Administrar informes"
|
||||
|
||||
trainings:
|
||||
#track and monitor the trainings
|
||||
trainings_monitoring: "Trainings monitoring"
|
||||
plan_session: "Schedule a new session"
|
||||
trainings: "Trainings"
|
||||
add_a_new_training: "Add a new training"
|
||||
name: "Nombre"
|
||||
@ -151,11 +162,13 @@ es:
|
||||
status_enabled: "Enabled"
|
||||
status_disabled: "Disabled"
|
||||
status_all: "All"
|
||||
|
||||
trainings_new:
|
||||
#create a new training
|
||||
add_a_new_training: "Add a new training"
|
||||
beware_when_creating_a_training_its_reservation_prices_are_initialized_to_zero: "Tenga cuidado, al crear una formación, sus precios de reserva se inicializan en cero."
|
||||
dont_forget_to_change_them_before_creating_slots_for_this_training: "No olvides cambiarlos antes de crear espacios para esta formación."
|
||||
|
||||
events:
|
||||
#events tracking and management
|
||||
events_monitoring: "Monitoreo de eventos"
|
||||
@ -210,6 +223,7 @@ es:
|
||||
do_you_really_want_to_delete_this_price_category: "¿Desea realmente eliminar esta categoría de precios?"
|
||||
price_category_successfully_deleted: "Categoría de precio eliminada correctamente."
|
||||
price_category_deletion_failed: "Error al eliminar la categoría de precio."
|
||||
|
||||
events_new:
|
||||
#add a new event
|
||||
add_an_event: "Add an event"
|
||||
@ -218,6 +232,7 @@ es:
|
||||
every_week: "Cada semana"
|
||||
every_month: "Cada mes"
|
||||
every_year: "Cada año"
|
||||
|
||||
events_edit:
|
||||
#edit an existing event
|
||||
edit_the_event: "Editar el evento"
|
||||
@ -245,6 +260,7 @@ es:
|
||||
no_reservations_for_now: "No hay reservas por ahora."
|
||||
back_to_monitoring: "Volver a monitorizar"
|
||||
canceled: "cancelada"
|
||||
|
||||
pricing:
|
||||
#subscriptions, prices, credits and coupons management
|
||||
pricing_management: "Gestión de precios"
|
||||
@ -325,14 +341,17 @@ es:
|
||||
status_enabled: "Enabled"
|
||||
status_disabled: "Disabled"
|
||||
status_all: "All"
|
||||
|
||||
coupons_new:
|
||||
#ajouter un code promotionnel
|
||||
add_a_coupon: "Añadir un cupón"
|
||||
unable_to_create_the_coupon_check_code_already_used: "No se puede crear el cupón. Compruebe que el código no esté ya utilizado"
|
||||
|
||||
coupons_edit:
|
||||
#mettre à jour un code promotionnel
|
||||
coupon: "Coupon:"
|
||||
unable_to_update_the_coupon_an_error_occurred: "No se puede actualizar el cupón: se ha producido un error."
|
||||
|
||||
plans:
|
||||
new:
|
||||
#add a subscription plan on the platform
|
||||
@ -352,6 +371,7 @@ es:
|
||||
space: "Espacio"
|
||||
unable_to_save_subscription_changes_please_try_again: "No se pueden guardar los cambios de suscripción. Por favor, inténtelo de nuevo."
|
||||
subscription_successfully_changed: "Suscripción cambiada correctamente."
|
||||
|
||||
invoices:
|
||||
#list of all invoices & invoicing parameters
|
||||
invoices: "Facturas"
|
||||
@ -542,7 +562,7 @@ es:
|
||||
general_space_code: "Accounting code for all spaces"
|
||||
accounting_Space_label: "Spaces label"
|
||||
general_space_label: "Account label for all spaces"
|
||||
codes_customization_success: "Customization of accounting codes successfully saved."
|
||||
codes_customization_success: "Customization of the accounting codes successfully saved."
|
||||
export_accounting_data: "Export accounting data"
|
||||
export_to: "Export to the accounting software"
|
||||
export_is_running: "Exportando, será notificado cuando esté listo."
|
||||
@ -553,7 +573,7 @@ es:
|
||||
encoding: "Encoding"
|
||||
separator: "Separator"
|
||||
dateFormat: "Date format"
|
||||
labelMaxLength: "Label maximum length"
|
||||
labelMaxLength: "Label (max)"
|
||||
decimalSeparator: "Decimal separator"
|
||||
exportInvoicesAtZero: "Export invoices equal to 0"
|
||||
columns: "Columns"
|
||||
@ -569,6 +589,7 @@ es:
|
||||
debit_euro: "Euro debit"
|
||||
credit_euro: "Euro credit"
|
||||
lettering: "Lettering"
|
||||
|
||||
members:
|
||||
#management of users, labels, groups, and so on
|
||||
users_management: "Gestión de usuarios"
|
||||
@ -653,6 +674,7 @@ es:
|
||||
#add a member
|
||||
add_a_member: "Agregar un miembro"
|
||||
user_is_an_organization: "El usuario es una organización"
|
||||
|
||||
members_import:
|
||||
#members bulk import
|
||||
import_members: "Import members"
|
||||
@ -678,6 +700,7 @@ es:
|
||||
update_on_id: "ID"
|
||||
update_on_username: "Username"
|
||||
update_on_email: "Email address"
|
||||
|
||||
members_import_result:
|
||||
#import results
|
||||
import_results: "Import results"
|
||||
@ -689,6 +712,7 @@ es:
|
||||
success: "Success"
|
||||
failed: "Failed"
|
||||
error_details: "Error's details:"
|
||||
|
||||
members_edit:
|
||||
#edit a member
|
||||
subscription: "Subscription"
|
||||
@ -732,6 +756,7 @@ es:
|
||||
a_problem_occurred_while_taking_the_subscription: "Se ha producido un problema al realizar la suscripción."
|
||||
wallet: "Wallet"
|
||||
to_credit: 'Credit'
|
||||
|
||||
admins_new:
|
||||
#add a new administrator to the platform
|
||||
add_an_administrator: "Agregar un administrador"
|
||||
@ -750,8 +775,9 @@ es:
|
||||
birth_date: "Date of birth"
|
||||
address: "Address"
|
||||
phone_number: "Phone number"
|
||||
|
||||
authentication_new:
|
||||
#add a new authentication provider (SSO)
|
||||
# add a new authentication provider (SSO)
|
||||
local_database: "Base de datos local"
|
||||
o_auth2: "OAuth 2.0"
|
||||
add_a_new_authentication_provider: "Agregar un nuevo proveedor de autenticación"
|
||||
@ -764,12 +790,14 @@ es:
|
||||
do_you_really_want_to_continue: "¿De verdad quieres continuar?"
|
||||
unsecured_oauth2_provider_successfully_added: "Proveedor de OAuth 2.0 no seguro, se ha agregado correctamente."
|
||||
oauth2_provider_successfully_added: "OAuth 2.0 proveedor agregado correctamente."
|
||||
|
||||
authentication_edit:
|
||||
#edit an authentication provider (SSO)
|
||||
provider: "Proveedor :"
|
||||
it_is_required_to_set_the_matching_between_User.uid_and_the_API_to_add_this_provider: "Es necesario establecer la coincidencia entre User.uid y la API para agregar este proveedor"
|
||||
provider_successfully_updated: "Proveedor actualizado correctamente"
|
||||
an_error_occurred_unable_to_update_the_provider: "Se ha producido un error: no se puede actualizar el proveedor."
|
||||
|
||||
statistics:
|
||||
#statistics tables
|
||||
statistics: "Statistics"
|
||||
@ -811,6 +839,7 @@ es:
|
||||
man: "Man"
|
||||
woman: "Woman"
|
||||
export_is_running_you_ll_be_notified_when_its_ready: "Export is running. You'll be notified when it's ready."
|
||||
|
||||
stats_graphs:
|
||||
#statistics graphs
|
||||
statistics: "Statistics"
|
||||
@ -830,8 +859,9 @@ es:
|
||||
week_of_START_to_END: "Semana del {START} a {END}"
|
||||
no_data_for_this_period: "No hay datos para este periodo"
|
||||
date: "Date"
|
||||
|
||||
settings:
|
||||
#global application parameters and customization
|
||||
# global application parameters and customization
|
||||
title: "Título"
|
||||
customize_the_application: "Personalizar la aplicación"
|
||||
general: "General"
|
||||
@ -976,10 +1006,11 @@ es:
|
||||
publish_will_notify: "Publish a new version will send a notification to every users."
|
||||
publish: "Publish"
|
||||
users_notified: "Platform users will be notified of the update."
|
||||
about_analytics: "I agree to share anonymous data with the development team to help improve Fab-Manager."
|
||||
about_analytics: "I agree to share anonymous data with the development team to help improve Fab-manager."
|
||||
read_more: "Which data do we collect?"
|
||||
analytics:
|
||||
intro_analytics_html: "You'll find below a detailed view of all the data, Fab-Manager will collect <strong>if permission is granted.</strong>"
|
||||
title: "Application improvement"
|
||||
intro_analytics_html: "You'll find below a detailed view of all the data, Fab-manager will collect <strong>if permission is granted.</strong>"
|
||||
version: "Application version"
|
||||
members: "Number of members"
|
||||
admins: "Number of administrators"
|
||||
@ -1008,18 +1039,21 @@ es:
|
||||
client_successfully_updated: "Cliente actualizado correctamente."
|
||||
client_successfully_deleted: "Cliente borrado correctamente."
|
||||
access_successfully_revoked: "Acceso revocado correctamente."
|
||||
|
||||
space_new:
|
||||
#create a new space
|
||||
# create a new space
|
||||
add_a_new_space: "Añadir un espacio nuevo"
|
||||
watch_out_when_creating_a_new_space_its_prices_are_initialized_at_0_for_all_subscriptions: "¡Cuidado! Al crear un nuevo espacio, sus precios se inicializan en 0 para todas las suscripciones."
|
||||
consider_changing_its_prices_before_creating_any_reservation_slot: "Considere cambiar sus precios antes de crear cualquier espacio de reserva."
|
||||
add_this_space: "Añadir este espacio"
|
||||
|
||||
space_edit:
|
||||
#modify an exiting space
|
||||
# modify an exiting space
|
||||
edit_the_space_NAME: "Edit the space: {NAME}"
|
||||
validate_the_changes: "Validar los cambios"
|
||||
|
||||
manage_abuses:
|
||||
#process and delete abuses reports
|
||||
# process and delete abuses reports
|
||||
abuses_list: "Lista de informes"
|
||||
no_reports: "No informes por ahora"
|
||||
published_by: "published by"
|
||||
@ -1029,3 +1063,192 @@ es:
|
||||
report_will_be_destroyed: "Once the report has been processed, it will be deleted. This can't be undone, continue?"
|
||||
report_removed: "The report has been deleted"
|
||||
failed_to_remove: "An error occurred, unable to delete the report"
|
||||
|
||||
tour:
|
||||
conclusion:
|
||||
title: "Thank you for your attention"
|
||||
content: "<p>If you want to restart this contextual help, press <strong>F1</strong> at any time or click on [? Help] from the user's menu.</p><p>If you need additional help, you can <a href='https://github.com/sleede/fab-manager/raw/master/doc/fr/guide_utilisation_fab_manager_v4.2.pdf' target='_blank'>check the user guide</a> (only in French for now).</p><p>The Fab-manager's team also provides personalized support (help with getting started, help with installation, customization, etc.), <a href='mailto:contact@fab-manager.com'>contact-us</a> for more info.</p>"
|
||||
trainings:
|
||||
welcome:
|
||||
title: "Trainings"
|
||||
content: "Here you can create, modify and delete trainings. It is also the place where you can validate the training courses followed by your members."
|
||||
trainings:
|
||||
title: "Manage trainings"
|
||||
content: "<p>When creating a training, you can define a default number of places. However, the number of actual places may be modified for each session.</p><p>The training sessions are scheduled from the administrator tab [Calendar].</p><p>Another thing: it is possible to associate one or more machines with a training. This makes it a prerequisite for the reservation of these machines.</p>"
|
||||
filter:
|
||||
title: "Filter"
|
||||
content: "By default, only active courses are displayed here. Display the others by choosing another filter here."
|
||||
tracking:
|
||||
title: "Trainings monitoring"
|
||||
content: "Once a training session is finished, you can validate the training for the members present from this screen. This validation is essential to allow them to use the associated machines, if applicable."
|
||||
calendar:
|
||||
welcome:
|
||||
title: "Calendar"
|
||||
content: "From this screen, you can plan the slots during which training, machines and spaces will be bookable by members."
|
||||
agenda:
|
||||
title: "The calendar"
|
||||
content: "Click in the calendar to start creating a new availability range. You can directly select the entire time range desired by maintaining your click."
|
||||
export:
|
||||
title: "Export"
|
||||
content: "Start generating an Excel file, listing all the availability slots created in the calendar."
|
||||
import:
|
||||
title: "Import external calendars"
|
||||
content: "Allows you to import calendars from an external source in iCal format."
|
||||
members:
|
||||
welcome:
|
||||
title: "Users"
|
||||
content: "Here you can create, modify and delete members and administrators. You can also manage groups, labels, import / export with spreadsheet files and connect SSO software."
|
||||
list:
|
||||
title: "Members list"
|
||||
content: "By default, this table lists all the members of your Fab-manager. You can sort the list in a different order by clicking on the header of each column."
|
||||
search:
|
||||
title: "Find a user"
|
||||
content: "This input field allows you to search for any text on all of the columns in the table below."
|
||||
filter:
|
||||
title: "Filter the list"
|
||||
content: "<p>Filter the list below to display only users who have not confirmed their email address or inactive accounts for more than 3 years.</p><p>Please notice that the GDPR requires that you delete any accounts inactive for more than 3 years.</p>"
|
||||
actions:
|
||||
title: "Members actions"
|
||||
content: "<p>The buttons in this column allow you to display and modify all of the member's parameters, or to delete them irreversibly.</p><p>In the event of a deletion, the billing information will be kept for 10 years and statistical data will also be kept anonymously.</p>"
|
||||
exports:
|
||||
title: "Export"
|
||||
content: "Each of these buttons starts the generation of an Excel file listing all the members, subscriptions or reservations, current and past."
|
||||
import:
|
||||
title: "Import members"
|
||||
content: "Allows you to import a list of members to create in Fab-manager, from a CSV file."
|
||||
admins:
|
||||
title: "Manage administrators"
|
||||
content: "In the same way as the members, manage the administrators of your Fab-manager here.<br>The administrators can take reservations for any member as well as modify all the parameters of the software."
|
||||
groups:
|
||||
title: "Manage groups"
|
||||
content: "Groups allow you to better segment your price list."
|
||||
labels:
|
||||
title: "Manage tags"
|
||||
content: "The labels allow you to reserve certain slots for users associated with these same labels."
|
||||
sso:
|
||||
title: "Single Sign-On"
|
||||
content: "Here you can set up and manage a single authentication system (SSO)."
|
||||
invoices:
|
||||
welcome:
|
||||
title: "Invoices"
|
||||
content: "<p>Here you will be able to download invoices and credit notes issued, as well as manage everything related to accounting and invoicing.</p><p>If you use third-party software to manage your invoices, it is possible to deactivate the billing module. For this, contact your system administrator.</p>"
|
||||
list:
|
||||
title: "Invoices list"
|
||||
content: "By default, this table lists all the invoices and credit notes issued by Fab-manager. You can sort the list in a different order by clicking on the header of each column."
|
||||
chained:
|
||||
title: "Chaining indicator"
|
||||
content: "<p>This icon ensures the inalterability of the accounting data of the invoice on this line, in accordance with the French finance law of 2018 against VAT fraud.</p><p>If a red icon appears instead of this one , please contact technical support immediately.</p>"
|
||||
download:
|
||||
title: "Download"
|
||||
content: "Click here to download the invoice in PDF format."
|
||||
refund:
|
||||
title: "Credit note"
|
||||
content: "Allows you to generate a credit note for the invoice on this line or some of its sub-elements. <strong>Warning:</strong> This will only generate the accounting document, the actual refund of the user will always be your responsibility."
|
||||
settings:
|
||||
title: "Settings"
|
||||
content: "<p>Here you can modify the parameters for invoices generation. Click on the item you are interested in to start editing.</p><p>In particular, this is where you can set if you are subject to VAT and the applicable rate.</p>"
|
||||
codes:
|
||||
title: "Accounting codes"
|
||||
content: "Set the accounting codes here for all kinds of entries generated by the software. This setting is only required if you use the accounting export functionality."
|
||||
export:
|
||||
title: "Accounting export"
|
||||
content: "Once the codes have been configured, click here to access the interface allowing you to export the entries to a third-party accounting software."
|
||||
periods:
|
||||
title: "Close accounting periods"
|
||||
content: "<p>The regulations of your country may require you to close your accounts regularly. The interface accessible from this button allows you to do this.</p> <p><strong>In France,</strong> if you are subject to VAT anti-fraud law <a href='https://bofip.impots.gouv.fr/bofip/10691-PGP.html' target='_blank'>BOI-TVA-DECLA-30-10-30-20160803</a>, this closing is mandatory at least once a year.</p><p>As a reminder, if you have to use a certified software (<a href='https://www.impots.gouv.fr/portail/suis-je-oblige-davoir-un-logiciel-de-caisse-securise' target='_blank'>take the test here</a>), you are under the legal obligation to provide a certificate of compliance of the software. <a href='mailto:contact@fab-manager.com'>Contact-us<a/> to get it.</p>"
|
||||
pricing:
|
||||
welcome:
|
||||
title: "Subscriptions & Prices"
|
||||
content: "Manage subscription plans and prices for the various services you offer to your members."
|
||||
new_plan:
|
||||
title: "New subscription plan"
|
||||
content: "Create subscription plans to offer preferential prices on machines and spaces to regular users."
|
||||
trainings:
|
||||
title: "Trainings"
|
||||
content: "Define training prices here, by user group."
|
||||
machines:
|
||||
title: "Machines"
|
||||
content: "Define here the prices of the machine slots, by user group. These prices will be applied to users who do not have subscriptions."
|
||||
spaces:
|
||||
title: "Espaces"
|
||||
content: "In the same way, define here the prices of the spaces slots, for the users without subscriptions."
|
||||
credits:
|
||||
title: "Credits"
|
||||
content: "<p>Credits allow you to give certain services for free to users who subscribe to a plan.</p><p>You can, for example, offer 2 hours of 3D printer for all annual subscriptions; or training of your choice for student subscribers, etc.</p>"
|
||||
coupons:
|
||||
title: "Coupons"
|
||||
content: "Create and manage promotional coupons allowing to offer punctual discounts to their holders."
|
||||
events:
|
||||
welcome:
|
||||
title: "Events"
|
||||
content: "Create events, track their reservations and organize them from this page."
|
||||
list:
|
||||
title: "The events"
|
||||
content: "This list displays all past or future events, as well as the number of reservations for each of them."
|
||||
filter:
|
||||
title: "Filter events"
|
||||
content: "Only display upcoming events in the list below; or on the contrary, only those already passed."
|
||||
categories:
|
||||
title: "Categories"
|
||||
content: "Categories help your users know what type of event it is. A category is required for each of the newly created events."
|
||||
themes:
|
||||
title: "Themes"
|
||||
content: "<p>Themes are an additional (and optional) categorization of your events. They can group together different events of very different forms.</p><p>For example, a two-day course about marquetry and an evening workshop about the handling of the wood planer, can be found in the theme « carpentry ».</p>"
|
||||
ages:
|
||||
title: "Age groups"
|
||||
content: "This other optional filter will help your users find events suited to their profile."
|
||||
prices:
|
||||
title: "Pricing categories"
|
||||
content: "The price of events does not depend on groups or subscriptions, but on the categories you define on this page."
|
||||
project_elements:
|
||||
welcome:
|
||||
title: "Projects"
|
||||
content: "Here you can define all the elements that will be available for members to document the projects they carry out."
|
||||
abuses:
|
||||
title: "Manage reports"
|
||||
content: "<p>Access here the management of reports.</p><p>Visitors can signal projects, for example for copyright infringement or for hate speech.</p><p>GDPR requires you to delete this reporting data once the required actions have been taken.</p>"
|
||||
statistics:
|
||||
welcome:
|
||||
title: "Statistics"
|
||||
content: "<p>From here, you will be able to access many statistics on your members and their uses within your Fab Lab.</p><p>In accordance with GDPR, users who have deleted their account continue to be reported in the statistics, but anonymously.</p>"
|
||||
export:
|
||||
title: "Export data"
|
||||
content: "You can choose to export all or part of the statistical data to an Excel file."
|
||||
trending:
|
||||
title: "Evolution"
|
||||
content: "Visualize the evolution over time of the main uses of your Fab Lab, thanks to graphs and curves."
|
||||
settings:
|
||||
welcome:
|
||||
title: "Application customization"
|
||||
content: "From here, you can configure the general settings of Fab-manager as well as customize various elements of the interface."
|
||||
home:
|
||||
title: "Customize home page"
|
||||
content: "<p>This WYSIWYG editor allows you to customize the appearance of the home page while using different components (last tweet, brief, etc.).</p><p><strong>Warning:</strong> Keep in mind that any uncontrolled changes can break the appearance of the home page.</p>"
|
||||
components:
|
||||
title: "Insert a component"
|
||||
content: "Click here to insert a pre-existing component into the home page."
|
||||
codeview:
|
||||
title: "Display HTML code"
|
||||
content: "This button allows you to directly view and modify the code of the home page. This is the recommended way to proceed, but it requires prior knowledge of HTML."
|
||||
reset:
|
||||
title: "Go back"
|
||||
content: "At any time, you can restore the original home page by clicking here."
|
||||
css:
|
||||
title: "Customize the style sheet"
|
||||
content: "For advanced users, it is possible to define a custom style sheet (CSS) for the home page."
|
||||
about:
|
||||
title: "About"
|
||||
content: "Fully personalize this page to present your activity."
|
||||
privacy:
|
||||
title: "Privacy policy"
|
||||
content: "<p>EExplain here how you use the data you collect about your members.</p><p>GDPR requires that a confidentiality policy is defined, as well as a data protection officer.</p>"
|
||||
draft:
|
||||
title: "Draft"
|
||||
content: "Click here to view a privacy policy draft with holes, which you just need to read and complete."
|
||||
open_api:
|
||||
welcome:
|
||||
title: "OpenAPI"
|
||||
content: "Fab-manager offers an open API allowing third-party software to deal simply with its data. This screen allows you to grant accesses to this API."
|
||||
doc:
|
||||
title: "Documentation"
|
||||
content: "Click here to access the API online documentation."
|
||||
|
@ -42,6 +42,9 @@ fr:
|
||||
select_some_machines: "Sélectionnez des machines"
|
||||
select_all: "Toutes"
|
||||
select_none: "Aucune"
|
||||
manage_machines: "Cliquez-ici pour ajouter ou supprimer des machines."
|
||||
manage_spaces: "Cliquez-ici pour ajouter ou supprimer des espaces."
|
||||
manage_trainings: "Cliquez-ici pour ajouter ou supprimer des formations."
|
||||
number_of_tickets: "Nombre de places : "
|
||||
adjust_the_opening_hours: "Ajuster l'horaire"
|
||||
to_time: "à" # eg. from 18:00 to 21:00
|
||||
@ -58,6 +61,7 @@ fr:
|
||||
select_nb_period: "Veuillez choisir un nombre de périodes pour la récurrence"
|
||||
select_end_date: "Veuillez choisir la date de dernière occurrence"
|
||||
about_to_create: "Vous vous apprêtez à créer {NUMBER, plural, one{le créneau} other{les créneaux}} {TYPE, select, machines{machine} training{formation} space{espace} other{autre}} suivant :"
|
||||
divided_in_slots: "Ce créneau sera proposé à la réservation par tranches de {DURATION} minutes. Contactez votre administrateur système pour modifier ce paramètre."
|
||||
reservable: "Réservable(s) :"
|
||||
labels: "Étiquette(s) :"
|
||||
none: "Aucune"
|
||||
@ -89,10 +93,11 @@ fr:
|
||||
view_reservations: "Voir les réservations"
|
||||
legend: "Légende"
|
||||
and: "et"
|
||||
external_sync: "Synchronisation d'agendas"
|
||||
|
||||
icalendar:
|
||||
icalendar_import: "Import iCalendar"
|
||||
intro: "Fab-manager vous permet d'importer automatiquement des évènements de calendrier, au format iCalendar RFC 5545, depuis des URL externes. Ces URL seront synchronisée toutes les nuits et les évènements seront affichés dans le calendrier publique."
|
||||
intro: "Fab-manager vous permet d'importer automatiquement des évènements de calendrier, au format iCalendar RFC 5545, depuis des URL externes. Ces URL seront synchronisée toutes les heures et les évènements seront affichés dans le calendrier publique. Vous pouvez aussi déclencher une synchronisation en cliquant sur le bouton correspondant, en face de chaque import."
|
||||
new_import: "Nouvel import ICS"
|
||||
color: "Couleur"
|
||||
text_color: "Couleur du texte"
|
||||
@ -127,6 +132,7 @@ fr:
|
||||
trainings:
|
||||
# suivre et surveiller les formations
|
||||
trainings_monitoring: "Suivi formations"
|
||||
plan_session: "Planifier une nouvelle session"
|
||||
trainings: "Formations"
|
||||
add_a_new_training: "Ajouter une nouvelle formation"
|
||||
name: "Nom"
|
||||
@ -1000,10 +1006,11 @@ fr:
|
||||
publish_will_notify: "Publier une nouvelle version enverra une notification à l'ensemble des utilisateurs."
|
||||
publish: "Publier"
|
||||
users_notified: "Les utilisateurs de la plateforme seront notifiés de la mise à jour."
|
||||
about_analytics: "J'accepte de partager des données anonymes avec l'équipe de développement pour aider à améliorer Fab-Manager."
|
||||
about_analytics: "J'accepte de partager des données anonymes avec l'équipe de développement pour aider à améliorer Fab-manager."
|
||||
read_more: "Quelles informations collectons-nous ?"
|
||||
analytics:
|
||||
intro_analytics_html: "Vous trouverez ci-dessous une vue détaillée de toutes les données de Fab-Manager collectera <strong>si l'autorisation lui est accordée.</strong>"
|
||||
title: "Amélioration de l'application"
|
||||
intro_analytics_html: "Vous trouverez ci-dessous une vue détaillée de toutes les données de Fab-manager collectera <strong>si l'autorisation lui est accordée.</strong>"
|
||||
version: "Version de l'application"
|
||||
members: "Nombre de membres"
|
||||
admins: "Nombre d'administrateurs"
|
||||
@ -1056,3 +1063,191 @@ fr:
|
||||
report_will_be_destroyed: "Une fois le signalement traité, le rapport sera supprimé. Cette action est irréversible, continuer ?"
|
||||
report_removed: "Le rapport a bien été supprimé"
|
||||
failed_to_remove: "Une erreur est survenue, impossible de supprimer le rapport"
|
||||
tour:
|
||||
conclusion:
|
||||
title: "Merci de votre attention"
|
||||
content: "<p>Si vous souhaitez relancer cette aide contextuelle, appuyez sur <strong>F1</strong> à n'importe quel moment ou cliquez sur [? Aide] depuis le menu utilisateur.</p><p>Si vous avez besoin d'aide supplémentaire, vous pouvez <a href='https://github.com/sleede/fab-manager/raw/master/doc/fr/guide_utilisation_fab_manager_v4.2.pdf' target='_blank'>consulter le guide d'utilisation</a> disponible en Français.</p><p>L'équipe de Fab-manager propose également du support personnalisé (aide à la prise en main, aide à l'installation, personnalisation, etc.), <a href='mailto:contact@fab-manager.com'>contactez-nous</a> pour plus d'informations.</p>"
|
||||
trainings:
|
||||
welcome:
|
||||
title: "Formations"
|
||||
content: "Ici vous pourrez créer, modifier et supprimer des formations. C'est également l'endroit où vous pourrez valider les formations suivies par vos membres."
|
||||
trainings:
|
||||
title: "Gérer les formations"
|
||||
content: "<p>Lors de la création d'une formation, vous pouvez définir un nombre de places par défaut. Néanmoins, le nombre de places effectives pourra être modifié pour chaque session.</p><p>La programmation des sessions de formation se fait depuis l'onglet administrateur [Agenda].</p><p>D'autre part, il est possible d'associer une ou plusieurs machines à une formation. Cela permet d'en faire un pré-requis pour la réservation de ces machines.</p>"
|
||||
filter:
|
||||
title: "Filtre"
|
||||
content: "Par défaut, seules les formations actives sont affichées ici. Affichez les autres en choisissant un autre filtre ici."
|
||||
tracking:
|
||||
title: "Suivi formations"
|
||||
content: "Une fois qu'une session de formation est terminée, vous pourrez valider la formation pour les membres présents depuis cet écran. Cette validation est indispensable pour leur permettre d'utiliser les machines associées, le cas échéant."
|
||||
calendar:
|
||||
welcome:
|
||||
title: "Agenda"
|
||||
content: "À partir de cet écran, vous pourrez planifier les créneaux durant lesquels les formations, machines et espaces seront réservables par les membres."
|
||||
agenda:
|
||||
title: "L'agenda"
|
||||
content: "Cliquez dans l'agenda pour commencer la création d'une nouvelle plage de disponibilité. Vous pouvez sélectionner directement toute la plage horaire souhaitée en maintenant votre clic."
|
||||
export:
|
||||
title: "Exporter"
|
||||
content: "Lancez la génération d'un fichier Excel, listant l'ensemble des créneaux de disponibilité créés dans l'agenda."
|
||||
import:
|
||||
title: "Importer des agendas externes"
|
||||
content: "Permet d'importer des agendas depuis une source externe au format iCal."
|
||||
members:
|
||||
welcome:
|
||||
title: "Utilisateurs"
|
||||
content: "Ici vous pourrez créer, modifier et supprimer des membres et des administrateurs. Vous pourrez également gérer les groupes, les étiquettes, réaliser des imports / exports avec des fichiers de tableur et connecter un logiciel de SSO."
|
||||
list:
|
||||
title: "Liste des membres"
|
||||
content: "Par défaut, ce tableau liste l'ensemble des membres de votre Fab-manager. Vous pouvez trier la liste dans un ordre différent en cliquant sur l'entête de chaque colonne."
|
||||
search:
|
||||
title: "Rechercher un utilisateur"
|
||||
content: "Ce champ de saisie vous permet de faire une recherche en texte libre sur l'ensemble des colonnes du tableau ci-dessous."
|
||||
filter:
|
||||
title: "Filtrer la liste"
|
||||
content: "<p>Filtrez la liste ci-dessous pour afficher uniquement les utilisateurs n'ayant pas confirmé leur adresse mail ou les comptes inactifs depuis plus de 3 ans.</p><p>Pour information, la RGPD impose de supprimer les comptes inactifs depuis plus de 3 ans.</p>"
|
||||
actions:
|
||||
title: "Actions sur le membre"
|
||||
content: "<p>Les boutons dans cette colonne vous permettent d'afficher et de modifier l'ensemble des paramètres du membre, ou alors de le supprimer de manière irréversible.</p><p>En cas de suppression, les informations de facturation seront néanmoins conservées pendant 10 ans et des données statistiques seront également conservées de manière anonyme.</p>"
|
||||
exports:
|
||||
title: "Exporter"
|
||||
content: "Chacun de ces boutons lance la génération d'un fichier Excel listant l'ensemble des membres, abonnements ou réservations, actuelles et passées."
|
||||
import:
|
||||
title: "Importer des membres"
|
||||
content: "Permet d'importer une liste de membres à créer dans Fab-manager, à partir d'un fichier CSV."
|
||||
admins:
|
||||
title: "Gérer les administrateurs"
|
||||
content: "De la même manière que les membres, gérez ici les administrateurs de votre Fab-manager.<br>Les administrateurs peuvent prendre des réservations pour n'importe quel membre ainsi que modifier l'ensemble des paramètres du logiciel."
|
||||
groups:
|
||||
title: "Gérer les groupes"
|
||||
content: "Les groupes vous permettent de mieux segmenter votre offre tarifaire."
|
||||
labels:
|
||||
title: "Gérer les étiquettes"
|
||||
content: "Les étiquettes vous permettent de réserver certains créneaux aux utilisateurs associés à ces mêmes étiquettes."
|
||||
sso:
|
||||
title: "Authentification unique"
|
||||
content: "Ici vous pourrez mettre en place et gérer un système d'authentification unique (ou Single Sign-On - SSO)."
|
||||
invoices:
|
||||
welcome:
|
||||
title: "Factures"
|
||||
content: "<p>Ici, vous pourrez télécharger les factures et les avoirs émis, ainsi que gérer tout ce qui a trait à la comptabilité et à la facturation.</p><p>Si vous utilisez un logiciel tiers pour gérer vos factures, il est possible de désactiver le module de facturation. Pour cela, contactez votre administrateur système.</p>"
|
||||
list:
|
||||
title: "Liste des factures"
|
||||
content: "Par défaut, ce tableau liste l'ensemble des factures et avoirs émis via Fab-manager. Vous pouvez trier la liste dans un ordre différent en cliquant sur l'entête de chaque colonne."
|
||||
chained:
|
||||
title: "Indicateur de chaînage"
|
||||
content: "<p>Cette icône assure l'inaltérablité des données comptables de la facture sur cette ligne, conformément à la loi de finances française de 2018 contre la fraude à la TVA.</p><p>Si une icône rouge apparaît au lieu de celle-ci, merci de contactez immédiatement le support technique.</p>"
|
||||
download:
|
||||
title: "Télécharger"
|
||||
content: "Cliquez ici pour télécharger la facture au format PDF."
|
||||
refund:
|
||||
title: "Avoir"
|
||||
content: "Permet de générer un avoir sur la facture de cette ligne ou certains de ses sous-éléments. <strong>Attention :</strong> Cela générera uniquement le document comptable, le remboursement effectif de l'utilisateur restera toujours à votre charge."
|
||||
settings:
|
||||
title: "Paramètres"
|
||||
content: "<p>Ici vous pourrez modifier les paramètres de génération des factures. Cliquez sur l'élément qui vous intéresse pour commencer l'édition.</p><p>C'est notamment ici que vous pourrez définir si vous êtes assujettis à la TVA et à quel taux.</p>"
|
||||
codes:
|
||||
title: "Codes comptables"
|
||||
content: "Paramétrez ici les codes comptables pour tous les types d'écritures générés par le logiciel. Ce paramétrage n'est requis que si vous utilisez la fonctionnalité d'export comptable."
|
||||
export:
|
||||
title: "Export comptable"
|
||||
content: "Une fois les codes configurés, cliquez ici pour accéder à l'interface vous permettant d'exporter les écritures vers un logiciel comptable tiers."
|
||||
periods:
|
||||
title: "Clôturer les périodes comptables"
|
||||
content: "<p>La réglementation de votre pays peut vous imposer de clôturer régulièrement vos comptes. L'interface accessible depuis ce bouton permet de le faire.</p> <p><strong>En France,</strong> si vous êtes soumis à la loi anti-fraude TVA <a href='https://bofip.impots.gouv.fr/bofip/10691-PGP.html' target='_blank'>BOI-TVA-DECLA-30-10-30-20160803</a>, cette clôture est obligatoire au moins une fois par an.</p><p>Pour rappel, en cas d'obligation d'utilisation d'un logiciel certifié (<a href='https://www.impots.gouv.fr/portail/suis-je-oblige-davoir-un-logiciel-de-caisse-securise' target='_blank'>faites le test ici</a>), vous êtes dans l'obligation légale de fournir une attestation de conformité du logiciel. <a href='mailto:contact@fab-manager.com'>Contactez-nous<a/> pour l'obtenir.</p>"
|
||||
pricing:
|
||||
welcome:
|
||||
title: "Abonnements & Tarifs"
|
||||
content: "Gérez les formules d'abonnement et les prix des différents services que vous proposez à vos membres."
|
||||
new_plan:
|
||||
title: "Nouvelle formule d'abonnement"
|
||||
content: "Créez des formules d'abonnement pour proposer des prix préférentiels sur les machines et les espaces, aux utilisateurs réguliers."
|
||||
trainings:
|
||||
title: "Formations"
|
||||
content: "Définissez ici les prix des formations, par groupe d'utilisateurs."
|
||||
machines:
|
||||
title: "Machines"
|
||||
content: "Définissez ici les prix des créneaux machine, par groupe d'utilisateurs. Ces prix seront appliqués aux utilisateurs qui n'ont pas d'abonnement."
|
||||
spaces:
|
||||
title: "Espaces"
|
||||
content: "De la même manière, définissez ici les prix des créneaux des espaces, pour les utilisateurs sans abonnement."
|
||||
credits:
|
||||
title: "Crédits"
|
||||
content: "<p>Les crédits vous permettent d'offrir certains services aux utilisateurs qui souscrivent à un abonnement.</p><p>Vous pouvez, par exemple, offrir 2h d'imprimante 3D pour tous les abonnements annuels ; ou une formation au choix pour les abonnés étudiants, etc.</p>"
|
||||
coupons:
|
||||
title: "Codes promotionnels"
|
||||
content: "Créez et gérez des codes promotionnels permettant d'offir des réductions ponctuelles à leurs détenteurs."
|
||||
events:
|
||||
welcome:
|
||||
title: "Évènements"
|
||||
content: "Créez des évènements, suivez leurs réservations et organisez-les depuis cette page."
|
||||
list:
|
||||
title: "Les évènements"
|
||||
content: "Cette liste affiche l'ensemble des évènements passés ou à venir, ainsi que le nombre de réservations pour chacun d'eux."
|
||||
filter:
|
||||
title: "Filtrez les évènements"
|
||||
content: "N'affichez que les évènements à venir dans la liste ci-dessous ; ou au contraire, uniquement ceux déjà passés."
|
||||
categories:
|
||||
title: "Les catégories"
|
||||
content: "Les catégories aident vos utilisateurs à savoir de quel type d'évènement il s'agit. Une catégorie est requise pour chacun des évènements nouvellement créé."
|
||||
themes:
|
||||
title: "Les thématique"
|
||||
content: "<p>Les thématiques constituent une catégorisation supplémentaire (et optionnelle) de vos évènements. Elles peuvent regrouper différents évènements de formes très différentes.</p><p>Par exemple, un stage de deux jours sur la marqueterie et un atelier d'une soirée sur la prise en main du rabot à bois, peuvent se retrouver dans la thématique « menuiserie ».</p>"
|
||||
ages:
|
||||
title: "Les tranches d'âge"
|
||||
content: "Cet autre filtre optionnel aidera vos utilisateurs à trouver des évènements adaptés à leur profil."
|
||||
prices:
|
||||
title: "Catégories tarifaires"
|
||||
content: "Le prix des évènements ne dépend pas des groupes ou des abonnements, mais des catégories que vous définissez sur cette page."
|
||||
project_elements:
|
||||
welcome:
|
||||
title: "Projets"
|
||||
content: "Vous pouvez définir ici l'ensemble des éléments qui seront disponibles pour que les membres documentent les projets qu'ils réalisent."
|
||||
abuses:
|
||||
title: "Gérer les signalements"
|
||||
content: "<p>Accédez par ici à la gestion des signalements.</p><p>Des visiteurs peuvent effectuer des signalements sur les projets, par exemple pour une atteinte au droit d'auteur ou pour un texte incitant à la haine.</p><p>La RGPD vous impose de supprimer ces données de signalement une fois que les actions requises ont été effectuées.</p>"
|
||||
statistics:
|
||||
welcome:
|
||||
title: "Statistiques"
|
||||
content: "<p>À partir d'ici, vous pourrez accéder à un ensemble de statistiques sur vos membres et leurs usages au sein de votre Fab Lab.</p><p>Conformément à la RGPD, les utilisateurs ayant supprimé leur compte continuent d'être rapportés dans les statistiques, mais de manière anonyme.</p>"
|
||||
export:
|
||||
title: "Exporter les données"
|
||||
content: "Vous pouvez choisir d'exporter tout ou partie des données statistiques vers un fichier Excel."
|
||||
trending:
|
||||
title: "Évolution"
|
||||
content: "Visualisez l'évolution dans le temps des principaux usages de votre Fab Lab, grâce à des graphiques et des courbes."
|
||||
settings:
|
||||
welcome:
|
||||
title: "Personnalisation de l'application"
|
||||
content: "D'ici, vous pourrez configurer les réglages généraux de Fab-manager ainsi que personnaliser différents éléments de l'interface."
|
||||
home:
|
||||
title: "Personnaliser la page d'accueil"
|
||||
content: "<p>Cet éditeur WYSIWYG vous permet de personnaliser l'apparence de la page d'accueil tout en utilisant différents composants (dernier tweet, brève, etc.).</p><p><strong>Attention :</strong> Gardez à l'esprit que toute modification non maîtrisée peut casser l'apparence de la page d'accueil.</p>"
|
||||
components:
|
||||
title: "Insérer un composant"
|
||||
content: "Cliquez ici pour insérer un composant pré-existant dans la page d'accueil."
|
||||
codeview:
|
||||
title: "Afficher le code HTML"
|
||||
content: "Ce bouton vous permet d'afficher et de modifier directement le code de la page d'accueil. C'est la méthode recommandée, mais elle nécessite une connaissance préalable du HTML."
|
||||
reset:
|
||||
title: "Revenir en arrière"
|
||||
content: "À tout moment, vous pouvez restaurer la page d'accueil initiale en cliquant ici."
|
||||
css:
|
||||
title: "Personnaliser la feuille de style"
|
||||
content: "Pour les utilisateurs avancés, il est possible de définir une feuille de style (CSS) personnalisée pour la page d'accueil."
|
||||
about:
|
||||
title: "À propos"
|
||||
content: "Personnalisez entièrement cette page pour présenter votre activité."
|
||||
privacy:
|
||||
title: "Politique de confidentialité"
|
||||
content: "<p>Expliquez ici la façon dont vous utilisez les données que vous recueillez sur vos membres.</p><p>La RGPD impose qu'une politique de confidentialité soit définie, ainsi qu'un délégué à la protection des données.</p>"
|
||||
draft:
|
||||
title: "Brouillon"
|
||||
content: "Cliquez ici pour afficher un brouillon à trous d'une politique de confidentialité, qu'il ne vous reste plus qu'à relire et à compléter."
|
||||
open_api:
|
||||
welcome:
|
||||
title: "OpenAPI"
|
||||
content: "Fab-manager propose une API ouverte permettant à des logiciels tiers de s'interfacer simplement avec ses données. Cet écran vous permet d'accorder des accès à cette API."
|
||||
doc:
|
||||
title: "Documentation"
|
||||
content: "Cliquez ici pour accéder à la documentation en ligne de l'API."
|
||||
|
@ -42,6 +42,9 @@ pt:
|
||||
select_some_machines: "Selecionar algumas máquinas"
|
||||
select_all: "Tudo"
|
||||
select_none: "Não"
|
||||
manage_machines: "Click here to add or remove machines."
|
||||
manage_spaces: "Click here to add or remove spaces."
|
||||
manage_trainings: "Click here to add or remove trainings."
|
||||
number_of_tickets: "Número de vagas: "
|
||||
adjust_the_opening_hours: "Ajustar o horário de funcionamento"
|
||||
to_time: "ás" # eg. from 18:00 to 21:00
|
||||
@ -58,6 +61,7 @@ pt:
|
||||
select_nb_period: "Please select a number of periods for the recurrence"
|
||||
select_end_date: "Please select the date of the last occurrence"
|
||||
about_to_create: "You are about to create the following {TYPE, select, machines{machine} training{training} space{space} other{other}} {NUMBER, plural, one{slot} other{slots}}:"
|
||||
divided_in_slots: "This slot will be open for booking in {DURATION}-minutes increments. Contact your system administrator to change this setting."
|
||||
reservable: "Reservable(s) :"
|
||||
labels: "Etiqueta(s):"
|
||||
none: "Nenhuma"
|
||||
@ -89,10 +93,11 @@ pt:
|
||||
view_reservations: "Ver reservas"
|
||||
legend: "legenda"
|
||||
and: "and"
|
||||
external_sync: "Calendar synchronization"
|
||||
|
||||
icalendar:
|
||||
icalendar_import: "iCalendar import"
|
||||
intro: "Fab-manager allows to automatically import calendar events, at RFC 5545 iCalendar format, from external URL. These URL are synchronized every nights and the events are shown in the public calendar."
|
||||
intro: "Fab-manager allows to automatically import calendar events, at RFC 5545 iCalendar format, from external URL. These URL are synchronized every hours and the events are shown in the public calendar. You can trigger a synchronisation too, by clicking on the corresponding button, in front of each import."
|
||||
new_import: "New ICS import"
|
||||
color: "Colour"
|
||||
text_color: "Text colour"
|
||||
@ -127,6 +132,7 @@ pt:
|
||||
trainings:
|
||||
# track and monitor the trainings
|
||||
trainings_monitoring: "Trainings monitoring"
|
||||
plan_session: "Schedule a new session"
|
||||
trainings: "Treinamentos"
|
||||
add_a_new_training: "Adicionar um novo treinamento"
|
||||
name: "Name"
|
||||
@ -1000,10 +1006,11 @@ pt:
|
||||
publish_will_notify: "Publish a new version will send a notification to every users."
|
||||
publish: "Publish"
|
||||
users_notified: "Platform users will be notified of the update."
|
||||
about_analytics: "I agree to share anonymous data with the development team to help improve Fab-Manager."
|
||||
about_analytics: "I agree to share anonymous data with the development team to help improve Fab-manager."
|
||||
read_more: "Which data do we collect?"
|
||||
analytics:
|
||||
intro_analytics_html: "You'll find below a detailed view of all the data, Fab-Manager will collect <strong>if permission is granted.</strong>"
|
||||
title: "Application improvement"
|
||||
intro_analytics_html: "You'll find below a detailed view of all the data, Fab-manager will collect <strong>if permission is granted.</strong>"
|
||||
version: "Application version"
|
||||
members: "Number of members"
|
||||
admins: "Number of administrators"
|
||||
@ -1056,3 +1063,192 @@ pt:
|
||||
report_will_be_destroyed: "Once the report has been processed, it will be deleted. This can't be undone, continue?"
|
||||
report_removed: "The report has been deleted"
|
||||
failed_to_remove: "An error occurred, unable to delete the report"
|
||||
|
||||
tour:
|
||||
conclusion:
|
||||
title: "Thank you for your attention"
|
||||
content: "<p>If you want to restart this contextual help, press <strong>F1</strong> at any time or click on [? Help] from the user's menu.</p><p>If you need additional help, you can <a href='https://github.com/sleede/fab-manager/raw/master/doc/fr/guide_utilisation_fab_manager_v4.2.pdf' target='_blank'>check the user guide</a> (only in French for now).</p><p>The Fab-manager's team also provides personalized support (help with getting started, help with installation, customization, etc.), <a href='mailto:contact@fab-manager.com'>contact-us</a> for more info.</p>"
|
||||
trainings:
|
||||
welcome:
|
||||
title: "Trainings"
|
||||
content: "Here you can create, modify and delete trainings. It is also the place where you can validate the training courses followed by your members."
|
||||
trainings:
|
||||
title: "Manage trainings"
|
||||
content: "<p>When creating a training, you can define a default number of places. However, the number of actual places may be modified for each session.</p><p>The training sessions are scheduled from the administrator tab [Calendar].</p><p>Another thing: it is possible to associate one or more machines with a training. This makes it a prerequisite for the reservation of these machines.</p>"
|
||||
filter:
|
||||
title: "Filter"
|
||||
content: "By default, only active courses are displayed here. Display the others by choosing another filter here."
|
||||
tracking:
|
||||
title: "Trainings monitoring"
|
||||
content: "Once a training session is finished, you can validate the training for the members present from this screen. This validation is essential to allow them to use the associated machines, if applicable."
|
||||
calendar:
|
||||
welcome:
|
||||
title: "Calendar"
|
||||
content: "From this screen, you can plan the slots during which training, machines and spaces will be bookable by members."
|
||||
agenda:
|
||||
title: "The calendar"
|
||||
content: "Click in the calendar to start creating a new availability range. You can directly select the entire time range desired by maintaining your click."
|
||||
export:
|
||||
title: "Export"
|
||||
content: "Start generating an Excel file, listing all the availability slots created in the calendar."
|
||||
import:
|
||||
title: "Import external calendars"
|
||||
content: "Allows you to import calendars from an external source in iCal format."
|
||||
members:
|
||||
welcome:
|
||||
title: "Users"
|
||||
content: "Here you can create, modify and delete members and administrators. You can also manage groups, labels, import / export with spreadsheet files and connect SSO software."
|
||||
list:
|
||||
title: "Members list"
|
||||
content: "By default, this table lists all the members of your Fab-manager. You can sort the list in a different order by clicking on the header of each column."
|
||||
search:
|
||||
title: "Find a user"
|
||||
content: "This input field allows you to search for any text on all of the columns in the table below."
|
||||
filter:
|
||||
title: "Filter the list"
|
||||
content: "<p>Filter the list below to display only users who have not confirmed their email address or inactive accounts for more than 3 years.</p><p>Please notice that the GDPR requires that you delete any accounts inactive for more than 3 years.</p>"
|
||||
actions:
|
||||
title: "Members actions"
|
||||
content: "<p>The buttons in this column allow you to display and modify all of the member's parameters, or to delete them irreversibly.</p><p>In the event of a deletion, the billing information will be kept for 10 years and statistical data will also be kept anonymously.</p>"
|
||||
exports:
|
||||
title: "Export"
|
||||
content: "Each of these buttons starts the generation of an Excel file listing all the members, subscriptions or reservations, current and past."
|
||||
import:
|
||||
title: "Import members"
|
||||
content: "Allows you to import a list of members to create in Fab-manager, from a CSV file."
|
||||
admins:
|
||||
title: "Manage administrators"
|
||||
content: "In the same way as the members, manage the administrators of your Fab-manager here.<br>The administrators can take reservations for any member as well as modify all the parameters of the software."
|
||||
groups:
|
||||
title: "Manage groups"
|
||||
content: "Groups allow you to better segment your price list."
|
||||
labels:
|
||||
title: "Manage tags"
|
||||
content: "The labels allow you to reserve certain slots for users associated with these same labels."
|
||||
sso:
|
||||
title: "Single Sign-On"
|
||||
content: "Here you can set up and manage a single authentication system (SSO)."
|
||||
invoices:
|
||||
welcome:
|
||||
title: "Invoices"
|
||||
content: "<p>Here you will be able to download invoices and credit notes issued, as well as manage everything related to accounting and invoicing.</p><p>If you use third-party software to manage your invoices, it is possible to deactivate the billing module. For this, contact your system administrator.</p>"
|
||||
list:
|
||||
title: "Invoices list"
|
||||
content: "By default, this table lists all the invoices and credit notes issued by Fab-manager. You can sort the list in a different order by clicking on the header of each column."
|
||||
chained:
|
||||
title: "Chaining indicator"
|
||||
content: "<p>This icon ensures the inalterability of the accounting data of the invoice on this line, in accordance with the French finance law of 2018 against VAT fraud.</p><p>If a red icon appears instead of this one , please contact technical support immediately.</p>"
|
||||
download:
|
||||
title: "Download"
|
||||
content: "Click here to download the invoice in PDF format."
|
||||
refund:
|
||||
title: "Credit note"
|
||||
content: "Allows you to generate a credit note for the invoice on this line or some of its sub-elements. <strong>Warning:</strong> This will only generate the accounting document, the actual refund of the user will always be your responsibility."
|
||||
settings:
|
||||
title: "Settings"
|
||||
content: "<p>Here you can modify the parameters for invoices generation. Click on the item you are interested in to start editing.</p><p>In particular, this is where you can set if you are subject to VAT and the applicable rate.</p>"
|
||||
codes:
|
||||
title: "Accounting codes"
|
||||
content: "Set the accounting codes here for all kinds of entries generated by the software. This setting is only required if you use the accounting export functionality."
|
||||
export:
|
||||
title: "Accounting export"
|
||||
content: "Once the codes have been configured, click here to access the interface allowing you to export the entries to a third-party accounting software."
|
||||
periods:
|
||||
title: "Close accounting periods"
|
||||
content: "<p>The regulations of your country may require you to close your accounts regularly. The interface accessible from this button allows you to do this.</p> <p><strong>In France,</strong> if you are subject to VAT anti-fraud law <a href='https://bofip.impots.gouv.fr/bofip/10691-PGP.html' target='_blank'>BOI-TVA-DECLA-30-10-30-20160803</a>, this closing is mandatory at least once a year.</p><p>As a reminder, if you have to use a certified software (<a href='https://www.impots.gouv.fr/portail/suis-je-oblige-davoir-un-logiciel-de-caisse-securise' target='_blank'>take the test here</a>), you are under the legal obligation to provide a certificate of compliance of the software. <a href='mailto:contact@fab-manager.com'>Contact-us<a/> to get it.</p>"
|
||||
pricing:
|
||||
welcome:
|
||||
title: "Subscriptions & Prices"
|
||||
content: "Manage subscription plans and prices for the various services you offer to your members."
|
||||
new_plan:
|
||||
title: "New subscription plan"
|
||||
content: "Create subscription plans to offer preferential prices on machines and spaces to regular users."
|
||||
trainings:
|
||||
title: "Trainings"
|
||||
content: "Define training prices here, by user group."
|
||||
machines:
|
||||
title: "Machines"
|
||||
content: "Define here the prices of the machine slots, by user group. These prices will be applied to users who do not have subscriptions."
|
||||
spaces:
|
||||
title: "Espaces"
|
||||
content: "In the same way, define here the prices of the spaces slots, for the users without subscriptions."
|
||||
credits:
|
||||
title: "Credits"
|
||||
content: "<p>Credits allow you to give certain services for free to users who subscribe to a plan.</p><p>You can, for example, offer 2 hours of 3D printer for all annual subscriptions; or training of your choice for student subscribers, etc.</p>"
|
||||
coupons:
|
||||
title: "Coupons"
|
||||
content: "Create and manage promotional coupons allowing to offer punctual discounts to their holders."
|
||||
events:
|
||||
welcome:
|
||||
title: "Events"
|
||||
content: "Create events, track their reservations and organize them from this page."
|
||||
list:
|
||||
title: "The events"
|
||||
content: "This list displays all past or future events, as well as the number of reservations for each of them."
|
||||
filter:
|
||||
title: "Filter events"
|
||||
content: "Only display upcoming events in the list below; or on the contrary, only those already passed."
|
||||
categories:
|
||||
title: "Categories"
|
||||
content: "Categories help your users know what type of event it is. A category is required for each of the newly created events."
|
||||
themes:
|
||||
title: "Themes"
|
||||
content: "<p>Themes are an additional (and optional) categorization of your events. They can group together different events of very different forms.</p><p>For example, a two-day course about marquetry and an evening workshop about the handling of the wood planer, can be found in the theme « carpentry ».</p>"
|
||||
ages:
|
||||
title: "Age groups"
|
||||
content: "This other optional filter will help your users find events suited to their profile."
|
||||
prices:
|
||||
title: "Pricing categories"
|
||||
content: "The price of events does not depend on groups or subscriptions, but on the categories you define on this page."
|
||||
project_elements:
|
||||
welcome:
|
||||
title: "Projects"
|
||||
content: "Here you can define all the elements that will be available for members to document the projects they carry out."
|
||||
abuses:
|
||||
title: "Manage reports"
|
||||
content: "<p>Access here the management of reports.</p><p>Visitors can signal projects, for example for copyright infringement or for hate speech.</p><p>GDPR requires you to delete this reporting data once the required actions have been taken.</p>"
|
||||
statistics:
|
||||
welcome:
|
||||
title: "Statistics"
|
||||
content: "<p>From here, you will be able to access many statistics on your members and their uses within your Fab Lab.</p><p>In accordance with GDPR, users who have deleted their account continue to be reported in the statistics, but anonymously.</p>"
|
||||
export:
|
||||
title: "Export data"
|
||||
content: "You can choose to export all or part of the statistical data to an Excel file."
|
||||
trending:
|
||||
title: "Evolution"
|
||||
content: "Visualize the evolution over time of the main uses of your Fab Lab, thanks to graphs and curves."
|
||||
settings:
|
||||
welcome:
|
||||
title: "Application customization"
|
||||
content: "From here, you can configure the general settings of Fab-manager as well as customize various elements of the interface."
|
||||
home:
|
||||
title: "Customize home page"
|
||||
content: "<p>This WYSIWYG editor allows you to customize the appearance of the home page while using different components (last tweet, brief, etc.).</p><p><strong>Warning:</strong> Keep in mind that any uncontrolled changes can break the appearance of the home page.</p>"
|
||||
components:
|
||||
title: "Insert a component"
|
||||
content: "Click here to insert a pre-existing component into the home page."
|
||||
codeview:
|
||||
title: "Display HTML code"
|
||||
content: "This button allows you to directly view and modify the code of the home page. This is the recommended way to proceed, but it requires prior knowledge of HTML."
|
||||
reset:
|
||||
title: "Go back"
|
||||
content: "At any time, you can restore the original home page by clicking here."
|
||||
css:
|
||||
title: "Customize the style sheet"
|
||||
content: "For advanced users, it is possible to define a custom style sheet (CSS) for the home page."
|
||||
about:
|
||||
title: "About"
|
||||
content: "Fully personalize this page to present your activity."
|
||||
privacy:
|
||||
title: "Privacy policy"
|
||||
content: "<p>EExplain here how you use the data you collect about your members.</p><p>GDPR requires that a confidentiality policy is defined, as well as a data protection officer.</p>"
|
||||
draft:
|
||||
title: "Draft"
|
||||
content: "Click here to view a privacy policy draft with holes, which you just need to read and complete."
|
||||
open_api:
|
||||
welcome:
|
||||
title: "OpenAPI"
|
||||
content: "Fab-manager offers an open API allowing third-party software to deal simply with its data. This screen allows you to grant accesses to this API."
|
||||
doc:
|
||||
title: "Documentation"
|
||||
content: "Click here to access the API online documentation."
|
||||
|
@ -23,6 +23,9 @@ en:
|
||||
my_invoices: "My Invoices"
|
||||
my_wallet: "My Wallet"
|
||||
|
||||
# contextual help
|
||||
help: "Help"
|
||||
|
||||
# login/logout
|
||||
sign_out: "Sign Out"
|
||||
sign_up: "Sign Up"
|
||||
@ -44,15 +47,15 @@ en:
|
||||
public_calendar: "Calendar"
|
||||
|
||||
# left menu (admin)
|
||||
trainings_monitoring: "Trainings monitoring"
|
||||
manage_the_calendar: "Manage the Calendar"
|
||||
manage_the_users: "Manage the Users"
|
||||
manage_the_invoices: "Manage the invoices"
|
||||
trainings_monitoring: "Trainings"
|
||||
manage_the_calendar: "Calendar"
|
||||
manage_the_users: "Users"
|
||||
manage_the_invoices: "Invoices"
|
||||
subscriptions_and_prices: "Subscriptions and Prices"
|
||||
manage_the_events: "Manage the events"
|
||||
manage_the_machines: "Manage the Machines"
|
||||
manage_the_spaces: "Manage the Spaces"
|
||||
manage_the_projects_elements: "Manage the Projects Elements"
|
||||
manage_the_events: "Events"
|
||||
manage_the_machines: "Machines"
|
||||
manage_the_spaces: "Spaces"
|
||||
manage_the_projects_elements: "Projects"
|
||||
statistics: "Statistics"
|
||||
customization: "Customization"
|
||||
open_api_clients: "OpenAPI clients"
|
||||
@ -123,8 +126,8 @@ en:
|
||||
|
||||
# Fab-manager's version
|
||||
version: "Version:"
|
||||
upgrade_fabmanager: "Upgrade Fab-Manager"
|
||||
current_version: "You are currently using version {VERSION} of Fab-Manager."
|
||||
upgrade_fabmanager: "Upgrade Fab-manager"
|
||||
current_version: "You are currently using version {VERSION} of Fab-manager."
|
||||
upgrade_to: "A new release is available. You can upgrade up to version {VERSION}."
|
||||
read_more: "View the details of this release"
|
||||
security_version_html: "<strong>Your current version is vulnerable!</strong><br> A later version, currently available, includes security fixes. Upgrade as soon as possible!"
|
||||
@ -171,7 +174,7 @@ en:
|
||||
# projects gallery
|
||||
the_fablab_projects: "The Fab Lab projects"
|
||||
add_a_project: "Add a project"
|
||||
search_over_the_whole_network: "Search over the whole Fab Manager network"
|
||||
search_over_the_whole_network: "Search over the whole Fab-manager network"
|
||||
tooltip_openlab_projects_switch: "The search over the whole network lets you search over the projects of every Fab-manager using this feature !"
|
||||
openlab_search_not_available_at_the_moment: "Search over the whole network is not available at the moment. You still can search over the projects of this platform."
|
||||
project_search_result_is_empty: "Sorry, we found no results matching your search criteria."
|
||||
@ -220,6 +223,7 @@ en:
|
||||
# list of machines
|
||||
the_fablab_s_machines: "The FabLab's machines"
|
||||
add_a_machine: "Add a machine"
|
||||
new_availability: "Open reservations"
|
||||
book: "Book"
|
||||
_or_the_: " or the "
|
||||
status_enabled: "Enabled"
|
||||
@ -294,7 +298,8 @@ en:
|
||||
add_an_event: "Add an event"
|
||||
load_the_next_events: "Load the next events..."
|
||||
full_price_: "Full price:"
|
||||
to_date: "to" # context: date. eg: 'from 01/01 to 01/05'
|
||||
to_date: "to" # eg. from 01/01 to 01/05
|
||||
all_themes: "All themes"
|
||||
|
||||
events_show:
|
||||
# details and booking of an event
|
||||
@ -306,8 +311,8 @@ en:
|
||||
ending: "Ending:"
|
||||
opening_hours: "Opening hours:"
|
||||
all_day: "All day"
|
||||
from_time: "From" # context: time. eg. 'from 18:00 to 21:00'
|
||||
to_time: "to" # context: time. eg. 'from 18:00 to 21:00'
|
||||
from_time: "From" # eg. from 18:00 to 21:00
|
||||
to_time: "to" # eg. from 18:00 to 21:00
|
||||
full_price_: "Full price:"
|
||||
tickets_still_availables: "Tickets still available:"
|
||||
sold_out: "Sold out."
|
||||
@ -361,6 +366,7 @@ en:
|
||||
spaces_list:
|
||||
# list of spaces
|
||||
the_spaces: "The spaces"
|
||||
new_availability: "Open reservations"
|
||||
add_a_space: "Add a space"
|
||||
status_enabled: "Enabled"
|
||||
status_disabled: "Disabled"
|
||||
@ -377,3 +383,83 @@ en:
|
||||
characteristics: "Characteristics"
|
||||
files_to_download: "Files to download"
|
||||
projects_using_the_space: "Projects using the space"
|
||||
|
||||
tour:
|
||||
conclusion:
|
||||
title: "Thank you for your attention"
|
||||
content: "<p>If you want to restart this contextual help, press <strong>F1</strong> at any time or click on [? Help] from the user's menu.</p><p>If you need additional help, you can <a href='https://github.com/sleede/fab-manager/raw/master/doc/fr/guide_utilisation_fab_manager_v4.2.pdf' target='_blank'>check the user guide</a> (only in French for now).</p><p>The Fab-manager's team also provides personalized support (help with getting started, help with installation, customization, etc.), <a href='mailto:contact@fab-manager.com'>contact-us</a> for more info.</p>"
|
||||
welcome:
|
||||
welcome:
|
||||
title: "Welcome to Fab-manager"
|
||||
content: "To help you get started with the application, we are going to take a quick tour of the features."
|
||||
home:
|
||||
title: "Home page"
|
||||
content: "Clicking here will take you back to the home page where you are currently."
|
||||
machines:
|
||||
title: "Machines"
|
||||
content: "<p>This page will allow you to consult the list of all machines and reserve a slot on behalf of a member.</p><p>A machine can be, for example, a 3D printer.</p><p>Members can also access this page and reserve a machine themselves, if credit card payment is enabled, or if some prices are equal to 0.</p>"
|
||||
trainings:
|
||||
title: "Trainings"
|
||||
content: "<p>This page will allow you to consult the list of all training sessions and to register a member for a training session.</p><p>Certaines formations peuvent être un préalable à la réservation de certaines machines.</p><p>Members can also access this page and register for a training session themselves, if credit card payment is enabled, or if some prices are equal to 0.</p>"
|
||||
spaces:
|
||||
title: "Spaces"
|
||||
content: "<p>This page will allow you to consult the list of all available spaces and to reserve a place on a slot, on behalf of a member.</p><p>A space can be, for example, a woodshop or a meeting room.</p><p>Their particularity is that they can be booked by several people at the same time.</p><p>Members can also access this page and reserve a machine themselves, if credit card payment is enabled, or if some prices are equal to 0.</p>"
|
||||
events:
|
||||
title: "Events"
|
||||
content: "<p>An open house evening or an internship to make your desk lamp? It's over here!</p><p>Events can be free or paid (with different prices), with or without reservation.</p><p>Again, members can access this page and book themselves places for free events, or paid events if credit card payment is enabled.</p>"
|
||||
calendar:
|
||||
title: "Agenda"
|
||||
content: "Visualize at a glance everything that is scheduled for the next coming weeks (events, training, machines available, etc.)."
|
||||
projects:
|
||||
title: "Projects"
|
||||
content: "<p>Document and share all your creations with the community.</p><p>If you use OpenLab, you will also be able to consult the projects of the entire Fab-Manager network. <a href='mailto:contact@fab-manager.com'>Contact-us</a> to get your access, it's free!</p>"
|
||||
plans:
|
||||
title: "Subscriptions"
|
||||
content: "Subscriptions provide a way to segment your prices and provide benefits to regular users."
|
||||
admin:
|
||||
title: "Administrator section"
|
||||
content: "<p>All of the elements below are only accessible to administrators. They allow you to manage and configure Fab-manager.</p><p>At the end of this visit, click on one of them to find out more.</p>"
|
||||
about:
|
||||
title: "About"
|
||||
content: "A page that you can fully customize, to present your activity and your structure."
|
||||
notifications:
|
||||
title: "Notifications center"
|
||||
content: "<p>Every time something important happens (reservations, creation of accounts, activity of your members, etc.), you will be notified here.</p><p>Your members also receive notifications there.</p>"
|
||||
profile:
|
||||
title: "User's menu"
|
||||
content: "<p>Find your personal information here as well as all your activity on Fab-manager.</p><p>This space is also available for all your members.</p>"
|
||||
news:
|
||||
title: "News"
|
||||
content: "<p>This space allows you to display the latest news from your structure.</p><p>You can easily change its content from [Customization]> [Home page].</p>"
|
||||
last_projects:
|
||||
title: "Last projects"
|
||||
content: "<p>This carousel scrolls through the latest projects documented by your members.</p>"
|
||||
last_tweet:
|
||||
title: "Last tweet"
|
||||
content: "<p>Le dernier tweet de votre flux Twitter peut s'afficher ici.</p><p>Configure it from [Customization]> [Home page].</p>"
|
||||
last_members:
|
||||
title: "Last members"
|
||||
content: "The last registered members who have validated their address and agreed to be contacted will be shown here."
|
||||
next_events:
|
||||
title: "Upcoming events"
|
||||
content: "The next three scheduled events are displayed in this space."
|
||||
customize:
|
||||
title: "Customize the home page"
|
||||
content: "<p>This page can be fully personalized.</p><p>You can <a href='mailto:contact@fab-manager.com'>contact-us</a> to make a tailored customization of the home page.</p>"
|
||||
version:
|
||||
title: "Application version"
|
||||
content: "Hover your cursor over this icon to find out the version of Fab-manager. If you are not up to date, this will be reported here and you'll be able to get details by clicking on it."
|
||||
machines:
|
||||
welcome:
|
||||
title: "Machines"
|
||||
content: "<p>Machines are the tools available for your users. You must create here the machines which can then be reserved by the members.</p><p>You can also create entries for non-bookable or free access machines, then you just need to not associate availability slots with them.</p>"
|
||||
view:
|
||||
title: "View"
|
||||
content: "To modify or delete a machine, click here first. You will not be able to delete a machine that has already been associated with availability slots, but you can deactivate it."
|
||||
spaces:
|
||||
welcome:
|
||||
title: "Spaces"
|
||||
content: "<p>Spaces are places available for your users. For example, a meeting room or a woodshop. You must create here the spaces which can then be reserved by members.</p><p>The specificity of the spaces is that they can be reserved by several users at the same time.</p>"
|
||||
view:
|
||||
title: "View"
|
||||
content: "To modify or delete a space, click here first. You will not be able to delete a space that has already been associated with availability slots, but you can deactivate it."
|
||||
|
@ -2,16 +2,18 @@ es:
|
||||
app:
|
||||
public:
|
||||
common:
|
||||
#header and "about" page
|
||||
# header and "about" page
|
||||
about_the_fablab: "Acerca de {GENDER, select, male{el} female{la} neutral{} other{las}} {NAME}"
|
||||
return: "Volver"
|
||||
#cookies
|
||||
|
||||
# cookies
|
||||
cookies:
|
||||
about_cookies: "Este sitio web utiliza cookies para medir la audiencia."
|
||||
learn_more: "Saber más"
|
||||
accept: "Aceptar cookies"
|
||||
decline: "Rechazar"
|
||||
#dashboard sections
|
||||
|
||||
# dashboard sections
|
||||
dashboard: "Panel"
|
||||
my_profile: "My Perfil"
|
||||
my_settings: "Mis ajustes"
|
||||
@ -20,15 +22,21 @@ es:
|
||||
my_events: "Mis eventos"
|
||||
my_invoices: "Mis facturas"
|
||||
my_wallet: "Mi cartera"
|
||||
#login/logout
|
||||
|
||||
# contextual help
|
||||
help: "Help"
|
||||
|
||||
# login/logout
|
||||
sign_out: "Salir"
|
||||
sign_up: "Registrarse"
|
||||
sign_in: "Ingresar"
|
||||
#left menu
|
||||
|
||||
# left menu
|
||||
notifications: "Notificaciones"
|
||||
admin: "Administrador"
|
||||
reduce_panel: "Reducir panel"
|
||||
#left menu (public)
|
||||
|
||||
# left menu (public)
|
||||
home: "Menú principal"
|
||||
reserve_a_machine: "Reservar una máquina"
|
||||
trainings_registrations: "Registro de cursos"
|
||||
@ -36,21 +44,23 @@ es:
|
||||
reserve_a_space: "Reservar un espacio"
|
||||
projects_gallery: "Galería de proyectos"
|
||||
subscriptions: "Suscripciones"
|
||||
public_calendar: "Calendario"
|
||||
#left menu (admin)
|
||||
trainings_monitoring: "Monitorización de cursos"
|
||||
manage_the_calendar: "Gestionar calendario"
|
||||
manage_the_users: "Gestionar usuarios"
|
||||
manage_the_invoices: "Gestionar facturas"
|
||||
public_calendar: "Agenda"
|
||||
|
||||
# left menu (admin)
|
||||
trainings_monitoring: "Cursos"
|
||||
manage_the_calendar: "Agenda"
|
||||
manage_the_users: "Usuarios"
|
||||
manage_the_invoices: "Facturas"
|
||||
subscriptions_and_prices: "Suscripciones y precios"
|
||||
manage_the_events: "Gestionar eventos"
|
||||
manage_the_machines: "Gestionar máquinas"
|
||||
manage_the_spaces: "Gestionar espacios"
|
||||
manage_the_projects_elements: "Gestionar los elementos de los proyectos"
|
||||
manage_the_events: "Eventos"
|
||||
manage_the_machines: "Máquinas"
|
||||
manage_the_spaces: "Espacios"
|
||||
manage_the_projects_elements: "Proyectos"
|
||||
statistics: "Estadísticas"
|
||||
customization: "Customización"
|
||||
open_api_clients: "Clientes OpenAPI"
|
||||
#account creation modal
|
||||
|
||||
# account creation modal
|
||||
create_your_account: "Crear su cuenta"
|
||||
man: "Hombre"
|
||||
woman: "Mujer"
|
||||
@ -92,11 +102,13 @@ es:
|
||||
used_for_profile: "This data will only be displayed on your profile"
|
||||
public_profile: "You will have a public profile and other users will be able to associate you in their projects"
|
||||
you_will_receive_confirmation_instructions_by_email_detailed: "Recibirá un correo electrónico con instrucciones sobre cómo confirmar su cuenta en unos minutos."
|
||||
|
||||
# password modification modal
|
||||
change_your_password: "Cambiar contraseña"
|
||||
your_new_password: "Nueva contraseña"
|
||||
your_password_was_successfully_changed: "Su contraseña ha sido cambiada con éxito."
|
||||
#connection modal
|
||||
|
||||
# connection modal
|
||||
connection: "Conexión"
|
||||
password_forgotten: "¿Ha olvidado su contraseña?"
|
||||
confirm_my_account: "Confirmar mi E-mail"
|
||||
@ -104,41 +116,49 @@ es:
|
||||
create_an_account: "Crear una cuenta"
|
||||
wrong_email_or_password: "E-mail o contraseña incorrecta."
|
||||
caps_lock_is_on: "Las mayusculas están activadas."
|
||||
|
||||
# confirmation modal
|
||||
you_will_receive_confirmation_instructions_by_email: "Recibirá las instrucciones de confirmación por email."
|
||||
|
||||
# forgotten password modal
|
||||
your_email_address_is_unknown: "Se desconoce su email."
|
||||
you_will_receive_in_a_moment_an_email_with_instructions_to_reset_your_password: "En un momento recibirá las instrucciones para restablecer su contraseña en su mail."
|
||||
#Fab-manager's version
|
||||
|
||||
# Fab-manager's version
|
||||
version: "Version:"
|
||||
upgrade_fabmanager: "Upgrade Fab-Manager"
|
||||
current_version: "You are currently using version {VERSION} of Fab-Manager."
|
||||
upgrade_fabmanager: "Upgrade Fab-manager"
|
||||
current_version: "You are currently using version {VERSION} of Fab-manager."
|
||||
upgrade_to: "A new release is available. You can upgrade up to version {VERSION}."
|
||||
read_more: "View the details of this release"
|
||||
security_version_html: "<strong>Your current version is vulnerable!</strong><br> A later version, currently available, includes security fixes. Upgrade as soon as possible!"
|
||||
how_to: "How to upgrade?"
|
||||
|
||||
# Notifications
|
||||
and_NUMBER_other_notifications: "y {NUMBER, plural, =0{no other notifications} =1{one other notification} otras{{NUMBER} other notifications}}..."
|
||||
|
||||
about:
|
||||
#about page
|
||||
read_the_fablab_policy: "Leer la politica del FabLab"
|
||||
read_the_fablab_s_general_terms_and_conditions: "Leer los terminos y condiciones del FabLab"
|
||||
your_fablab_s_contacts: "Sus contactos del FabLab"
|
||||
privacy_policy: "Política de privacidad"
|
||||
|
||||
privacy:
|
||||
#'privacy policy' page
|
||||
title: "Política de privacidad"
|
||||
dpo: "Oficial de protección de datos"
|
||||
last_update: "Última actualización,"
|
||||
|
||||
home:
|
||||
#home page
|
||||
# home page
|
||||
latest_documented_projects: "Los últimos proyectos documentados"
|
||||
follow_us: "Siguenos"
|
||||
latest_tweets: "Los últimos tweets"
|
||||
latest_registered_members: "Miembros más recientes"
|
||||
create_an_account: "Crear una cuenta"
|
||||
discover_members: "Descubrir miembros"
|
||||
#next events summary on the home page
|
||||
|
||||
# next events summary on the home page
|
||||
fablab_s_next_events: "Próximos eventos del FabLab"
|
||||
every_events: "Todos los eventos"
|
||||
from_date_to_date: "Desde {START} hasta {END}"
|
||||
@ -149,8 +169,9 @@ es:
|
||||
full_price: "Precio final"
|
||||
event_full: "Evento lleno"
|
||||
still_available: "Available place(s)"
|
||||
|
||||
projects_list:
|
||||
#projects gallery
|
||||
# projects gallery
|
||||
the_fablab_projects: "Los proyectos del FabLab"
|
||||
add_a_project: "Añadir un proyecto"
|
||||
search_over_the_whole_network: "Buscar en toda la red de FabLab"
|
||||
@ -167,8 +188,9 @@ es:
|
||||
all_materials: "Todo el material"
|
||||
load_next_projects: "Cargar más proyectos"
|
||||
rough_draft: "Borrador"
|
||||
|
||||
projects_show:
|
||||
#details of a projet
|
||||
# details of a projet
|
||||
rough_draft: "Draft"
|
||||
project_description: "Descripción de proyecto"
|
||||
by_name: "Por {NAME}"
|
||||
@ -196,17 +218,20 @@ es:
|
||||
message_is_required: "El mensaje es obligatorio."
|
||||
report: "Reportar"
|
||||
do_you_really_want_to_delete_this_project: "¿Está seguro de querer eliminar este proyecto?"
|
||||
|
||||
machines_list:
|
||||
#list of machines
|
||||
# list of machines
|
||||
the_fablab_s_machines: "Las máquinas del FabLab"
|
||||
add_a_machine: "Añadir una máquina"
|
||||
new_availability: "Open reservations"
|
||||
book: "Reservar"
|
||||
_or_the_: " o el "
|
||||
status_enabled: "Activas"
|
||||
status_disabled: "No activas"
|
||||
status_all: "Todas"
|
||||
|
||||
machines_show:
|
||||
#details of a machine
|
||||
# details of a machine
|
||||
book_this_machine: "Alquilar máquina"
|
||||
technical_specifications: "Technical specifications"
|
||||
files_to_download: "Archivos a descargar"
|
||||
@ -216,19 +241,22 @@ es:
|
||||
do_you_really_want_to_delete_this_machine: "¿Está seguro de querer eliminar esta máquina?"
|
||||
unauthorized_operation: "Unauthorized operation"
|
||||
the_machine_cant_be_deleted_because_it_is_already_reserved_by_some_users: "La máquina no puede borrarse porque está siendo usada o ha sido reservada por algún usuario."
|
||||
|
||||
trainings_list:
|
||||
#list of trainings
|
||||
# list of trainings
|
||||
book: "Reservar"
|
||||
the_trainings: "Lista de cursos"
|
||||
|
||||
training_show:
|
||||
#details of a training
|
||||
# details of a training
|
||||
book_this_training: "reservar plaza en este curso"
|
||||
do_you_really_want_to_delete_this_training: "Está seguro de querer eliminar este curso?"
|
||||
unauthorized_operation: "Operación no autorizada"
|
||||
confirmation_required: "Confirmation required"
|
||||
the_training_cant_be_deleted_because_it_is_already_reserved_by_some_users: "El curso no puede borrarse porque ya ha sido reservado por algún usuario."
|
||||
|
||||
plans:
|
||||
#summary of the subscriptions
|
||||
# summary of the subscriptions
|
||||
subcriptions: "Suscripciones"
|
||||
i_choose_that_plan: "Elijo este plan"
|
||||
i_subscribe_online: "Suscribirme online"
|
||||
@ -256,8 +284,9 @@ es:
|
||||
here_is_the_NAME_subscription_summary: "Resumen de la suscrpición de {NAME}:"
|
||||
confirm_payment_of_html: "{ROLE, select, admin{Cash} other{Pay}}: {AMOUNT}" #(contexte : validate a payment of $20,00)
|
||||
online_payment_disabled: "Payment by credit card is not available. Please contact the Fablab's reception directly."
|
||||
|
||||
events_list:
|
||||
#Fablab's events list
|
||||
# Fablab's events list
|
||||
the_fablab_s_events: "Los eventos del FabLab"
|
||||
all_categories: "Todas las categorías"
|
||||
for_all: "Para todo"
|
||||
@ -269,9 +298,11 @@ es:
|
||||
add_an_event: "Add an event"
|
||||
load_the_next_events: "Cargar los próximos eventos..."
|
||||
full_price_: "Full price:"
|
||||
to_date: '"to"'
|
||||
to_date: "to" # eg. from 01/01 to 01/05
|
||||
all_themes: "All themes"
|
||||
|
||||
events_show:
|
||||
#details and booking of an event
|
||||
# details and booking of an event
|
||||
event_description: "Descripción del evento"
|
||||
downloadable_documents: "Archivos descargables"
|
||||
information_and_booking: "Información y reservas"
|
||||
@ -280,8 +311,8 @@ es:
|
||||
ending: "Termina:"
|
||||
opening_hours: "Hora de apertura:"
|
||||
all_day: "All day"
|
||||
from_time: '"From"'
|
||||
to_time: '"to"'
|
||||
from_time: "From" # eg. from 18:00 to 21:00
|
||||
to_time: "to" # eg. from 18:00 to 21:00
|
||||
full_price_: "Full price:"
|
||||
tickets_still_availables: "Entradas disponibles:"
|
||||
sold_out: "Entradas vendidas."
|
||||
@ -320,8 +351,9 @@ es:
|
||||
view_event_list: "View events to come"
|
||||
share_on_facebook: "Share on Facebook"
|
||||
share_on_twitter: "Share on Twitter"
|
||||
|
||||
calendar:
|
||||
#public calendar
|
||||
# public calendar
|
||||
calendar: "Calendario"
|
||||
show_unavailables: "Mostrar campos inválidos"
|
||||
filter_calendar: "Filtrar calendario"
|
||||
@ -330,16 +362,19 @@ es:
|
||||
spaces: "Espacios"
|
||||
events: "Eventos"
|
||||
externals: "Otros calendarios"
|
||||
|
||||
spaces_list:
|
||||
#list of spaces
|
||||
# list of spaces
|
||||
the_spaces: "Espacios"
|
||||
new_availability: "Open reservations"
|
||||
add_a_space: "Añadir espacios"
|
||||
status_enabled: "Activos"
|
||||
status_disabled: "No activos"
|
||||
status_all: "Todos"
|
||||
book: "Reservar"
|
||||
|
||||
space_show:
|
||||
#display the details of a space
|
||||
# display the details of a space
|
||||
book_this_space: "Reservar este espacio"
|
||||
unauthorized_operation: "Operación no autorizada"
|
||||
confirmation_required: "Confirmación requerida"
|
||||
@ -348,3 +383,83 @@ es:
|
||||
characteristics: "Características"
|
||||
files_to_download: "Archivos para descargar"
|
||||
projects_using_the_space: "Proyectos que usan el espacio"
|
||||
|
||||
tour:
|
||||
conclusion:
|
||||
title: "Thank you for your attention"
|
||||
content: "<p>If you want to restart this contextual help, press <strong>F1</strong> at any time or click on [? Help] from the user's menu.</p><p>If you need additional help, you can <a href='https://github.com/sleede/fab-manager/raw/master/doc/fr/guide_utilisation_fab_manager_v4.2.pdf' target='_blank'>check the user guide</a> (only in French for now).</p><p>The Fab-manager's team also provides personalized support (help with getting started, help with installation, customization, etc.), <a href='mailto:contact@fab-manager.com'>contact-us</a> for more info.</p>"
|
||||
welcome:
|
||||
welcome:
|
||||
title: "Welcome to Fab-manager"
|
||||
content: "To help you get started with the application, we are going to take a quick tour of the features."
|
||||
home:
|
||||
title: "Home page"
|
||||
content: "Clicking here will take you back to the home page where you are currently."
|
||||
machines:
|
||||
title: "Machines"
|
||||
content: "<p>This page will allow you to consult the list of all machines and reserve a slot on behalf of a member.</p><p>A machine can be, for example, a 3D printer.</p><p>Members can also access this page and reserve a machine themselves, if credit card payment is enabled, or if some prices are equal to 0.</p>"
|
||||
trainings:
|
||||
title: "Trainings"
|
||||
content: "<p>This page will allow you to consult the list of all training sessions and to register a member for a training session.</p><p>Certaines formations peuvent être un préalable à la réservation de certaines machines.</p><p>Members can also access this page and register for a training session themselves, if credit card payment is enabled, or if some prices are equal to 0.</p>"
|
||||
spaces:
|
||||
title: "Spaces"
|
||||
content: "<p>This page will allow you to consult the list of all available spaces and to reserve a place on a slot, on behalf of a member.</p><p>A space can be, for example, a woodshop or a meeting room.</p><p>Their particularity is that they can be booked by several people at the same time.</p><p>Members can also access this page and reserve a machine themselves, if credit card payment is enabled, or if some prices are equal to 0.</p>"
|
||||
events:
|
||||
title: "Events"
|
||||
content: "<p>An open house evening or an internship to make your desk lamp? It's over here!</p><p>Events can be free or paid (with different prices), with or without reservation.</p><p>Again, members can access this page and book themselves places for free events, or paid events if credit card payment is enabled.</p>"
|
||||
calendar:
|
||||
title: "Agenda"
|
||||
content: "Visualize at a glance everything that is scheduled for the next coming weeks (events, training, machines available, etc.)."
|
||||
projects:
|
||||
title: "Projects"
|
||||
content: "<p>Document and share all your creations with the community.</p><p>If you use OpenLab, you will also be able to consult the projects of the entire Fab-Manager network. <a href='mailto:contact@fab-manager.com'>Contact-us</a> to get your access, it's free!</p>"
|
||||
plans:
|
||||
title: "Subscriptions"
|
||||
content: "Subscriptions provide a way to segment your prices and provide benefits to regular users."
|
||||
admin:
|
||||
title: "Administrator section"
|
||||
content: "<p>All of the elements below are only accessible to administrators. They allow you to manage and configure Fab-manager.</p><p>At the end of this visit, click on one of them to find out more.</p>"
|
||||
about:
|
||||
title: "About"
|
||||
content: "A page that you can fully customize, to present your activity and your structure."
|
||||
notifications:
|
||||
title: "Notifications center"
|
||||
content: "<p>Every time something important happens (reservations, creation of accounts, activity of your members, etc.), you will be notified here.</p><p>Your members also receive notifications there.</p>"
|
||||
profile:
|
||||
title: "User's menu"
|
||||
content: "<p>Find your personal information here as well as all your activity on Fab-manager.</p><p>This space is also available for all your members.</p>"
|
||||
news:
|
||||
title: "News"
|
||||
content: "<p>This space allows you to display the latest news from your structure.</p><p>You can easily change its content from [Customization]> [Home page].</p>"
|
||||
last_projects:
|
||||
title: "Last projects"
|
||||
content: "<p>This carousel scrolls through the latest projects documented by your members.</p>"
|
||||
last_tweet:
|
||||
title: "Last tweet"
|
||||
content: "<p>Le dernier tweet de votre flux Twitter peut s'afficher ici.</p><p>Configure it from [Customization]> [Home page].</p>"
|
||||
last_members:
|
||||
title: "Last members"
|
||||
content: "The last registered members who have validated their address and agreed to be contacted will be shown here."
|
||||
next_events:
|
||||
title: "Upcoming events"
|
||||
content: "The next three scheduled events are displayed in this space."
|
||||
customize:
|
||||
title: "Customize the home page"
|
||||
content: "<p>This page can be fully personalized.</p><p>You can <a href='mailto:contact@fab-manager.com'>contact-us</a> to make a tailored customization of the home page.</p>"
|
||||
version:
|
||||
title: "Application version"
|
||||
content: "Hover your cursor over this icon to find out the version of Fab-manager. If you are not up to date, this will be reported here and you'll be able to get details by clicking on it."
|
||||
machines:
|
||||
welcome:
|
||||
title: "Machines"
|
||||
content: "<p>Machines are the tools available for your users. You must create here the machines which can then be reserved by the members.</p><p>You can also create entries for non-bookable or free access machines, then you just need to not associate availability slots with them.</p>"
|
||||
view:
|
||||
title: "View"
|
||||
content: "To modify or delete a machine, click here first. You will not be able to delete a machine that has already been associated with availability slots, but you can deactivate it."
|
||||
spaces:
|
||||
welcome:
|
||||
title: "Spaces"
|
||||
content: "<p>Spaces are places available for your users. For example, a meeting room or a woodshop. You must create here the spaces which can then be reserved by members.</p><p>The specificity of the spaces is that they can be reserved by several users at the same time.</p>"
|
||||
view:
|
||||
title: "View"
|
||||
content: "To modify or delete a space, click here first. You will not be able to delete a space that has already been associated with availability slots, but you can deactivate it."
|
||||
|
@ -23,6 +23,9 @@ fr:
|
||||
my_invoices: "Mes factures"
|
||||
my_wallet: "Mon porte-monnaie"
|
||||
|
||||
# aide contextuelle
|
||||
help: "Aide"
|
||||
|
||||
# connexion / déconnexion
|
||||
sign_out: "Se déconnecter"
|
||||
sign_up: "S'inscrire"
|
||||
@ -41,18 +44,18 @@ fr:
|
||||
reserve_a_space: "Réserver un espace"
|
||||
projects_gallery: "Galerie de projets"
|
||||
subscriptions: "Abonnements"
|
||||
public_calendar: "Calendrier"
|
||||
public_calendar: "Agenda"
|
||||
|
||||
# menu de gauche (partie admin)
|
||||
trainings_monitoring: "Suivi formations"
|
||||
manage_the_calendar: "Gérer le calendrier"
|
||||
manage_the_users: "Gérer les utilisateurs"
|
||||
manage_the_invoices: "Gérer les factures"
|
||||
trainings_monitoring: "Formations"
|
||||
manage_the_calendar: "Agenda"
|
||||
manage_the_users: "Utilisateurs"
|
||||
manage_the_invoices: "Factures"
|
||||
subscriptions_and_prices: "Abonnements & Tarifs"
|
||||
manage_the_events: "Gérer les évènements"
|
||||
manage_the_machines: "Gérer les machines"
|
||||
manage_the_spaces: "Gérer les espaces"
|
||||
manage_the_projects_elements: "Gérer les éléments projets"
|
||||
manage_the_events: "Évènements"
|
||||
manage_the_machines: "Machines"
|
||||
manage_the_spaces: "Espaces"
|
||||
manage_the_projects_elements: "Projets"
|
||||
statistics: "Statistiques"
|
||||
customization: "Personnalisation"
|
||||
open_api_clients: "Clients OpenAPI"
|
||||
@ -123,8 +126,8 @@ fr:
|
||||
|
||||
# Fab-manager's version
|
||||
version: "Version :"
|
||||
upgrade_fabmanager: "Mettez à jour Fab-Manager"
|
||||
current_version: "Vous utilisez actuellement la version {VERSION} de Fab-Manager."
|
||||
upgrade_fabmanager: "Mettez à jour Fab-manager"
|
||||
current_version: "Vous utilisez actuellement la version {VERSION} de Fab-manager."
|
||||
upgrade_to: "Une nouvelle version est disponible. Vous pouvez mettre à jour vers la version {VERSION}."
|
||||
read_more: "Voir les détails de cette version"
|
||||
security_version_html: "<strong>Votre version actuelle est vulnérable !</strong><br> Une version ultérieure, actuellement disponible, inclut des correctifs de sécurité. Mettez à jour dès que possible !"
|
||||
@ -171,7 +174,7 @@ fr:
|
||||
# galerie des projets
|
||||
the_fablab_projects: "Les projets du FabLab"
|
||||
add_a_project: "Ajouter un projet"
|
||||
search_over_the_whole_network: "Chercher sur tout le réseau Fab Manager"
|
||||
search_over_the_whole_network: "Chercher sur tout le réseau Fab-manager"
|
||||
tooltip_openlab_projects_switch: "La recherche sur tout le réseau vous permet de rechercher parmis les projets de tous les Fab-managers utilisant cette fonctionnalité !"
|
||||
openlab_search_not_available_at_the_moment: "La recherche sur tout le réseau n'est pas disponible pour le moment. Vous pouvez cependant effectuer une recherche parmis les projets de cette plateforme."
|
||||
project_search_result_is_empty: "Il n'y a pas de projets correspondant à vos critères de recherche."
|
||||
@ -220,6 +223,7 @@ fr:
|
||||
# liste des machines
|
||||
the_fablab_s_machines: "Les machines du FabLab"
|
||||
add_a_machine: "Ajouter une machine"
|
||||
new_availability: "Ouvrir des réservations"
|
||||
book: "Réserver"
|
||||
_or_the_: " ou la "
|
||||
status_enabled: "Actives"
|
||||
@ -294,7 +298,8 @@ fr:
|
||||
add_an_event: "Ajouter un évènement"
|
||||
load_the_next_events: "Charger les évènements suivants..."
|
||||
full_price_: "Plein tarif :"
|
||||
to_date: "au" # context: date. eg: 'from 01/01 to 01/05'
|
||||
to_date: "au" # eg. from 01/01 to 01/05
|
||||
all_themes: "Toutes les thématiques"
|
||||
|
||||
events_show:
|
||||
# détails d'un événement et réservation
|
||||
@ -306,8 +311,8 @@ fr:
|
||||
ending: "Fin :"
|
||||
opening_hours: "Horaires :"
|
||||
all_day: "Toute la journée"
|
||||
from_time: "De" # context: time. eg. 'from 18:00 to 21:00'
|
||||
to_time: "à" # context: time. eg. 'from 18:00 to 21:00'
|
||||
from_time: "De" # eg. from 18:00 to 21:00
|
||||
to_time: "à" # eg. from 18:00 to 21:00
|
||||
full_price_: "Plein tarif :"
|
||||
tickets_still_availables: "Places encore disponibles :"
|
||||
sold_out: "Événement complet"
|
||||
@ -361,6 +366,7 @@ fr:
|
||||
spaces_list:
|
||||
# liste des espaces
|
||||
the_spaces: "Les espaces"
|
||||
new_availability: "Ouvrir des réservations"
|
||||
add_a_space: "Ajouter un espace"
|
||||
status_enabled: "Activés"
|
||||
status_disabled: "Désactivés"
|
||||
@ -377,3 +383,83 @@ fr:
|
||||
characteristics: "Caractéristiques"
|
||||
files_to_download: "Fichiers à télécharger"
|
||||
projects_using_the_space: "Projets utilisant l'espace"
|
||||
|
||||
tour:
|
||||
conclusion:
|
||||
title: "Merci de votre attention"
|
||||
content: "<p>Si vous souhaitez relancer cette aide contextuelle, appuyez sur <strong>F1</strong> à n'importe quel moment ou cliquez sur [? Aide] depuis le menu utilisateur.</p><p>Si vous avez besoin d'aide supplémentaire, vous pouvez <a href='https://github.com/sleede/fab-manager/raw/master/doc/fr/guide_utilisation_fab_manager_v4.2.pdf' target='_blank'>consulter le guide d'utilisation</a> disponible en Français.</p><p>L'équipe de Fab-manager propose également du support personnalisé (aide à la prise en main, aide à l'installation, personnalisation, etc.), <a href='mailto:contact@fab-manager.com'>contactez-nous</a> pour plus d'informations.</p>"
|
||||
welcome:
|
||||
welcome:
|
||||
title: "Bienvenue dans Fab-manager"
|
||||
content: "Afin de vous aider à bien prendre en main l'application, nous allons procéder à une rapide visite guidée des fonctionnalités."
|
||||
home:
|
||||
title: "Page d'accueil"
|
||||
content: "Un clic ici vous ramènera vers la page d'accueil où vous vous situez actuellement."
|
||||
machines:
|
||||
title: "Machines"
|
||||
content: "<p>Cette page vous permettra de consulter la liste de toutes les machines et réserver un créneau pour le compte d'un membre.</p><p>Une machine peut-être, par exemple, une imprimante 3D.</p><p>Les membres peuvent également accéder à cette page et, si le paiement par carte bancaire est activé, ou que certains prix sont à 0, réserver eux-même une machine.</p>"
|
||||
trainings:
|
||||
title: "Formations"
|
||||
content: "<p>Cette page vous permettra de consulter la liste de toutes les formations et d'inscrire un membre à une session de formation.</p><p>Certaines formations peuvent être un préalable à la réservation de certaines machines.</p><p>Les membres peuvent également accéder à cette page et, si le paiement par carte bancaire est activé, ou que certains prix sont à 0, s'inscrire eux-même une session de formation.</p>"
|
||||
spaces:
|
||||
title: "Espaces"
|
||||
content: "<p>Cette page vous permettra de consulter la liste de tous les espaces disponibles et de réserver une place sur un créneau, pour le compte d'un membre.</p><p>Un espace peut-être, par exemple, un atelier bois ou une salle de réunion.</p><p>Leur particularité est qu'ils peuvent être réservés par plusieurs personnes en même temps.</p><p>Les membres peuvent également accéder à cette page et, si le paiement par carte bancaire est activé, ou que certains prix sont à 0, réserver eux-même une place.</p>"
|
||||
events:
|
||||
title: "Évènements"
|
||||
content: "<p>Une soirée porte ouverte ou un stage pour fabriquer sa lampe de bureau ? C'est par ici !</p><p>Les évènements peuvent être gratuits ou payants (avec plusieurs tarifs), avec ou sans réservation.</p><p>Ici encore, les membres peuvent accéder à cette page et réserver eux-mêmes des places pour des évènements gratuits, ou payants si le paiement par carte bancaire est activé.</p>"
|
||||
calendar:
|
||||
title: "Agenda"
|
||||
content: "Visualisez en un clin d'oeil tout ce qui est prévu au programme des prochaines semaines (évènements, formations, machines disponibles, etc.)."
|
||||
projects:
|
||||
title: "Projets"
|
||||
content: "<p>Documentez et partagez toutes vos réalisations avec la communauté.</p><p>Si vous utilisez OpenLab, vous pourrez également consulter les projets de l'ensemble du réseau Fab-Manager. <a href='mailto:contact@fab-manager.com'>Contactez-nous</a> pour obtenir votre accès, c'est gratuit !</p>"
|
||||
plans:
|
||||
title: "Abonnements"
|
||||
content: "Les abonnements offrent un moyen de segmenter vos tarifs et d'accorder des avantages aux utilisateurs réguliers."
|
||||
admin:
|
||||
title: "Section administrateur"
|
||||
content: "<p>L'ensemble des éléments ci-dessous ne sont accessibles qu'aux administrateurs. Ils permettent de gérer et de configurer Fab-manager.</p><p>À la fin de cette visite, cliquez sur l'un d'entre eux pour en savoir plus.</p>"
|
||||
about:
|
||||
title: "À propos"
|
||||
content: "Une page que vous pouvez entièrement personnaliser, pour y présenter votre activité et votre structure."
|
||||
notifications:
|
||||
title: "Centre de notifications"
|
||||
content: "<p>Chaque fois qu'il se passe quelque chose d'important (réservations, création de comptes, activité de vos membres, etc.), vous serez notifié ici.</p><p>Vos membres reçoivent également des notifications à cet endroit.</p>"
|
||||
profile:
|
||||
title: "Menu utilisateur"
|
||||
content: "<p>Retrouvez ici vos informations personnelles ainsi que toute votre activité sur Fab-manager.</p><p>Cet espace est également disponible pour tous vos membres.</p>"
|
||||
news:
|
||||
title: "Les brèves"
|
||||
content: "<p>Cet espace vous permet d'afficher les dernières actualités de votre structure.</p><p>Vous pouvez facilement changer son contenu depuis [Personnalisation] > [Page d'accueil].</p>"
|
||||
last_projects:
|
||||
title: "les derniers projets"
|
||||
content: "<p>Ce carousel fait défiler les derniers projets documentés par vos membres.</p>"
|
||||
last_tweet:
|
||||
title: "Dernier tweet"
|
||||
content: "<p>Le dernier tweet de votre flux Twitter peut s'afficher ici.</p><p>Configurez-le depuis [Personnalisation] > [Page d'accueil].</p>"
|
||||
last_members:
|
||||
title: "Derniers membres"
|
||||
content: "Les derniers membres inscrits qui ont validé leur adresse et accepté d'être contactés, seront affichés ici."
|
||||
next_events:
|
||||
title: "Prochains évènements"
|
||||
content: "Les trois prochains évènements programmés sont affichés dans cette espace."
|
||||
customize:
|
||||
title: "Personnalisez la page d'accueil"
|
||||
content: "<p>Cette page peut être entièrement personnalisée.</p><p>Vous pouvez <a href='mailto:contact@fab-manager.com'>nous contactez</a> pour réaliser une personnalisation sur mesure de la page d'accueil.</p>"
|
||||
version:
|
||||
title: "Version de l'application"
|
||||
content: "Passez votre curseur sur cette icône pour connaître la version de Fab-manager. Si vous n'êtes pas à jour, cela vous sera signalé ici et vous pourrez alors obtenir des détails en cliquant dessus."
|
||||
machines:
|
||||
welcome:
|
||||
title: "Machines"
|
||||
content: "<p>Les machines sont les outils que vous mettez à disposition de vos utilisateurs. Vous devez créer ici les machines qui pourront ensuite être réservées par les membres.</p><p>Vous pouvez également créer des entrées pour des machines non réservables ou en libre accès, il vous suffira ensuite de ne pas associer de créneaux de disponibilités à celles-ci.</p>"
|
||||
view:
|
||||
title: "Consulter"
|
||||
content: "Pour modifier ou supprimer une machine, cliquez tout d'abord ici. Vous ne pourrez pas supprimer une machine qui a déjà été associée à des créneaux de disponibilité, mais vous pourrez la désactiver."
|
||||
spaces:
|
||||
welcome:
|
||||
title: "Espaces"
|
||||
content: "<p>Les espaces sont des lieux que vous mettez à disposition de vos utilisateurs. Par exemple, une salle de réunion ou un atelier bois. Vous devez créer ici les espaces qui pourront ensuite être réservées par les membres.</p><p>La spécificité des espaces est qu'ils peuvent être réservés par plusieurs utilisateurs en même temps.</p>"
|
||||
view:
|
||||
title: "Consulter"
|
||||
content: "Pour modifier ou supprimer un espace, cliquez tout d'abord ici. Vous ne pourrez pas supprimer un espace qui a déjà été associée à des créneaux de disponibilité, mais vous pourrez le désactiver."
|
||||
|
@ -23,6 +23,9 @@ pt:
|
||||
my_invoices: "Minhas Contas"
|
||||
my_wallet: "Minha Carteira"
|
||||
|
||||
# contextual help
|
||||
help: "Help"
|
||||
|
||||
# login/logout
|
||||
sign_out: "Sair"
|
||||
sign_up: "Cadastrar"
|
||||
@ -41,18 +44,18 @@ pt:
|
||||
reserve_a_space: "Reserva de espaço"
|
||||
projects_gallery: "Galeria de Projetos"
|
||||
subscriptions: "Assinaturas"
|
||||
public_calendar: "Calendário"
|
||||
public_calendar: "Agenda"
|
||||
|
||||
# left menu (admin)
|
||||
trainings_monitoring: "Treinamentos"
|
||||
manage_the_calendar: "Gerenciar calendário"
|
||||
manage_the_users: "Gerenciar usuários"
|
||||
manage_the_invoices: "Gerenciar contas"
|
||||
manage_the_calendar: "Agenda"
|
||||
manage_the_users: "Uusuários"
|
||||
manage_the_invoices: "Contas"
|
||||
subscriptions_and_prices: "Assinaturas e Preços"
|
||||
manage_the_events: "Gerenciar eventos"
|
||||
manage_the_machines: "Gerenciar Máquinas"
|
||||
manage_the_spaces: "Gerenciar espaços"
|
||||
manage_the_projects_elements: "Gerenciar Elementos de Projeto"
|
||||
manage_the_events: "Eventos"
|
||||
manage_the_machines: "Máquinas"
|
||||
manage_the_spaces: "Espaços"
|
||||
manage_the_projects_elements: "Projeto"
|
||||
statistics: "Estatísticas"
|
||||
customization: "Customizações"
|
||||
open_api_clients: "OpenAPI clients"
|
||||
@ -123,8 +126,8 @@ pt:
|
||||
|
||||
# Fab-manager's version
|
||||
version: "Versão:"
|
||||
upgrade_fabmanager: "Upgrade Fab-Manager"
|
||||
current_version: "You are currently using version {VERSION} of Fab-Manager."
|
||||
upgrade_fabmanager: "Upgrade Fab-manager"
|
||||
current_version: "You are currently using version {VERSION} of Fab-manager."
|
||||
upgrade_to: "A new release is available. You can upgrade up to version {VERSION}."
|
||||
read_more: "View the details of this release"
|
||||
security_version_html: "<strong>Your current version is vulnerable!</strong><br> A later version, currently available, includes security fixes. Upgrade as soon as possible!"
|
||||
@ -220,6 +223,7 @@ pt:
|
||||
# list of machines
|
||||
the_fablab_s_machines: "Lista de máquinas no FabLab"
|
||||
add_a_machine: "Adicionar uma máquina"
|
||||
new_availability: "Open reservations"
|
||||
book: "Reservar"
|
||||
_or_the_: " ou o "
|
||||
status_enabled: "Ativo"
|
||||
@ -294,7 +298,8 @@ pt:
|
||||
add_an_event: "Add an event"
|
||||
load_the_next_events: "Load the next events..."
|
||||
full_price_: "Full price:"
|
||||
to_date: "to" # context: date. eg: 'from 01/01 to 01/05'
|
||||
to_date: "to" # eg. from 01/01 to 01/05
|
||||
all_themes: "All themes"
|
||||
|
||||
events_show:
|
||||
# details and booking of an event
|
||||
@ -306,8 +311,8 @@ pt:
|
||||
ending: "Término:"
|
||||
opening_hours: "Abre ás:"
|
||||
all_day: "All day"
|
||||
from_time: "From" # context: time. eg. 'from 18:00 to 21:00'
|
||||
to_time: "to" # context: time. eg. 'from 18:00 to 21:00'
|
||||
from_time: "From" # eg. from 18:00 to 21:00
|
||||
to_time: "to" # eg. from 18:00 to 21:00
|
||||
full_price_: "Full price:"
|
||||
tickets_still_availables: "Tickets ainda disponíveis:"
|
||||
sold_out: "Esgotado."
|
||||
@ -361,6 +366,7 @@ pt:
|
||||
spaces_list:
|
||||
# list of spaces
|
||||
the_spaces: "Os espaços"
|
||||
new_availability: "Open reservations"
|
||||
add_a_space: "Adicionar espaço"
|
||||
status_enabled: "Ativo"
|
||||
status_disabled: "Desabilitado"
|
||||
@ -377,3 +383,83 @@ pt:
|
||||
characteristics: "Características"
|
||||
files_to_download: "Arquivo para download"
|
||||
projects_using_the_space: "Projetos usando espaço"
|
||||
|
||||
tour:
|
||||
conclusion:
|
||||
title: "Thank you for your attention"
|
||||
content: "<p>If you want to restart this contextual help, press <strong>F1</strong> at any time or click on [? Help] from the user's menu.</p><p>If you need additional help, you can <a href='https://github.com/sleede/fab-manager/raw/master/doc/fr/guide_utilisation_fab_manager_v4.2.pdf' target='_blank'>check the user guide</a> (only in French for now).</p><p>The Fab-manager's team also provides personalized support (help with getting started, help with installation, customization, etc.), <a href='mailto:contact@fab-manager.com'>contact-us</a> for more info.</p>"
|
||||
welcome:
|
||||
welcome:
|
||||
title: "Welcome to Fab-manager"
|
||||
content: "To help you get started with the application, we are going to take a quick tour of the features."
|
||||
home:
|
||||
title: "Home page"
|
||||
content: "Clicking here will take you back to the home page where you are currently."
|
||||
machines:
|
||||
title: "Machines"
|
||||
content: "<p>This page will allow you to consult the list of all machines and reserve a slot on behalf of a member.</p><p>A machine can be, for example, a 3D printer.</p><p>Members can also access this page and reserve a machine themselves, if credit card payment is enabled, or if some prices are equal to 0.</p>"
|
||||
trainings:
|
||||
title: "Trainings"
|
||||
content: "<p>This page will allow you to consult the list of all training sessions and to register a member for a training session.</p><p>Certaines formations peuvent être un préalable à la réservation de certaines machines.</p><p>Members can also access this page and register for a training session themselves, if credit card payment is enabled, or if some prices are equal to 0.</p>"
|
||||
spaces:
|
||||
title: "Spaces"
|
||||
content: "<p>This page will allow you to consult the list of all available spaces and to reserve a place on a slot, on behalf of a member.</p><p>A space can be, for example, a woodshop or a meeting room.</p><p>Their particularity is that they can be booked by several people at the same time.</p><p>Members can also access this page and reserve a machine themselves, if credit card payment is enabled, or if some prices are equal to 0.</p>"
|
||||
events:
|
||||
title: "Events"
|
||||
content: "<p>An open house evening or an internship to make your desk lamp? It's over here!</p><p>Events can be free or paid (with different prices), with or without reservation.</p><p>Again, members can access this page and book themselves places for free events, or paid events if credit card payment is enabled.</p>"
|
||||
calendar:
|
||||
title: "Agenda"
|
||||
content: "Visualize at a glance everything that is scheduled for the next coming weeks (events, training, machines available, etc.)."
|
||||
projects:
|
||||
title: "Projects"
|
||||
content: "<p>Document and share all your creations with the community.</p><p>If you use OpenLab, you will also be able to consult the projects of the entire Fab-Manager network. <a href='mailto:contact@fab-manager.com'>Contact-us</a> to get your access, it's free!</p>"
|
||||
plans:
|
||||
title: "Subscriptions"
|
||||
content: "Subscriptions provide a way to segment your prices and provide benefits to regular users."
|
||||
admin:
|
||||
title: "Administrator section"
|
||||
content: "<p>All of the elements below are only accessible to administrators. They allow you to manage and configure Fab-manager.</p><p>At the end of this visit, click on one of them to find out more.</p>"
|
||||
about:
|
||||
title: "About"
|
||||
content: "A page that you can fully customize, to present your activity and your structure."
|
||||
notifications:
|
||||
title: "Notifications center"
|
||||
content: "<p>Every time something important happens (reservations, creation of accounts, activity of your members, etc.), you will be notified here.</p><p>Your members also receive notifications there.</p>"
|
||||
profile:
|
||||
title: "User's menu"
|
||||
content: "<p>Find your personal information here as well as all your activity on Fab-manager.</p><p>This space is also available for all your members.</p>"
|
||||
news:
|
||||
title: "News"
|
||||
content: "<p>This space allows you to display the latest news from your structure.</p><p>You can easily change its content from [Customization]> [Home page].</p>"
|
||||
last_projects:
|
||||
title: "Last projects"
|
||||
content: "<p>This carousel scrolls through the latest projects documented by your members.</p>"
|
||||
last_tweet:
|
||||
title: "Last tweet"
|
||||
content: "<p>Le dernier tweet de votre flux Twitter peut s'afficher ici.</p><p>Configure it from [Customization]> [Home page].</p>"
|
||||
last_members:
|
||||
title: "Last members"
|
||||
content: "The last registered members who have validated their address and agreed to be contacted will be shown here."
|
||||
next_events:
|
||||
title: "Upcoming events"
|
||||
content: "The next three scheduled events are displayed in this space."
|
||||
customize:
|
||||
title: "Customize the home page"
|
||||
content: "<p>This page can be fully personalized.</p><p>You can <a href='mailto:contact@fab-manager.com'>contact-us</a> to make a tailored customization of the home page.</p>"
|
||||
version:
|
||||
title: "Application version"
|
||||
content: "Hover your cursor over this icon to find out the version of Fab-manager. If you are not up to date, this will be reported here and you'll be able to get details by clicking on it."
|
||||
machines:
|
||||
welcome:
|
||||
title: "Machines"
|
||||
content: "<p>Machines are the tools available for your users. You must create here the machines which can then be reserved by the members.</p><p>You can also create entries for non-bookable or free access machines, then you just need to not associate availability slots with them.</p>"
|
||||
view:
|
||||
title: "View"
|
||||
content: "To modify or delete a machine, click here first. You will not be able to delete a machine that has already been associated with availability slots, but you can deactivate it."
|
||||
spaces:
|
||||
welcome:
|
||||
title: "Spaces"
|
||||
content: "<p>Spaces are places available for your users. For example, a meeting room or a woodshop. You must create here the spaces which can then be reserved by members.</p><p>The specificity of the spaces is that they can be reserved by several users at the same time.</p>"
|
||||
view:
|
||||
title: "View"
|
||||
content: "To modify or delete a space, click here first. You will not be able to delete a space that has already been associated with availability slots, but you can deactivate it."
|
||||
|
@ -427,7 +427,7 @@ en:
|
||||
tags_of_the_destination_slot: "Tags of the destination slot:"
|
||||
confirm_my_modification: "Confirm my modification"
|
||||
your_booking_slot_was_successfully_moved_from_: "Your booking slot was successfully moved from"
|
||||
to_date: "to" # context: date. eg: 'from 01/01 to 01/05'
|
||||
to_date: "to" # eg. from 01/01 to 01/05
|
||||
please_select_a_member_first: 'Please select a member first'
|
||||
unable_to_select_plan_if_slots_in_the_past: 'Unable to select a plan if any of the selected slots is in the past'
|
||||
unable_to_change_the_reservation: "Unable to change the reservation"
|
||||
@ -435,7 +435,7 @@ en:
|
||||
do_you_really_want_to_cancel_this_reservation: "Do you really want to cancel this reservation?"
|
||||
reservation_was_cancelled_successfully: "Reservation was cancelled successfully."
|
||||
cancellation_failed: "Cancellation failed."
|
||||
confirm_payment_of_html: "{ROLE, select, admin{Payment on site} other{Pay}}: {AMOUNT}" # (context: confirm my payment of $20.00)
|
||||
confirm_payment_of_html: "{ROLE, select, admin{Payment on site} other{Pay}}: {AMOUNT}" # eg. confirm my payment of $20.00
|
||||
a_problem_occurred_during_the_payment_process_please_try_again_later: "A problem occurred during the payment process. Please try again later."
|
||||
none: "None"
|
||||
online_payment_disabled: "Online payment is not available. Please contact the Fablab reception directly."
|
||||
|
@ -2,7 +2,7 @@ es:
|
||||
app:
|
||||
shared:
|
||||
buttons:
|
||||
#translations of common buttons
|
||||
# translations of common buttons
|
||||
confirm_changes: "Confirmar cambios"
|
||||
consult: "Consultar"
|
||||
edit: "Editar"
|
||||
@ -18,12 +18,14 @@ es:
|
||||
"yes": "Sí"
|
||||
"no": "No"
|
||||
apply: "Aplicar"
|
||||
|
||||
messages:
|
||||
you_will_lose_any_unsaved_modification_if_you_quit_this_page: "Si cierra la página se perderán todas las modificaciones que no se hayan guardado"
|
||||
you_will_lose_any_unsaved_modification_if_you_reload_this_page: "Si recarga la página se perderán todas las modificaciones que no se hayan guardado"
|
||||
payment_card_error: "A problem has occurred with your credit card:"
|
||||
|
||||
user:
|
||||
#user edition form
|
||||
# user edition form
|
||||
man: "Man"
|
||||
woman: "Woman"
|
||||
add_an_avatar: "Añadir un avatar"
|
||||
@ -62,8 +64,9 @@ es:
|
||||
used_for_invoicing: "This data will be used for billing purposes"
|
||||
used_for_reservation: "This data will be used in case of change on one of your bookings"
|
||||
used_for_profile: "This data will only be displayed on your profile"
|
||||
|
||||
project:
|
||||
#project edition form
|
||||
# project edition form
|
||||
name: "Name"
|
||||
name_is_required: "Name is required."
|
||||
illustration: "Ilustración"
|
||||
@ -91,8 +94,9 @@ es:
|
||||
themes: "Themes"
|
||||
tags: "Tags"
|
||||
save_as_draft: "Save as draft"
|
||||
|
||||
machine:
|
||||
#machine edition form
|
||||
# machine edition form
|
||||
name: "Nombre"
|
||||
name_is_required: "Se requiere un nombre."
|
||||
illustration: "Ilustración"
|
||||
@ -106,28 +110,33 @@ es:
|
||||
add_an_attachment: "añadir archivo adjunto"
|
||||
disable_machine: "Disable machine"
|
||||
validate_your_machine: "Validar su máquina"
|
||||
|
||||
plan_subscribe:
|
||||
#frame to select a plan to subscribe
|
||||
# frame to select a plan to subscribe
|
||||
subscribe_online: "suscribirse online"
|
||||
do_not_subscribe: "no suscribe"
|
||||
|
||||
member_select:
|
||||
#admin: choose a member to interact with
|
||||
# admin: choose a member to interact with
|
||||
select_a_member: "Selecciona un miembro"
|
||||
start_typing: "Empezar a escribir..."
|
||||
|
||||
stripe:
|
||||
#stripe payment modal
|
||||
# stripe payment modal
|
||||
online_payment: "Online payment"
|
||||
i_have_read_and_accept_: "He leido y acepto"
|
||||
_the_general_terms_and_conditions: "Los términos y condiciones."
|
||||
credit_amount_for_pay_reservation: "{amount} {currency} falta por pagar para efectuar su reserva"
|
||||
client_credit_amount_for_pay_reservation: "{amount} {currency} falta por pagar para efectuar la reserva del cliente"
|
||||
confirm_payment_of_: "Pay: {AMOUNT}"
|
||||
|
||||
valid_reservation_modal:
|
||||
#dialog of on site payment for reservations
|
||||
booking_confirmation: "Confirmar reserva"
|
||||
here_is_the_summary_of_the_slots_to_book_for_the_current_user: "Resumen de los espacios reservados por el usuario actual:"
|
||||
|
||||
event:
|
||||
#event edition form
|
||||
# event edition form
|
||||
title: "Title"
|
||||
title_is_required: "Se requiere un título."
|
||||
matching_visual: "Coincidencia visual"
|
||||
@ -151,8 +160,9 @@ es:
|
||||
tickets_available: "Entradas disponibles"
|
||||
event_theme: "Tema del evento"
|
||||
age_range: "Rango de edades"
|
||||
|
||||
plan:
|
||||
#subscription plan edition form
|
||||
# subscription plan edition form
|
||||
general_information: "Información general"
|
||||
name: "Nombre"
|
||||
name_is_required: "Se requiere un nombre."
|
||||
@ -193,8 +203,9 @@ es:
|
||||
email_address_is_required: "Se requiere un mail."
|
||||
disabled: "Disable subscription"
|
||||
disable_plan_will_not_unsubscribe_users: "Beware: disabling this plan won't unsubscribe users having active subscriptions with it."
|
||||
|
||||
trainings:
|
||||
#training edition form
|
||||
# training edition form
|
||||
name: "Nombre"
|
||||
name_is_required: "Se requiere un nombre."
|
||||
illustration: "Ilustración"
|
||||
@ -207,8 +218,9 @@ es:
|
||||
number_of_tickets: "Número de entradas"
|
||||
public_page: "Hacer curso público"
|
||||
disable_training: "Disable the training"
|
||||
|
||||
user_admin:
|
||||
#partial form to edit/create an user (admin view)
|
||||
# partial form to edit/create an user (admin view)
|
||||
user: "User"
|
||||
incomplete_profile: "Incomplete profile"
|
||||
user_profile: "Profil utilisateur"
|
||||
@ -217,8 +229,9 @@ es:
|
||||
group_is_required: "Se requiere un grupo"
|
||||
trainings: "Cursos"
|
||||
tags: "Tags"
|
||||
|
||||
authentication:
|
||||
#partial form to edit/create an authentication provider (SSO)
|
||||
# partial form to edit/create an authentication provider (SSO)
|
||||
name: "Nombre"
|
||||
provider_name_is_required: "Se requiere el nombre del proveedor."
|
||||
authentication_type: "Tipo de autenticación"
|
||||
@ -229,6 +242,7 @@ es:
|
||||
expected_data_type: "Tipo de datos esperado"
|
||||
input_format: "Formato de entrada"
|
||||
mappings: "Mapeos"
|
||||
|
||||
oauth2:
|
||||
#edition/creation form of an OAuth2 authentication provider
|
||||
common_url: "URL común"
|
||||
@ -253,25 +267,29 @@ es:
|
||||
api_endpoint_url: "API final de URL"
|
||||
api_type: "Tipo de API"
|
||||
api_fields: "Campos de API"
|
||||
|
||||
confirm_modify_slot_modal:
|
||||
#machine/training slot modification modal
|
||||
# machine/training slot modification modal
|
||||
change_the_slot: "Cambiar la ranura"
|
||||
do_you_want_to_change_your_booking_slot_initially_planned_at: "Desea cambiar su reserva efectuada inicialmente el:"
|
||||
do_you_want_to_change_NAME_s_booking_slot_initially_planned_at: "Desea cambiar la reserva de {NAME} , efectuada inicialmente el:"
|
||||
cancel_this_reservation: "Cancelar reserva"
|
||||
i_want_to_change_date: "Quiero cambiar la fecha"
|
||||
|
||||
request_training_modal:
|
||||
#modal introducing that a training is requested before booking a machine
|
||||
# modal introducing that a training is requested before booking a machine
|
||||
to_book_the_MACHINE_you_must_have_completed_the_TRAINING: "Para reservar \"{MACHINE}\" debes haber completado el curso: {TRAINING}."
|
||||
register_for_the_training: "Apuntarse al curso"
|
||||
i_dont_want_to_register_now: "No quiero apuntarme aún"
|
||||
|
||||
training_reservation_modal:
|
||||
#modal introducing that a user must wait for his training being validated before booking a machine
|
||||
# modal introducing that a user must wait for his training being validated before booking a machine
|
||||
machine_reservation: "Reserva de máquina"
|
||||
you_must_wait_for_your_training_is_being_validated_by_the_fablab_team_to_book_this_machine: "Debes esperar a que el Fablab valide tu curso para reservar la máquina."
|
||||
your_training_will_occur_: "Tu curso será realizado"
|
||||
|
||||
public_profile:
|
||||
#user public profile
|
||||
# user public profile
|
||||
last_activity_html: "Last activity <br><strong>on {DATE}</strong>"
|
||||
to_come: "por llegar"
|
||||
approved: "aprobada"
|
||||
@ -285,6 +303,7 @@ es:
|
||||
email_address: "Email address"
|
||||
trainings: "Trainings"
|
||||
no_trainings: "No trainings"
|
||||
|
||||
wallet:
|
||||
#wallet
|
||||
wallet: 'Cartera'
|
||||
@ -321,8 +340,9 @@ es:
|
||||
debit_reservation_machine: "Débito por reserva de máquina"
|
||||
debit_reservation_event: "Débito por reserva de evento"
|
||||
warning_uneditable_credit: "ADVERTENCIA: una vez validada la reserva no podrá modificarse el pago."
|
||||
|
||||
coupon:
|
||||
#promotional coupon (creation/edition form)
|
||||
# promotional coupon (creation/edition form)
|
||||
name: "Nombre"
|
||||
name_is_required: "Name is required."
|
||||
code: "Código"
|
||||
@ -344,8 +364,9 @@ es:
|
||||
max_usages: "Usos máximos permitidos"
|
||||
max_usages_must_be_equal_or_greater_than_0: "El número de usos máximos permitidos debe ser mayor que 0."
|
||||
enabled: "Activo"
|
||||
|
||||
coupon_input:
|
||||
#coupon (input zone for users)
|
||||
# coupon (input zone for users)
|
||||
i_have_a_coupon: "I have a coupon!"
|
||||
code_: "Code:"
|
||||
the_coupon_has_been_applied_you_get_PERCENT_discount: "Se ha aplicado el cupón {PERCENT}% de descuento."
|
||||
@ -357,8 +378,9 @@ es:
|
||||
unable_to_apply_the_coupon_because_amount_exceeded: "No se puede aplicar el cupón: el descuento excede el monto total de esta compra."
|
||||
unable_to_apply_the_coupon_because_undefined: "No se puede aplicar el cupón: se ha producido un error inesperado, póngase en contacto con el gerente del Fablab."
|
||||
unable_to_apply_the_coupon_because_rejected: "Este código no existe."
|
||||
|
||||
space:
|
||||
#form to create/edit a space
|
||||
# form to create/edit a space
|
||||
name: "Nombre"
|
||||
name_is_required: "Se requiere un nombre."
|
||||
illustration: "Ilustración"
|
||||
@ -373,8 +395,9 @@ es:
|
||||
default_places: "Máximo de entradas predeterminado"
|
||||
default_places_is_required: "Se requiere un máximo de entradas predeterminado."
|
||||
disable_space: "Disable space"
|
||||
|
||||
cart:
|
||||
#module de panier d'achat de réservations
|
||||
# module de panier d'achat de réservations
|
||||
summary: "Resumen"
|
||||
select_one_or_more_slots_in_the_calendar: "Selecciona uno {SINGLE, select, true{slot} other{or more slots}} en el calendario"
|
||||
you_ve_just_selected_the_slot: "Acaba de seleccionar el espacio :"
|
||||
|
@ -427,7 +427,7 @@ fr:
|
||||
tags_of_the_destination_slot: "Étiquettes du créneau de destination :"
|
||||
confirm_my_modification: "Valider ma modification"
|
||||
your_booking_slot_was_successfully_moved_from_: "Votre créneau de réservation a bien été déplacé du"
|
||||
to_date: "au" # context: date. eg: 'from 01/01 to 01/05'
|
||||
to_date: "au" # eg. from 01/01 to 01/05
|
||||
please_select_a_member_first: "Veuillez tout d'abord sélectionner un membre"
|
||||
unable_to_select_plan_if_slots_in_the_past: "Impossible de sélectionner un abonnement si l'un des créneaux sélectionné est dans le passé"
|
||||
unable_to_change_the_reservation: "Impossible de modifier la réservation"
|
||||
@ -435,7 +435,12 @@ fr:
|
||||
do_you_really_want_to_cancel_this_reservation: "Êtes-vous sur de vouloir annuler cette réservation ?"
|
||||
reservation_was_cancelled_successfully: "La réservation a bien été annulée."
|
||||
cancellation_failed: "L'annulation a échouée."
|
||||
confirm_payment_of_html: "{ROLE, select, admin{Paiement sur place} other{Payer}} : {AMOUNT}" # (contexte : valider mon paiement de 20,00 €)
|
||||
confirm_payment_of_html: "{ROLE, select, admin{Paiement sur place} other{Payer}} : {AMOUNT}" # eg. valider mon paiement de 20,00 €
|
||||
a_problem_occurred_during_the_payment_process_please_try_again_later: "Il y a eu un problème lors de la procédure de paiement. Veuillez réessayer plus tard."
|
||||
none: "Aucune"
|
||||
online_payment_disabled: "Le payment par carte bancaire n'est pas disponible. Merci de contacter directement l'accueil du Fablab."
|
||||
|
||||
tour:
|
||||
previous: "Précédent"
|
||||
next: "Suivant"
|
||||
end: "Terminer la visite"
|
||||
|
@ -427,7 +427,7 @@ pt:
|
||||
tags_of_the_destination_slot: "Tags do slot de destino:"
|
||||
confirm_my_modification: "Confirmar minha modificação"
|
||||
your_booking_slot_was_successfully_moved_from_: "Seu slot de reserva foi movido com sucesso para"
|
||||
to_date: "até" # context: date. eg: 'from 01/01 to 01/05'
|
||||
to_date: "até" # eg. from 01/01 to 01/05
|
||||
please_select_a_member_first: "Por favor selecione o membro primeiramente"
|
||||
unable_to_select_plan_if_slots_in_the_past: 'Não é possível selecionar um plano se algum dos slots selecionados estiver no passado'
|
||||
unable_to_change_the_reservation: "Não permitido alterar esta reserva"
|
||||
|
@ -1,5 +1,4 @@
|
||||
en:
|
||||
|
||||
duration:
|
||||
# subscription plan duration
|
||||
year:
|
||||
@ -237,7 +236,6 @@ en:
|
||||
reservations: "Reservations"
|
||||
available_seats: "Available seats"
|
||||
|
||||
|
||||
api:
|
||||
notifications:
|
||||
# internal app notifications
|
||||
@ -247,7 +245,7 @@ en:
|
||||
notify_admin_member_create_reservation:
|
||||
a_RESERVABLE_reservation_was_made_by_USER_html: "A <strong><em>%{RESERVABLE}</em></strong> reservation was made by <strong><em>%{USER}</em></strong>."
|
||||
notify_admin_profile_complete:
|
||||
account_imported_from_PROVIDER_UID_has_completed_its_information_html: "Account imported from <strong><em>%{PROVIDER} </strong> (%{UID})</em> has completed its information."
|
||||
account_imported_from_PROVIDER_UID_has_completed_its_information_html: "Account imported from <strong><em>%{PROVIDER}</strong> (%{UID})</em> has completed its information."
|
||||
notify_admin_slot_is_canceled:
|
||||
USER_s_reservation_on_the_DATE_was_cancelled_remember_to_generate_a_refund_invoice_if_applicable_html: "<strong><em>%{USER}</em></strong>'s reservation, on the %{DATE}, was cancelled. Remember to generate a refund invoice if applicable."
|
||||
notify_admin_slot_is_modified:
|
||||
|
@ -1,6 +1,6 @@
|
||||
es:
|
||||
duration:
|
||||
#subscription plan duration
|
||||
# subscription plan duration
|
||||
year:
|
||||
one: 'un año'
|
||||
other: '%{count} años'
|
||||
@ -10,24 +10,26 @@ es:
|
||||
week:
|
||||
one: 'una semana'
|
||||
other: '%{count} semanas'
|
||||
|
||||
time:
|
||||
formats:
|
||||
#See http://apidock.com/ruby/DateTime/strftime for a list of available directives
|
||||
# See http://apidock.com/ruby/DateTime/strftime for a list of available directives
|
||||
hour_minute: "%I:%M %p"
|
||||
errors:
|
||||
messages:
|
||||
#CarrierWave
|
||||
carrierwave_processing_error: "no se pudo procesar"
|
||||
|
||||
errors: &errors
|
||||
messages: &errors_messages
|
||||
# CarrierWave
|
||||
carrierwave_processing_error: "falló al procesar"
|
||||
carrierwave_integrity_error: "es un tipo de archivo no permitido"
|
||||
carrierwave_download_error: "no pudo ser descargado"
|
||||
extension_white_list_error: "No puede subir archivos con extensión %{extension}, tipos permitidos: %{allowed_types}"
|
||||
extension_black_list_error: "No puede subir archivos con extensión %{extension}, tipos prohibidos: %{prohibited_types}"
|
||||
extension_white_list_error: "No puede subir archivos de extensión %{extension}, tipos permitidos: %{allowed_types}"
|
||||
extension_black_list_error: "No puede subir archivos de extensión %{extension}, tipos prohibidos: %{prohibited_types}"
|
||||
rmagick_processing_error: "Error al manipular con rmagick, ¿Está seguro de que el archivo es una imagen? Error original: %{e}"
|
||||
mime_types_processing_error: "Error al procesar archivo con MIME::Types, puede ser que el contenido no sea válido. Error original: %{e}"
|
||||
mini_magick_processing_error: "Error al editar con MiniMagick, ¿Está seguro de que el archivo es una imagen? Error original: %{e}"
|
||||
wrong_size: "es de tamaño incorrecto (debería ser de %{file_size})"
|
||||
size_too_small: "es demasiado pequeño (debería ser de minimo %{file_size})"
|
||||
size_too_big: "es demasiado grande (deberia ser de maximo %{file_size})"
|
||||
size_too_big: "es demasiado grande (debería ser de maximo %{file_size})"
|
||||
export_not_found: "La exportación solicitada no se encontró. Probablemente fue borrada, por favor, genere una nueva exportación."
|
||||
percentage_out_of_range: "El porcentaje debe estar incluido entre 0 y 100"
|
||||
cannot_be_blank_at_same_time: "no puede estar vacío cuando %{field} también está vacío"
|
||||
@ -40,55 +42,38 @@ es:
|
||||
end_before_start: "La fecha de fin no puede ser anterior a la fecha de inicio. Elija una fecha posterior a %{START}"
|
||||
invalid_duration: "La duración permitida es de 1 día a 1 año. Su período es %{DAYS} días de largo."
|
||||
must_be_in_the_past: "El período debe ser estrictamente anterior a la fecha de hoy."
|
||||
|
||||
activemodel:
|
||||
errors:
|
||||
messages:
|
||||
carrierwave_processing_error: falló al procesar
|
||||
carrierwave_integrity_error: es un tipo de archivo no permitido
|
||||
carrierwave_download_error: no pudo ser descargado
|
||||
extension_white_list_error: 'No puede subir archivos de extensión %{extension}, tipos permitidos: %{allowed_types}'
|
||||
extension_black_list_error: 'No puede subir archivos de extensión %{extension}, tipos prohibidos: %{prohibited_types}'
|
||||
rmagick_processing_error: 'Error al manipular con rmagick, ¿Está seguro de que el archivo es una imagen? Error original: %{e}'
|
||||
mime_types_processing_error: 'Error al procesar archivo con MIME::Types, puede ser que el contenido no sea válido. Error original: %{e}'
|
||||
mini_magick_processing_error: 'Error al editar con MiniMagick, ¿Está seguro de que el archivo es una imagen? Error original: %{e}'
|
||||
wrong_size: es de tamaño incorrecto (debería ser de %{file_size})
|
||||
size_too_small: es demasiado pequeño (debería ser de minimo %{file_size})
|
||||
size_too_big: es demasiado grande (debería ser de maximo %{file_size})
|
||||
export_not_found: La exportación solicitada no se encontró. Probablemente fue borrada, por favor, genere una nueva exportación.
|
||||
percentage_out_of_range: El porcentaje debe estar incluido entre 0 y 100
|
||||
cannot_be_blank_at_same_time: no puede estar vacío cuando %{field} también está vacío
|
||||
cannot_be_in_the_past: no puede estar en el pasado
|
||||
cannot_be_before_previous_value: no puede estar antes del valor anterior
|
||||
cannot_overlap: no se puede solapar con un período contable existente
|
||||
cannot_encompass: no puede abarcar un período contable existente
|
||||
in_closed_period: no puede estar dentro de un período de contabilidad cerrado
|
||||
invalid_footprint: la suma de comprobación de factura no es válida
|
||||
end_before_start: La fecha de fin no puede ser anterior a la fecha de inicio. Elija una fecha posterior a %{START}
|
||||
invalid_duration: La duración permitida es de 1 día a 1 año. Su período es %{DAYS} días de largo.
|
||||
must_be_in_the_past: El período debe ser estrictamente anterior a la fecha de hoy.
|
||||
<<: *errors
|
||||
|
||||
apipie:
|
||||
api_documentation: "Documentación API"
|
||||
|
||||
omniauth:
|
||||
#error messages when importing an account from a SSO
|
||||
# error messages when importing an account from a SSO
|
||||
email_already_linked_to_another_account_please_input_your_authentication_code: "El correo electrónico \"%{OLD_MAIL}\" ya está ligado a otra cuenta, ingrese su código de autenticación."
|
||||
your_username_is_already_linked_to_another_account_unable_to_update_it: "Su nombre de usuario (%{USERNAME}) ya está ligado a otra cuenta, no se puede actualizar."
|
||||
your_email_address_is_already_linked_to_another_account_unable_to_update_it: "Your e-mail address (%{EMAIL}) ya está ligado a otra cuenta, no se puede actualizar."
|
||||
this_account_is_already_linked_to_an_user_of_the_platform: "Esta cuenta %{NAME} ya está ligada a un usuario de la plataforma."
|
||||
|
||||
availabilities:
|
||||
#availability slots in the calendar
|
||||
# availability slots in the calendar
|
||||
not_available: "No disponible"
|
||||
i_ve_reserved: "He reservado"
|
||||
length_must_be_slot_multiple: "Debe ser al menos %{MIN} minutos después de la fecha de inicio"
|
||||
must_be_associated_with_at_least_1_machine: "debe estar asociado con al menos 1 máquina"
|
||||
|
||||
members:
|
||||
#members management
|
||||
# members management
|
||||
unable_to_change_the_group_while_a_subscription_is_running: "No se puede cambiar de grupo mientras haya una suscripción en curso"
|
||||
please_input_the_authentication_code_sent_to_the_address: "Por favor Ingrese el código de autenticación enviado a la dirección de correo electrónico %{EMAIL}"
|
||||
your_authentication_code_is_not_valid: "Su código de autenticación no es válido."
|
||||
current_authentication_method_no_code: "El método de autenticación actual no requiere ningún código de migración"
|
||||
requested_account_does_not_exists: "La cuenta solicitada no existe"
|
||||
|
||||
invoices:
|
||||
#PDF invoices generation
|
||||
# PDF invoices generation
|
||||
refund_invoice_reference: "Referencia de la factura de reembolso: %{REF}"
|
||||
invoice_reference: "Referencia de factura: %{REF}"
|
||||
code: "Código: %{CODE}"
|
||||
@ -139,6 +124,7 @@ es:
|
||||
subscription_of_NAME_for_DURATION_starting_from_DATE: "Suscripción %{NAME} por %{DURATION} empezando desde %{DATE}"
|
||||
subscription_of_NAME_extended_starting_from_STARTDATE_until_ENDDATE: "Subscripción de %{NAME} extendida (días gratuitos) empezando desde %{STARTDATE} hasta %{ENDDATE}"
|
||||
and: 'y'
|
||||
|
||||
accounting_export:
|
||||
journal_code: "Código de registro"
|
||||
date: "Fecha contable"
|
||||
@ -158,19 +144,22 @@ es:
|
||||
Event_reservation: "reserv. evento"
|
||||
Space_reservation: "reserv. espacio"
|
||||
wallet: "cartera"
|
||||
|
||||
trainings:
|
||||
#training availabilities
|
||||
# training availabilities
|
||||
i_ve_reserved: "Reservé"
|
||||
completed: "Lleno"
|
||||
|
||||
events:
|
||||
#error messages when updating an event
|
||||
# error messages when updating an event
|
||||
error_deleting_reserved_price: "No se puede eliminar el precio solicitado porque está asociado con algunas reservas."
|
||||
other_error: "Se ha producido un error inesperado al actualizar el evento."
|
||||
#event duration
|
||||
# event duration
|
||||
from_STARTDATE_to_ENDDATE: "Del %{STARTDATE} al %{ENDDATE},"
|
||||
from_STARTTIME_to_ENDTIME: "de %{STARTTIME} a %{ENDTIME}"
|
||||
|
||||
export_members:
|
||||
#members list export to EXCEL format
|
||||
# members list export to EXCEL format
|
||||
members: "Miembros"
|
||||
id: "ID"
|
||||
surname: "Apellido"
|
||||
@ -201,8 +190,9 @@ es:
|
||||
man: "hombre"
|
||||
woman: "mujer"
|
||||
without_subscriptions: "Sin suscripciones"
|
||||
|
||||
export_reservations:
|
||||
#machines/trainings/events reservations list to EXCEL format
|
||||
# machines/trainings/events reservations list to EXCEL format
|
||||
reservations: "Reservas"
|
||||
customer_id: "Identificación del cliente"
|
||||
customer: "Cliente"
|
||||
@ -214,8 +204,9 @@ es:
|
||||
payment_method: "Método de pago"
|
||||
local_payment: "Pago en recepción"
|
||||
online_payment: "Pago online"
|
||||
|
||||
export_subscriptions:
|
||||
#subscriptions list export to EXCEL format
|
||||
# subscriptions list export to EXCEL format
|
||||
subscriptions: "Suscripciones"
|
||||
id: "ID"
|
||||
customer: "Cliente"
|
||||
@ -228,8 +219,9 @@ es:
|
||||
payment_method: "Método de pago"
|
||||
local_payment: "Pago en recepción"
|
||||
online_payment: "Pago en línea"
|
||||
|
||||
export_availabilities:
|
||||
#reservation slots export, by type, to EXCEL format
|
||||
# reservation slots export, by type, to EXCEL format
|
||||
machines: "Máquinas"
|
||||
trainings: "Formaciones"
|
||||
spaces: "Espacios"
|
||||
@ -243,16 +235,17 @@ es:
|
||||
event: "Evento"
|
||||
reservations: "Reservas"
|
||||
available_seats: "Asientos disponibles"
|
||||
|
||||
api:
|
||||
notifications:
|
||||
#internal app notifications
|
||||
# internal app notifications
|
||||
deleted_user: "Usuario eliminado"
|
||||
notify_admin_abuse_reported:
|
||||
an_abuse_was_reported_on_TYPE_ID_NAME_html: "Un abuso ha sido reportado <strong>%{TYPE} %{ID}: <em>%{NAME}</em></strong>."
|
||||
notify_admin_member_create_reservation:
|
||||
a_RESERVABLE_reservation_was_made_by_USER_html: "Una reserva de <strong><em>%{RESERVABLE}</em></strong> fue hecha por <strong><em>%{USER}</em></strong>."
|
||||
notify_admin_profile_complete:
|
||||
account_imported_from_PROVIDER_UID_has_completed_its_information_html: "Cuenta importada desde <strong><em>%{PROVIDER} </strong> (%{UID})</em> ha completado su información."
|
||||
account_imported_from_PROVIDER_UID_has_completed_its_information_html: "Cuenta importada desde <strong><em>%{PROVIDER}</strong> (%{UID})</em> ha completado su información."
|
||||
notify_admin_slot_is_canceled:
|
||||
USER_s_reservation_on_the_DATE_was_cancelled_remember_to_generate_a_refund_invoice_if_applicable_html: "La reserva de <strong><em>%{USER}</em></strong>, hecha el %{DATE} ha sido cancelada. Recuerda reclamar una devolución si está disponible."
|
||||
notify_admin_slot_is_modified:
|
||||
@ -358,8 +351,9 @@ es:
|
||||
click_to_show: "Haga clic aquí para consultar"
|
||||
notify_admin_refund_created:
|
||||
refund_created: "Se ha creado un reembolso de %{AMOUNT} para el usuario %{USER}"
|
||||
|
||||
statistics:
|
||||
#statistics tools for admins
|
||||
# statistics tools for admins
|
||||
subscriptions: "Suscripciones"
|
||||
machines_hours: "Machine slots"
|
||||
spaces: "Espacios"
|
||||
@ -385,8 +379,9 @@ es:
|
||||
revenue: "Ingresos"
|
||||
account_creation: "Creación de cuenta"
|
||||
project_publication: "Publicación de proyectos"
|
||||
|
||||
export:
|
||||
#statistics exports to the excel file format
|
||||
# statistics exports to the excel file format
|
||||
entries: "Entradas"
|
||||
revenue: "Ingresos"
|
||||
average_age: "Edad media"
|
||||
@ -400,10 +395,12 @@ es:
|
||||
type: "Tipo"
|
||||
male: "Hombre"
|
||||
female: "Mujer"
|
||||
|
||||
price_category:
|
||||
#initial price's category for events, created to replace the old "reduced amount" property
|
||||
# initial price's category for events, created to replace the old "reduced amount" property
|
||||
reduced_fare: "Tarifa reducida"
|
||||
reduced_fare_if_you_are_under_25_student_or_unemployed: "Tarifa reducida si tienes menos de 25 años, eres estudiante o estás desempleado."
|
||||
|
||||
group:
|
||||
#name of the user's group for administrators
|
||||
# name of the user's group for administrators
|
||||
admins: 'Administradores'
|
||||
|
@ -1,5 +1,4 @@
|
||||
fr:
|
||||
|
||||
duration:
|
||||
# durée d'une formule d'abonnement
|
||||
year:
|
||||
@ -237,7 +236,6 @@ fr:
|
||||
reservations: "Réservations"
|
||||
available_seats: "Places disponibles"
|
||||
|
||||
|
||||
api:
|
||||
notifications:
|
||||
# notifications internes à l'application
|
||||
@ -247,7 +245,7 @@ fr:
|
||||
notify_admin_member_create_reservation:
|
||||
a_RESERVABLE_reservation_was_made_by_USER_html: "Une réservation <strong><em>%{RESERVABLE}</em></strong> a été effectuée par <strong><em>%{USER}</em></strong>."
|
||||
notify_admin_profile_complete:
|
||||
account_imported_from_PROVIDER_UID_has_completed_its_information_html: "Le compte importé depuis <strong><em>%{PROVIDER} </strong> (%{UID})</em> a complété ses informations."
|
||||
account_imported_from_PROVIDER_UID_has_completed_its_information_html: "Le compte importé depuis <strong><em>%{PROVIDER}</strong> (%{UID})</em> a complété ses informations."
|
||||
notify_admin_slot_is_canceled:
|
||||
USER_s_reservation_on_the_DATE_was_cancelled_remember_to_generate_a_refund_invoice_if_applicable_html: "La réservation de <strong><em>%{USER}</em></strong>, le %{DATE}, a été annulée. Pensez a générer un avoir le cas échéant."
|
||||
notify_admin_slot_is_modified:
|
||||
|
@ -291,7 +291,7 @@ en:
|
||||
|
||||
notify_admin_free_disk_space:
|
||||
subject: "Low disk space"
|
||||
body: "Warning: available disk space on the server hosting fab-manager is less than %{THRESHOLD} MiB. This can affect its operation and prevent saving some data. Currently, %{AVAILABLE} MiB of free disk space remains available on the mount point."
|
||||
body: "Warning: available disk space on the server hosting Fab-manager is less than %{THRESHOLD} MiB. This can affect its operation and prevent saving some data. Currently, %{AVAILABLE} MiB of free disk space remains available on the mount point."
|
||||
|
||||
notify_admin_close_period_reminder:
|
||||
subject: "Remind to close your accounting periods"
|
||||
|
@ -291,7 +291,7 @@ es:
|
||||
|
||||
notify_admin_free_disk_space:
|
||||
subject: "Low disk space"
|
||||
body: "Warning: available disk space on the server hosting fab-manager is less than %{THRESHOLD} MiB. This can affect its operation and prevent saving some data. Currently, %{AVAILABLE} MiB of free disk space remains available on the mount point."
|
||||
body: "Warning: available disk space on the server hosting Fab-manager is less than %{THRESHOLD} MiB. This can affect its operation and prevent saving some data. Currently, %{AVAILABLE} MiB of free disk space remains available on the mount point."
|
||||
|
||||
notify_admin_close_period_reminder:
|
||||
subject: "Remind to close your accounting periods"
|
||||
|
@ -291,7 +291,7 @@ fr:
|
||||
|
||||
notify_admin_free_disk_space:
|
||||
subject: "Espace disque faible"
|
||||
body: "Attention : l'espace disque disponible sur le serveur hébergeant fab-manager est inférieur à %{THRESHOLD} MiO. Cela peut nuire à son bon fonctionnement et empêcher la sauvegarde de certaines données. Actuellement, il reste %{AVAILABLE} MiO d'espace libre sur le point de montage."
|
||||
body: "Attention : l'espace disque disponible sur le serveur hébergeant Fab-manager est inférieur à %{THRESHOLD} MiO. Cela peut nuire à son bon fonctionnement et empêcher la sauvegarde de certaines données. Actuellement, il reste %{AVAILABLE} MiO d'espace libre sur le point de montage."
|
||||
|
||||
notify_admin_close_period_reminder:
|
||||
subject: "Pensez à clôturer vos périodes comptables"
|
||||
|
@ -291,7 +291,7 @@ pt:
|
||||
|
||||
notify_admin_free_disk_space:
|
||||
subject: "Low disk space"
|
||||
body: "Warning: available disk space on the server hosting fab-manager is less than %{THRESHOLD} MiB. This can affect its operation and prevent saving some data. Currently, %{AVAILABLE} MiB of free disk space remains available on the mount point."
|
||||
body: "Warning: available disk space on the server hosting Fab-manager is less than %{THRESHOLD} MiB. This can affect its operation and prevent saving some data. Currently, %{AVAILABLE} MiB of free disk space remains available on the mount point."
|
||||
|
||||
notify_admin_close_period_reminder:
|
||||
subject: "Remind to close your accounting periods"
|
||||
|
@ -1,5 +1,4 @@
|
||||
pt:
|
||||
|
||||
duration:
|
||||
# subscription plan duration
|
||||
year:
|
||||
@ -237,7 +236,6 @@ pt:
|
||||
reservations: "Reservas"
|
||||
available_seats: "Assentos disponíveis"
|
||||
|
||||
|
||||
api:
|
||||
notifications:
|
||||
# internal app notifications
|
||||
@ -247,7 +245,7 @@ pt:
|
||||
notify_admin_member_create_reservation:
|
||||
a_RESERVABLE_reservation_was_made_by_USER_html: "A <strong><em>%{RESERVABLE}</em></strong> reserva foi feita por <strong><em>%{USER}</em></strong>."
|
||||
notify_admin_profile_complete:
|
||||
account_imported_from_PROVIDER_UID_has_completed_its_information_html: "Conta importada para <strong><em>%{PROVIDER} </strong> (%{UID})</em> completou a sua informação."
|
||||
account_imported_from_PROVIDER_UID_has_completed_its_information_html: "Conta importada para <strong><em>%{PROVIDER}</strong> (%{UID})</em> completou a sua informação."
|
||||
notify_admin_slot_is_canceled:
|
||||
USER_s_reservation_on_the_DATE_was_cancelled_remember_to_generate_a_refund_invoice_if_applicable_html: "A reserva de <strong> <em> %{USER} </em> </strong>, na %{DATE}, foi cancelada. Lembre-se de gerar uma fatura de reembolso, se aplicável."
|
||||
notify_admin_slot_is_modified:
|
||||
|
@ -58,6 +58,7 @@ Rails.application.routes.draw do
|
||||
post 'list', action: 'list', on: :collection
|
||||
get 'search/:query', action: 'search', on: :collection
|
||||
get 'mapping', action: 'mapping', on: :collection
|
||||
patch ':id/complete_tour', action: 'complete_tour', on: :collection
|
||||
end
|
||||
resources :reservations, only: %i[show create index update]
|
||||
resources :notifications, only: %i[index show update] do
|
||||
|
@ -16,7 +16,7 @@ generate_statistic:
|
||||
queue: default
|
||||
|
||||
i_calendar_import:
|
||||
cron: "0 2 * * *"
|
||||
cron: "0 * * * *"
|
||||
class: "ICalendarImportWorker"
|
||||
queue: default
|
||||
|
||||
|
@ -24,6 +24,7 @@ development:
|
||||
user_confirmation_needed_to_sign_in: <%= ENV["USER_CONFIRMATION_NEEDED_TO_SIGN_IN"] %>
|
||||
events_in_calendar: <%= ENV["EVENTS_IN_CALENDAR"] %>
|
||||
slot_duration: <%= ENV["SLOT_DURATION"] %>
|
||||
feature_tour_display: <%= ENV["FEATURE_TOUR_DISPLAY"] %>
|
||||
default_host: <%= ENV["DEFAULT_HOST"] %>
|
||||
default_protocol: <%= ENV["DEFAULT_PROTOCOL"] %>
|
||||
time_zone: <%= ENV["TIME_ZONE"] %>
|
||||
@ -70,6 +71,7 @@ test:
|
||||
user_confirmation_needed_to_sign_in: <%= ENV["USER_CONFIRMATION_NEEDED_TO_SIGN_IN"] %>
|
||||
events_in_calendar: false
|
||||
slot_duration: 60
|
||||
feature_tour_display: <%= ENV["FEATURE_TOUR_DISPLAY"] %>
|
||||
default_host: <%= ENV["DEFAULT_HOST"] %>
|
||||
default_protocol: <%= ENV["DEFAULT_PROTOCOL"] %>
|
||||
time_zone: Paris
|
||||
@ -116,6 +118,7 @@ staging:
|
||||
user_confirmation_needed_to_sign_in: <%= ENV["USER_CONFIRMATION_NEEDED_TO_SIGN_IN"] %>
|
||||
events_in_calendar: <%= ENV["EVENTS_IN_CALENDAR"] %>
|
||||
slot_duration: <%= ENV["SLOT_DURATION"] %>
|
||||
feature_tour_display: <%= ENV["FEATURE_TOUR_DISPLAY"] %>
|
||||
default_host: <%= ENV["DEFAULT_HOST"] %>
|
||||
default_protocol: <%= ENV["DEFAULT_PROTOCOL"] %>
|
||||
delivery_method: <%= ENV['DELIVERY_METHOD'] %>
|
||||
@ -174,6 +177,7 @@ production:
|
||||
user_confirmation_needed_to_sign_in: <%= ENV["USER_CONFIRMATION_NEEDED_TO_SIGN_IN"] %>
|
||||
events_in_calendar: <%= ENV["EVENTS_IN_CALENDAR"] %>
|
||||
slot_duration: <%= ENV["SLOT_DURATION"] %>
|
||||
feature_tour_display: <%= ENV["FEATURE_TOUR_DISPLAY"] %>
|
||||
default_host: <%= ENV["DEFAULT_HOST"] %>
|
||||
default_protocol: <%= ENV["DEFAULT_PROTOCOL"] %>
|
||||
delivery_method: <%= ENV['DELIVERY_METHOD'] %>
|
||||
|
@ -1,7 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# From this migration, we store URL to iCalendar files and a piece of configuration about them.
|
||||
# This allows to display the events of these external calendars in fab-manager
|
||||
# This allows to display the events of these external calendars in Fab-manager
|
||||
class CreateICalendars < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :i_calendars do |t|
|
||||
|
@ -1,3 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# From this migration, we distinct multiple stylesheets by their name (previously there was one only one for the main theme override)
|
||||
class AddNameToStylesheet < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :stylesheets, :name, :string
|
||||
|
8
db/migrate/20200218092221_add_tours_to_profile.rb
Normal file
8
db/migrate/20200218092221_add_tours_to_profile.rb
Normal file
@ -0,0 +1,8 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# From this migration, we save in database the "feature tours" viewed by each users to prevent displaying them many times
|
||||
class AddToursToProfile < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :profiles, :tours, :string
|
||||
end
|
||||
end
|
@ -11,7 +11,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20200127111404) do
|
||||
ActiveRecord::Schema.define(version: 20200218092221) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
@ -511,6 +511,7 @@ ActiveRecord::Schema.define(version: 20200127111404) do
|
||||
t.string "lastfm"
|
||||
t.string "flickr"
|
||||
t.string "job"
|
||||
t.string "tours"
|
||||
end
|
||||
|
||||
add_index "profiles", ["user_id"], name: "index_profiles_on_user_id", using: :btree
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Install Fab-Manager in a development environment with Docker
|
||||
# Install Fab-manager in a development environment with Docker
|
||||
|
||||
This document will guide you through all the steps needed to set up a development environment for Fab-Manager.
|
||||
This document will guide you through all the steps needed to set up a development environment for Fab-manager.
|
||||
|
||||
##### Table of contents
|
||||
|
||||
@ -42,7 +42,7 @@ This procedure is not easy to follow so if you don't need to write some code for
|
||||
sudo reboot
|
||||
```
|
||||
|
||||
6. Create a docker network for fab-manager.
|
||||
6. Create a docker network for Fab-manager.
|
||||
You may have to change the network address if it is already in use.
|
||||
> 🍏 If you're using MacOS, this is not required.
|
||||
```bash
|
||||
@ -132,7 +132,7 @@ This procedure is not easy to follow so if you don't need to write some code for
|
||||
foreman s -p 3000
|
||||
```
|
||||
|
||||
16. You should now be able to access your local development FabManager instance by accessing `http://localhost:3000` in your web browser.
|
||||
16. You should now be able to access your local development Fab-manager instance by accessing `http://localhost:3000` in your web browser.
|
||||
|
||||
17. You can login as the default administrator using the credentials defined previously.
|
||||
|
||||
@ -162,12 +162,12 @@ We will use docker to easily install the required version of PostgreSQL.
|
||||
postgres:9.6
|
||||
```
|
||||
|
||||
3. Configure fab-manager to use it.
|
||||
3. Configure Fab-manager to use it.
|
||||
On linux systems, PostgreSQL will be available at 172.18.0.2.
|
||||
On MacOS, you'll have to set the host to 127.0.0.1 (or localhost).
|
||||
See [environment.md](environment.md) for more details.
|
||||
|
||||
4 . Finally, you may want to have a look at detailed informations about PostgreSQL usage in fab-manager.
|
||||
4 . Finally, you may want to have a look at detailed informations about PostgreSQL usage in Fab-manager.
|
||||
Some information about that is available in the [PostgreSQL Readme](postgresql_readme.md).
|
||||
|
||||
<a name="elasticsearch"></a>
|
||||
@ -175,7 +175,7 @@ We will use docker to easily install the required version of PostgreSQL.
|
||||
|
||||
ElasticSearch is a powerful search engine based on Apache Lucene combined with a NoSQL database used as a cache to index data and quickly process complex requests on it.
|
||||
|
||||
In FabManager, it is used for the admin's statistics module and to perform searches in projects.
|
||||
In Fab-manager, it is used for the admin's statistics module and to perform searches in projects.
|
||||
|
||||
<a name="setup-elasticsearch"></a>
|
||||
### Install ElasticSearch
|
||||
@ -205,7 +205,7 @@ In FabManager, it is used for the admin's statistics module and to perform searc
|
||||
elasticsearch:5.6
|
||||
```
|
||||
|
||||
4. Configure fab-manager to use it.
|
||||
4. Configure Fab-manager to use it.
|
||||
On linux systems, ElasticSearch will be available at 172.18.0.3.
|
||||
On MacOS, you'll have to set the host to 127.0.0.1 (or localhost).
|
||||
See [environment.md](environment.md) for more details.
|
||||
|
@ -1,9 +1,9 @@
|
||||
# Install Fab-Manager in production with docker-compose
|
||||
# Install Fab-manager in production with docker-compose
|
||||
|
||||
This document will guide you through all the steps needed to set up your Fab-Manager app on a production server, based on a solution using Docker and Docker-compose.
|
||||
This document will guide you through all the steps needed to set up your Fab-manager app on a production server, based on a solution using Docker and Docker-compose.
|
||||
We recommend DigitalOcean, but these steps will work on any Docker-compatible cloud provider or local server.
|
||||
|
||||
In order to make it work, please use the same directories structure as described in this guide in your Fab-Manager app folder.
|
||||
In order to make it work, please use the same directories structure as described in this guide in your Fab-manager app folder.
|
||||
You will need to be root through the rest of the setup.
|
||||
|
||||
##### Table of contents
|
||||
@ -39,7 +39,7 @@ Here's a non exhaustive list:
|
||||
|
||||
Choose one, depending on your budget, on the server's location, on the uptime guarantee, etc.
|
||||
|
||||
You will need at least 2GB of addressable memory (RAM + swap) to install and use FabManager.
|
||||
You will need at least 2GB of addressable memory (RAM + swap) to install and use Fab-manager.
|
||||
We recommend 4 GB RAM for larger communities.
|
||||
|
||||
On DigitalOcean, create a Droplet with One-click apps **"Docker on Ubuntu 16.04 LTS"**.
|
||||
@ -71,7 +71,7 @@ connect to the server with `ssh root@your-domain-name`.
|
||||
<a name="prepare-the-server"></a>
|
||||
### Prepare the server
|
||||
|
||||
Before installing fab-manager, we recommend you to:
|
||||
Before installing Fab-manager, we recommend you to:
|
||||
- Upgrade your system
|
||||
- Setup the server timezone
|
||||
- Add at least 2GB of swap memory
|
||||
@ -84,16 +84,16 @@ You can run the following script as root to easily perform all these operations:
|
||||
```
|
||||
|
||||
<a name="install-fab-manager"></a>
|
||||
## Install Fab-Manager
|
||||
## Install Fab-manager
|
||||
|
||||
Run the following command to install Fab-Manager.
|
||||
Run the following command to install Fab-manager.
|
||||
This script will guide you through the installation process by checking the requirements and asking you the configuration elements.
|
||||
|
||||
```bash
|
||||
\curl -sSL setup.fab-manager.com | bash
|
||||
```
|
||||
|
||||
**OR**, if you don't want to install fab-manager in `/apps/fabmanager`, use the following instead:
|
||||
**OR**, if you don't want to install Fab-manager in `/apps/fabmanager`, use the following instead:
|
||||
```bash
|
||||
\curl -sSL setup.fab-manager.com | bash -s "/my/custom/path"
|
||||
```
|
||||
@ -142,14 +142,14 @@ docker-compose run --rm -e ADMIN_EMAIL=xxx -e ADMIN_PASSWORD=xxx fabmanager bund
|
||||
<a name="update-fabmanager"></a>
|
||||
## Update Fab-manager
|
||||
|
||||
*This procedure updates Fab-Manager to the most recent version by default.*
|
||||
*This procedure updates Fab-manager to the most recent version by default.*
|
||||
|
||||
> ⚠ If you are upgrading from a very outdated version, you must first upgrade to v2.8.3, then to v3.1.2 and finally to the last version
|
||||
|
||||
<a name="steps"></a>
|
||||
### Steps
|
||||
|
||||
When a new version is available, follow this procedure to update fab-manager app in a production environment, using docker-compose.
|
||||
When a new version is available, follow this procedure to update Fab-manager app in a production environment, using docker-compose.
|
||||
You can subscribe to [this atom feed](https://github.com/sleede/fab-manager/releases.atom) to get notified when a new release comes out.
|
||||
|
||||
1. go to your app folder
|
||||
|
@ -3,7 +3,7 @@
|
||||
## Automatic upgrade
|
||||
|
||||
Fab-manager release 2.6.5 has upgraded its dependency to ElasticSearch from version 1.7 to version 5.6 as the previous was unsupported for months.
|
||||
To keep using fab-manager you need to upgrade your installation with the new version.
|
||||
To keep using Fab-manager you need to upgrade your installation with the new version.
|
||||
We've wrote a script to automate the process while keeping your data integrity, but there's some requirements to understand before running it.
|
||||
|
||||
- You need to install *curl*, *jq*, *GNU awk* and *sudo* on your system before running the script.
|
||||
@ -16,7 +16,7 @@ We've wrote a script to automate the process while keeping your data integrity,
|
||||
Please ensure that you'll have enough space, considering the point above. The script won't run otherwise.
|
||||
- This script will run on any Linux or Macintoch systems if you installed ElasticSearch using docker or docker-compose.
|
||||
Otherwise, only Debian compatible OS (like Ubuntu) and MacOS X are supported for classical installations. On any other cases you'll need to perform the upgrade yourself manually.
|
||||
- If your ElasticSearch instance uses replicas shards, you can't use this script and you must perform a manual upgrade (if you have a standard fab-manager installation and you don't understand what this mean, you're probably not concerned).
|
||||
- If your ElasticSearch instance uses replicas shards, you can't use this script and you must perform a manual upgrade (if you have a standard Fab-manager installation and you don't understand what this mean, you're probably not concerned).
|
||||
|
||||
Once you've understood all the points above, you can run the migration script with the following:
|
||||
|
||||
|
@ -241,6 +241,15 @@ If not specified, every admins will receive system administration notifications.
|
||||
FORCE_VERSION_CHECK
|
||||
|
||||
In test and development environments, the version won't be check automatically, unless this variable is set to "true".
|
||||
<a name="FEATURE_TOUR_DISPLAY"></a>
|
||||
|
||||
FEATURE_TOUR_DISPLAY
|
||||
|
||||
When logged-in as an administrator, a feature tour will be triggered the first time you visit each section of the application.
|
||||
You can change this behavior by setting this variable to one of the following values:
|
||||
- "once" to keep the default behavior.
|
||||
- "session" to display the tours each time you reopen the application.
|
||||
- "manual" to prevent displaying the tours automatically; you'll still be able to trigger them by pressing the F1 key.
|
||||
|
||||
<a name="internationalization-settings"></a>
|
||||
## Internationalization setting.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user