1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2024-12-01 12:24:28 +01:00
This commit is contained in:
vincent 2022-04-01 17:48:32 +02:00
parent c16150d7cc
commit f25fdd4091
164 changed files with 4662 additions and 6718 deletions

View File

@ -1 +0,0 @@
defaults

View File

@ -13,9 +13,11 @@
"angular": true, "angular": true,
"Fablab": true, "Fablab": true,
"moment": true, "moment": true,
"_": true "_": true,
"Humanize": true,
"GTM": true
}, },
"plugins": ["lint-erb"], "plugins": ["html-erb"],
"overrides": [ "overrides": [
{ {
"files": ["**/*.ts", "**/*.tsx"], "files": ["**/*.ts", "**/*.tsx"],

7
.gitignore vendored
View File

@ -65,3 +65,10 @@ yarn-error.log
/yarn-error.log /yarn-error.log
yarn-debug.log* yarn-debug.log*
.yarn-integrity .yarn-integrity
/public/packs
/public/packs-test
/node_modules
/yarn-error.log
yarn-debug.log*
.yarn-integrity

View File

@ -1,8 +1,77 @@
# Changelog Fab-manager # Changelog Fab-manager
- Updated Node to 16.13.2 - Updated Node to 16.13.2
- Updated eslint to v8 and eslint related packages to their latest versions
- Updated typescript to v4.6.3
- Webpack overlay will now report eslint issues
- Linted all code according to eslint rules
# v5.3.2 2022 January 19 ## v5.3.7 2022 March 28
- Updated Spanish translations (thanks to [@altieriranedo](https://crowdin.com/profile/altieriranedo))
- Fix a security issue: updated minimist to 1.2.6 to fix [CVE-2021-44906](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-44906)
- Fix a security issue: updated node-forge to 1.3.0 to fix [CVE-2022-24771](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-24771), [CVE-2022-24772](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-24772) and [CVE-2022-24773](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-24773)
## v5.3.6 2022 March 24
- Support for Google Analytics V4
- OAuth2 scopes are now configurable from the interface
- Prepaid-packs purchases are exported to the accounting CSV file
- Updated environment documentation
- Updated react-i18next to 11.15.6
- Updated i18next to 21.6.13
- Updated i18next-icu to 2.0.3
- Updated sidekiq-unique-jobs to 7.1.15
- Updated @uirouter/angularjs to 1.0.30
- Updated bootstrap-sass to 3.4.3
- Removed unmaintained gem sidekiq-cron and replaced it with sidekiq-scheduler
- Removed unmaintained @rails/webpacker v5 and replaced it with shakapacker v6.2.0
- Removed dependency to auto-ngtemplate-loader
- Removed support for Universal Analytics
- Updated deprecated division operators in sass
- Fix a bug: prepaid-packs purchases are reported as subscriptions in the statistics
- Fix a bug: error Couldn't find the binary git during assets compilation
- Fix a bug: a sentence was not linked to a translation key
- Fix a bug: the version check may be scheduled at an invalid time
- Fix a bug: the moment-timezone relied on an outdated version of moment with a case-sensitive locale file
- Fix a bug: unable to delete an administrator who had closed an accounting period
- Fix a bug: captcha keys are not shown in the admin panel, once configured
- Fix a bug: help message in upgrade script has a bogus format
- Fix a security issue: removed message format in elasticsearch's log4j to fix [CVE-2021-44228](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-44228)
- Fix a security issue: updated image_processing to 1.12.2 to fix [CVE-2022-24720](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-24720)
- Fix a security issue: updated url-parse to 1.5.10 to fix [CVE-2022-0686](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-0686), [CVE-2022-0691](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-0691), [CVE-2022-0639](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-0639) and [CVE-2022-0512](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-0512)
- Fix a security issue: updated rails to 5.2.6.3 to fix [CVE-2022-21831](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-21831), [CVE-2022-23633](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23633)
- Fix a security issue: updated sidekiq to 6.4.1 to fix [CVE-2022-23837](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23837)
- Fix a security issue: updated nokogiri to 1.13.3 to fix [CVE-2021-30560](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-30560) and [CVE-2022-23308](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23308)
- Fix a security issue: updated puma to 4.3.11 to fix [CVE-2022-23634](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23634)
- Fix a security issue: updated i18next-http-backend to 1.3.2 to fix [CVE-2022-0235](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-0235)
- Fix a security issue: updated follow-redirects to 1.18.8 to fix [CVE-2022-0536](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-0536)
- [TODO DEPLOY] `rails fablab:maintenance:regenerate_statistics[2021,07]`
- [TODO DEPLOY] `\curl -sSL https://raw.githubusercontent.com/sleede/fab-manager/master/scripts/cve-2021-44228.sh | bash`
- [TODO DEPLOY] update your oAuth2 provider configuration with the scopes previously defined in the OAUTH2_SCOPE environment variable
## v5.3.5 2022 March 02
- Added [an option](doc/environment.md#OPENLAB_SSL_VERIFY) to allow set verify ssl option for OpenLab
## v5.3.4 2022 March 01
- Fix line break on home events' cards
- Fix typo "projets" => "projects"
- Removes dead code about OpenAPI (open_api_calls_count_tracings)
- Fix a bug: unable to modify OpenLab url for production
## v5.3.3 2022 February 08
- Updated german translations
- Fix a bug: unable to rebuild the statistics
- Fix a bug/regresion: $sce.getTrustedHtml removes all dangerous html like iframe (youtube players, ect), replaced by $sce.trustAsHtml which trusts the content, it creates a security breach but all contents are created by users to we trust them
- Fix a bug: in SubscriptionPolicy#show?, was causing an error notice, making user think that the payment was not done, but it was
- Fix a bug: destroying a project was impossible
- Fix a bug: fix non-blocking js error when there was not payment gateway set
- [TODO DEPLOY] `rails fablab:maintenance:regenerate_statistics[2020,04]`
## v5.3.2 2022 January 19
- Add a test for statistics generation - Add a test for statistics generation
- Fix a bug: missing the Other payment method - Fix a bug: missing the Other payment method
@ -14,7 +83,7 @@
- Fix a bug: prepaid-packs without expiration date do not work - Fix a bug: prepaid-packs without expiration date do not work
- [TODO DEPLOY] `rails fablab:maintenance:regenerate_statistics[2020,04]` - [TODO DEPLOY] `rails fablab:maintenance:regenerate_statistics[2020,04]`
# v5.3.1 2022 January 17 ## v5.3.1 2022 January 17
- Definition of extended prices for spaces is now made in hours (previously in minutes) - Definition of extended prices for spaces is now made in hours (previously in minutes)
- Support for JSONPath syntax in OAuth2 SSO fields mapping - Support for JSONPath syntax in OAuth2 SSO fields mapping
@ -45,7 +114,7 @@
- Fix a security issue: updated follow-redirects to 1.14.7 to fix [CVE-2022-0155](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-0155) - Fix a security issue: updated follow-redirects to 1.14.7 to fix [CVE-2022-0155](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-0155)
- [TODO DEPLOY] `rails db:seed` - [TODO DEPLOY] `rails db:seed`
# v5.3.0 2021 December 29 ## v5.3.0 2021 December 29
- Ability to configure multiple VAT rates, per kind of invoiced item - Ability to configure multiple VAT rates, per kind of invoiced item
- Ability to export the collected VAT, by rates, to a CSV file - Ability to export the collected VAT, by rates, to a CSV file

View File

@ -9,6 +9,8 @@ RUN apk update && apk upgrade && \
curl \ curl \
nodejs \ nodejs \
yarn \ yarn \
git \
openssh \
imagemagick \ imagemagick \
supervisor \ supervisor \
tzdata \ tzdata \
@ -26,7 +28,6 @@ RUN apk update && apk upgrade && \
alpine-sdk \ alpine-sdk \
build-base \ build-base \
linux-headers \ linux-headers \
git \
patch patch
RUN gem install bundler RUN gem install bundler

View File

@ -7,8 +7,8 @@ gem 'rails', '~> 5.2.4'
# Used by rails 5.2 to reduce the app boot time by over 50% # Used by rails 5.2 to reduce the app boot time by over 50%
gem 'bootsnap' gem 'bootsnap'
# Use Puma as web server # Use Puma as web server
gem 'puma', '4.3.9' gem 'puma', '4.3.11'
gem 'webpacker', '~> 5.x' gem 'shakapacker', '6.2.0'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.5' gem 'jbuilder', '~> 2.5'
@ -90,8 +90,8 @@ gem 'aasm'
# Background job processing # Background job processing
gem 'sidekiq', '>= 6.0.7' gem 'sidekiq', '>= 6.0.7'
# Recurring jobs for Sidekiq # Recurring jobs for Sidekiq
gem 'sidekiq-cron' gem 'sidekiq-scheduler'
gem 'sidekiq-unique-jobs', '~> 6.0.22' gem 'sidekiq-unique-jobs', '~> 7.1.15'
gem 'stripe', '5.29.0' gem 'stripe', '5.29.0'

View File

@ -4,46 +4,46 @@ GEM
Ascii85 (1.0.3) Ascii85 (1.0.3)
aasm (5.0.8) aasm (5.0.8)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
actioncable (5.2.6) actioncable (5.2.6.3)
actionpack (= 5.2.6) actionpack (= 5.2.6.3)
nio4r (~> 2.0) nio4r (~> 2.0)
websocket-driver (>= 0.6.1) websocket-driver (>= 0.6.1)
actionmailer (5.2.6) actionmailer (5.2.6.3)
actionpack (= 5.2.6) actionpack (= 5.2.6.3)
actionview (= 5.2.6) actionview (= 5.2.6.3)
activejob (= 5.2.6) activejob (= 5.2.6.3)
mail (~> 2.5, >= 2.5.4) mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
actionpack (5.2.6) actionpack (5.2.6.3)
actionview (= 5.2.6) actionview (= 5.2.6.3)
activesupport (= 5.2.6) activesupport (= 5.2.6.3)
rack (~> 2.0, >= 2.0.8) rack (~> 2.0, >= 2.0.8)
rack-test (>= 0.6.3) rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2) rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionpack-page_caching (1.2.2) actionpack-page_caching (1.2.2)
actionpack (>= 5.0.0) actionpack (>= 5.0.0)
actionview (5.2.6) actionview (5.2.6.3)
activesupport (= 5.2.6) activesupport (= 5.2.6.3)
builder (~> 3.1) builder (~> 3.1)
erubi (~> 1.4) erubi (~> 1.4)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.3) rails-html-sanitizer (~> 1.0, >= 1.0.3)
active_record_query_trace (1.7) active_record_query_trace (1.7)
activejob (5.2.6) activejob (5.2.6.3)
activesupport (= 5.2.6) activesupport (= 5.2.6.3)
globalid (>= 0.3.6) globalid (>= 0.3.6)
activemodel (5.2.6) activemodel (5.2.6.3)
activesupport (= 5.2.6) activesupport (= 5.2.6.3)
activerecord (5.2.6) activerecord (5.2.6.3)
activemodel (= 5.2.6) activemodel (= 5.2.6.3)
activesupport (= 5.2.6) activesupport (= 5.2.6.3)
arel (>= 9.0) arel (>= 9.0)
activestorage (5.2.6) activestorage (5.2.6.3)
actionpack (= 5.2.6) actionpack (= 5.2.6.3)
activerecord (= 5.2.6) activerecord (= 5.2.6.3)
marcel (~> 1.0.0) marcel (~> 1.0.0)
activesupport (5.2.6) activesupport (5.2.6.3)
concurrent-ruby (~> 1.0, >= 1.0.2) concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2) i18n (>= 0.7, < 2)
minitest (~> 5.1) minitest (~> 5.1)
@ -66,6 +66,9 @@ GEM
bindex (0.8.1) bindex (0.8.1)
bootsnap (1.4.6) bootsnap (1.4.6)
msgpack (~> 1.0) msgpack (~> 1.0)
brpoplpush-redis_script (0.1.2)
concurrent-ruby (~> 1.0, >= 1.0.5)
redis (>= 1.0, <= 5.0)
builder (3.2.4) builder (3.2.4)
bullet (7.0.0) bullet (7.0.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
@ -91,7 +94,7 @@ GEM
cldr-plurals-runtime-rb (1.0.1) cldr-plurals-runtime-rb (1.0.1)
coercible (1.0.0) coercible (1.0.0)
descendants_tracker (~> 0.0.1) descendants_tracker (~> 0.0.1)
concurrent-ruby (1.1.8) concurrent-ruby (1.1.9)
connection_pool (2.2.5) connection_pool (2.2.5)
coveralls_reborn (0.18.0) coveralls_reborn (0.18.0)
simplecov (>= 0.18.1, < 0.20.0) simplecov (>= 0.18.1, < 0.20.0)
@ -115,6 +118,7 @@ GEM
dotenv-rails (2.7.5) dotenv-rails (2.7.5)
dotenv (= 2.7.5) dotenv (= 2.7.5)
railties (>= 3.2, < 6.1) railties (>= 3.2, < 6.1)
e2mmap (0.1.0)
elasticsearch (5.0.5) elasticsearch (5.0.5)
elasticsearch-api (= 5.0.5) elasticsearch-api (= 5.0.5)
elasticsearch-transport (= 5.0.5) elasticsearch-transport (= 5.0.5)
@ -137,36 +141,36 @@ GEM
multi_json multi_json
equalizer (0.0.11) equalizer (0.0.11)
erubi (1.10.0) erubi (1.10.0)
et-orbi (1.2.1) et-orbi (1.2.7)
tzinfo tzinfo
faker (2.10.2) faker (2.10.2)
i18n (>= 1.6, < 2) i18n (>= 1.6, < 2)
faraday (0.17.3) faraday (0.17.3)
multipart-post (>= 1.2, < 3) multipart-post (>= 1.2, < 3)
ffi (1.15.4) ffi (1.15.5)
foreman (0.87.0) foreman (0.87.0)
forgery (0.7.0) forgery (0.7.0)
friendly_id (5.1.0) friendly_id (5.1.0)
activerecord (>= 4.0.0) activerecord (>= 4.0.0)
fugit (1.3.1) fugit (1.5.2)
et-orbi (~> 1.1, >= 1.1.8) et-orbi (~> 1.1, >= 1.1.8)
raabro (~> 1.1) raabro (~> 1.4)
globalid (0.4.2) globalid (1.0.0)
activesupport (>= 4.2.0) activesupport (>= 5.0)
hashdiff (1.0.1) hashdiff (1.0.1)
hashery (2.1.2) hashery (2.1.2)
hashie (4.1.0) hashie (4.1.0)
htmlentities (4.3.4) htmlentities (4.3.4)
httparty (0.18.1) httparty (0.20.0)
mime-types (~> 3.0) mime-types (~> 3.0)
multi_xml (>= 0.5.2) multi_xml (>= 0.5.2)
i18n (1.8.10) i18n (1.10.0)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
icalendar (2.5.3) icalendar (2.5.3)
ice_cube (~> 0.16) ice_cube (~> 0.16)
ice_cube (0.16.3) ice_cube (0.16.3)
ice_nine (0.11.2) ice_nine (0.11.2)
image_processing (1.12.1) image_processing (1.12.2)
mini_magick (>= 4.9.5, < 5) mini_magick (>= 4.9.5, < 5)
ruby-vips (>= 2.0.17, < 3) ruby-vips (>= 2.0.17, < 3)
jaro_winkler (1.5.4) jaro_winkler (1.5.4)
@ -193,25 +197,25 @@ GEM
listen (3.0.8) listen (3.0.8)
rb-fsevent (~> 0.9, >= 0.9.4) rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7) rb-inotify (~> 0.9, >= 0.9.7)
loofah (2.9.1) loofah (2.14.0)
crass (~> 1.0.2) crass (~> 1.0.2)
nokogiri (>= 1.5.9) nokogiri (>= 1.5.9)
mail (2.7.1) mail (2.7.1)
mini_mime (>= 0.1.1) mini_mime (>= 0.1.1)
marcel (1.0.1) marcel (1.0.2)
message_format (0.0.6) message_format (0.0.6)
twitter_cldr (~> 5.0) twitter_cldr (~> 5.0)
method_source (1.0.0) method_source (1.0.0)
mime-types (3.3.1) mime-types (3.4.1)
mime-types-data (~> 3.2015) mime-types-data (~> 3.2015)
mime-types-data (3.2021.0225) mime-types-data (3.2022.0105)
mimemagic (0.4.3) mimemagic (0.4.3)
nokogiri (~> 1) nokogiri (~> 1)
rake rake
mini_magick (4.10.1) mini_magick (4.10.1)
mini_mime (1.1.0) mini_mime (1.1.2)
mini_portile2 (2.6.1) mini_portile2 (2.8.0)
minitest (5.14.4) minitest (5.15.0)
minitest-reporters (1.4.2) minitest-reporters (1.4.2)
ansi ansi
builder builder
@ -222,8 +226,8 @@ GEM
multi_xml (0.6.0) multi_xml (0.6.0)
multipart-post (2.1.1) multipart-post (2.1.1)
nio4r (2.5.8) nio4r (2.5.8)
nokogiri (1.12.5) nokogiri (1.13.3)
mini_portile2 (~> 2.6.1) mini_portile2 (~> 2.8.0)
racc (~> 1.4) racc (~> 1.4)
notify_with (0.0.2) notify_with (0.0.2)
jbuilder (~> 2.0) jbuilder (~> 2.0)
@ -245,8 +249,8 @@ GEM
omniauth-rails_csrf_protection (0.1.2) omniauth-rails_csrf_protection (0.1.2)
actionpack (>= 4.2) actionpack (>= 4.2)
omniauth (>= 1.3.1) omniauth (>= 1.3.1)
openlab_ruby (0.0.5) openlab_ruby (0.0.7)
httparty (~> 0.13) httparty (~> 0.20)
orm_adapter (0.5.0) orm_adapter (0.5.0)
parallel (1.19.1) parallel (1.19.1)
parser (2.7.0.4) parser (2.7.0.4)
@ -269,35 +273,35 @@ GEM
prawn-table (0.2.2) prawn-table (0.2.2)
prawn (>= 1.3.0, < 3.0.0) prawn (>= 1.3.0, < 3.0.0)
public_suffix (4.0.6) public_suffix (4.0.6)
puma (4.3.9) puma (4.3.11)
nio4r (~> 2.0) nio4r (~> 2.0)
pundit (2.1.0) pundit (2.1.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
raabro (1.1.6) raabro (1.4.0)
racc (1.5.2) racc (1.6.0)
rack (2.2.3) rack (2.2.3)
rack-proxy (0.6.5) rack-proxy (0.7.2)
rack rack
rack-test (1.1.0) rack-test (1.1.0)
rack (>= 1.0, < 3) rack (>= 1.0, < 3)
railroady (1.5.3) railroady (1.5.3)
rails (5.2.6) rails (5.2.6.3)
actioncable (= 5.2.6) actioncable (= 5.2.6.3)
actionmailer (= 5.2.6) actionmailer (= 5.2.6.3)
actionpack (= 5.2.6) actionpack (= 5.2.6.3)
actionview (= 5.2.6) actionview (= 5.2.6.3)
activejob (= 5.2.6) activejob (= 5.2.6.3)
activemodel (= 5.2.6) activemodel (= 5.2.6.3)
activerecord (= 5.2.6) activerecord (= 5.2.6.3)
activestorage (= 5.2.6) activestorage (= 5.2.6.3)
activesupport (= 5.2.6) activesupport (= 5.2.6.3)
bundler (>= 1.3.0) bundler (>= 1.3.0)
railties (= 5.2.6) railties (= 5.2.6.3)
sprockets-rails (>= 2.0.0) sprockets-rails (>= 2.0.0)
rails-dom-testing (2.0.3) rails-dom-testing (2.0.3)
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
nokogiri (>= 1.6) nokogiri (>= 1.6)
rails-html-sanitizer (1.3.0) rails-html-sanitizer (1.4.2)
loofah (~> 2.3) loofah (~> 2.3)
rails-observers (0.1.5) rails-observers (0.1.5)
activemodel (>= 4.0) activemodel (>= 4.0)
@ -306,14 +310,14 @@ GEM
rails_stdout_logging rails_stdout_logging
rails_serve_static_assets (0.0.5) rails_serve_static_assets (0.0.5)
rails_stdout_logging (0.0.5) rails_stdout_logging (0.0.5)
railties (5.2.6) railties (5.2.6.3)
actionpack (= 5.2.6) actionpack (= 5.2.6.3)
activesupport (= 5.2.6) activesupport (= 5.2.6.3)
method_source method_source
rake (>= 0.8.7) rake (>= 0.8.7)
thor (>= 0.19.0, < 2.0) thor (>= 0.19.0, < 2.0)
rainbow (3.0.0) rainbow (3.0.0)
rake (13.0.3) rake (13.0.6)
rb-fsevent (0.10.3) rb-fsevent (0.10.3)
rb-inotify (0.10.1) rb-inotify (0.10.1)
ffi (~> 1.0) ffi (~> 1.0)
@ -321,7 +325,7 @@ GEM
recurrence (1.3.0) recurrence (1.3.0)
activesupport activesupport
i18n i18n
redis (4.4.0) redis (4.6.0)
repost (0.3.2) repost (0.3.2)
responders (2.4.1) responders (2.4.1)
actionpack (>= 4.2.0, < 6.0) actionpack (>= 4.2.0, < 6.0)
@ -337,31 +341,43 @@ GEM
unicode-display_width (~> 1.4.0) unicode-display_width (~> 1.4.0)
ruby-progressbar (1.10.1) ruby-progressbar (1.10.1)
ruby-rc4 (0.1.5) ruby-rc4 (0.1.5)
ruby-vips (2.0.17) ruby-vips (2.1.4)
ffi (~> 1.9) ffi (~> 1.12)
rubyXL (3.4.14) rubyXL (3.4.14)
nokogiri (>= 1.10.8) nokogiri (>= 1.10.8)
rubyzip (>= 1.3.0) rubyzip (>= 1.3.0)
rubyzip (2.3.0) rubyzip (2.3.0)
rufus-scheduler (3.8.1)
fugit (~> 1.1, >= 1.1.6)
safe_yaml (1.0.5) safe_yaml (1.0.5)
sassc (2.4.0) sassc (2.4.0)
ffi (~> 1.9) ffi (~> 1.9)
seed_dump (3.3.1) seed_dump (3.3.1)
activerecord (>= 4) activerecord (>= 4)
activesupport (>= 4) activesupport (>= 4)
semantic_range (2.3.0) semantic_range (3.0.0)
sha3 (1.0.1) sha3 (1.0.1)
sidekiq (6.2.1) shakapacker (6.2.0)
activesupport (>= 5.2)
rack-proxy (>= 0.6.1)
railties (>= 5.2)
semantic_range (>= 2.3.0)
sidekiq (6.4.1)
connection_pool (>= 2.2.2) connection_pool (>= 2.2.2)
rack (~> 2.0) rack (~> 2.0)
redis (>= 4.2.0) redis (>= 4.2.0)
sidekiq-cron (1.1.0) sidekiq-scheduler (3.1.1)
fugit (~> 1.1) e2mmap
sidekiq (>= 4.2.1) redis (>= 3, < 5)
sidekiq-unique-jobs (6.0.22) rufus-scheduler (~> 3.2)
sidekiq (>= 3)
thwait
tilt (>= 1.4.0)
sidekiq-unique-jobs (7.1.15)
brpoplpush-redis_script (> 0.1.1, <= 2.0.0)
concurrent-ruby (~> 1.0, >= 1.0.5) concurrent-ruby (~> 1.0, >= 1.0.5)
sidekiq (>= 4.0, < 7.0) sidekiq (>= 5.0, < 8.0)
thor (~> 0) thor (>= 0.20, < 3.0)
simplecov (0.19.0) simplecov (0.19.0)
docile (~> 1.1) docile (~> 1.1)
simplecov-html (~> 0.11) simplecov-html (~> 0.11)
@ -371,12 +387,12 @@ GEM
spring-watcher-listen (2.0.1) spring-watcher-listen (2.0.1)
listen (>= 2.7, < 4.0) listen (>= 2.7, < 4.0)
spring (>= 1.2, < 3.0) spring (>= 1.2, < 3.0)
sprockets (4.0.2) sprockets (4.0.3)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
rack (> 1, < 3) rack (> 1, < 3)
sprockets-rails (3.2.2) sprockets-rails (3.4.2)
actionpack (>= 4.0) actionpack (>= 5.2)
activesupport (>= 4.0) activesupport (>= 5.2)
sprockets (>= 3.0.0) sprockets (>= 3.0.0)
ssrf_filter (1.0.7) ssrf_filter (1.0.7)
stripe (5.29.0) stripe (5.29.0)
@ -387,6 +403,9 @@ GEM
tins (~> 1.0) tins (~> 1.0)
thor (0.20.3) thor (0.20.3)
thread_safe (0.3.6) thread_safe (0.3.6)
thwait (0.2.0)
e2mmap
tilt (2.0.10)
tins (1.25.0) tins (1.25.0)
sync sync
ttfunk (1.5.1) ttfunk (1.5.1)
@ -417,12 +436,7 @@ GEM
addressable (>= 2.3.6) addressable (>= 2.3.6)
crack (>= 0.3.2) crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0) hashdiff (>= 0.4.0, < 2.0.0)
webpacker (5.2.1) websocket-driver (0.7.5)
activesupport (>= 5.2)
rack-proxy (>= 0.6.1)
railties (>= 5.2)
semantic_range (>= 2.3.0)
websocket-driver (0.7.3)
websocket-extensions (>= 0.1.0) websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5) websocket-extensions (0.1.5)
@ -475,7 +489,7 @@ DEPENDENCIES
pg_search pg_search
prawn prawn
prawn-table prawn-table
puma (= 4.3.9) puma (= 4.3.11)
pundit pundit
railroady railroady
rails (~> 5.2.4) rails (~> 5.2.4)
@ -492,9 +506,10 @@ DEPENDENCIES
sassc sassc
seed_dump seed_dump
sha3 sha3
shakapacker (= 6.2.0)
sidekiq (>= 6.0.7) sidekiq (>= 6.0.7)
sidekiq-cron sidekiq-scheduler
sidekiq-unique-jobs (~> 6.0.22) sidekiq-unique-jobs (~> 7.1.15)
spring spring
spring-watcher-listen (~> 2.0.0) spring-watcher-listen (~> 2.0.0)
stripe (= 5.29.0) stripe (= 5.29.0)
@ -503,7 +518,6 @@ DEPENDENCIES
vcr (= 6.0.0) vcr (= 6.0.0)
web-console (>= 3.3.0) web-console (>= 3.3.0)
webmock webmock
webpacker (~> 5.x)
BUNDLED WITH BUNDLED WITH
2.2.19 2.2.21

View File

@ -1,4 +1,3 @@
web: bundle exec rails server puma -p $PORT web: bundle exec rails server puma -p $PORT
worker: bundle exec sidekiq -C ./config/sidekiq.yml worker: bundle exec sidekiq -C ./config/sidekiq.yml
wp-client: bin/webpack-dev-server webpack: bin/webpacker-dev-server
wp-server: SERVER_BUNDLE_ONLY=yes bin/webpack --watch

View File

@ -83,7 +83,7 @@ class API::AuthProvidersController < API::ApiController
params.require(:auth_provider) params.require(:auth_provider)
.permit(:name, :providable_type, .permit(:name, :providable_type,
providable_attributes: [:id, :base_url, :token_endpoint, :authorization_endpoint, :logout_endpoint, providable_attributes: [:id, :base_url, :token_endpoint, :authorization_endpoint, :logout_endpoint,
:profile_url, :client_id, :client_secret, :profile_url, :client_id, :client_secret, :scopes,
o_auth2_mappings_attributes: [:id, :local_model, :local_field, :api_field, o_auth2_mappings_attributes: [:id, :local_model, :local_field, :api_field,
:api_endpoint, :api_data_type, :_destroy, :api_endpoint, :api_data_type, :_destroy,
transformation: [:type, :format, :true_value, transformation: [:type, :format, :true_value,

View File

@ -6,7 +6,7 @@ class API::OpenlabProjectsController < API::ApiController
before_action :init_openlab before_action :init_openlab
def index def index
render json: @projets.search(params[:q], page: params[:page], per_page: params[:per_page]).response.body render json: @projects.search(params[:q], page: params[:page], per_page: params[:per_page]).response.body
rescue StandardError rescue StandardError
render json: { errors: ['service unavailable'] } render json: { errors: ['service unavailable'] }
end end
@ -15,6 +15,6 @@ class API::OpenlabProjectsController < API::ApiController
def init_openlab def init_openlab
client = Openlab::Client.new(app_secret: Setting.get('openlab_app_secret')) client = Openlab::Client.new(app_secret: Setting.get('openlab_app_secret'))
@projets = Openlab::Projects.new(client) @projects = Openlab::Projects.new(client)
end end
end end

View File

@ -4,7 +4,7 @@ import 'regenerator-runtime/runtime';
import 'jquery'; import 'jquery';
import {} from 'jquery-ujs'; import {} from 'jquery-ujs';
import 'bootstrap-sass'; import 'bootstrap-sass';
import '../src/javascript/lib/polyfill'; import 'src/javascript/lib/polyfill';
import 'angular'; import 'angular';
<% unless Rails.application.secrets.angular_locale == 'en-us' %> <% unless Rails.application.secrets.angular_locale == 'en-us' %>
import 'angular-i18n/angular-locale_<%= Rails.application.secrets.angular_locale %>.js'; import 'angular-i18n/angular-locale_<%= Rails.application.secrets.angular_locale %>.js';
@ -31,16 +31,15 @@ import 'ngUpload';
import 'jasny-bootstrap/js/fileinput'; import 'jasny-bootstrap/js/fileinput';
import 'holderjs'; import 'holderjs';
import 'AngularDevise'; import 'AngularDevise';
import '../src/javascript/lib/devise-modal'; import 'src/javascript/lib/devise-modal';
import 'angular-growl-v2'; import 'angular-growl-v2';
import 'angular-xeditable'; import 'angular-xeditable';
import 'checklist-model/checklist-model'; import 'checklist-model/checklist-model';
import 'angular-unsavedchanges/lib/unsavedChanges'; import 'angular-unsavedchanges/lib/unsavedChanges';
import 'angular-loading-bar/src/loading-bar'; import 'angular-loading-bar/src/loading-bar';
import 'angular-scroll/angular-scroll'; import 'angular-scroll/angular-scroll';
import 'angular-google-analytics/dist/angular-google-analytics'; import 'src/javascript/lib/dirDisqus';
import '../src/javascript/lib/dirDisqus'; import 'src/javascript/lib/humanize';
import '../src/javascript/lib/humanize';
import 'underscore/underscore'; import 'underscore/underscore';
import 'elasticsearch-browser/elasticsearch.angular'; import 'elasticsearch-browser/elasticsearch.angular';
import 'd3/d3'; import 'd3/d3';
@ -56,7 +55,7 @@ import 'summernote';
import 'summernote/lang/summernote-<%= Rails.application.secrets.summernote_locale %>.js'; import 'summernote/lang/summernote-<%= Rails.application.secrets.summernote_locale %>.js';
<% end %> <% end %>
import 'angular-summernote/dist/angular-summernote'; import 'angular-summernote/dist/angular-summernote';
import '../src/javascript/lib/summernote-ext-nugget'; import 'src/javascript/lib/summernote-ext-nugget';
import '@claviska/jquery-minicolors/jquery.minicolors.js'; import '@claviska/jquery-minicolors/jquery.minicolors.js';
import 'angular-minicolors/angular-minicolors.js'; import 'angular-minicolors/angular-minicolors.js';
import 'angular-translate/dist/angular-translate'; import 'angular-translate/dist/angular-translate';
@ -80,18 +79,18 @@ import 'angular-ui-tour/app/angular-ui-tour';
import '@fortawesome/fontawesome-free'; import '@fortawesome/fontawesome-free';
import '@fortawesome/fontawesome-free/js/v4-shims'; import '@fortawesome/fontawesome-free/js/v4-shims';
require('../src/javascript/app.js'); require('src/javascript/app.js');
require('../src/javascript/router.js'); require('src/javascript/router.js');
require('../src/javascript/plugins.js.erb'); require('src/javascript/plugins.js.erb');
function importAll (r) { r.keys().forEach(r); } function importAll (r) { r.keys().forEach(r); }
importAll(require.context('../src/javascript/components/', true, /.*/)); importAll(require.context('src/javascript/components/', true, /.*/));
importAll(require.context('../src/javascript/controllers/', true, /.*/)); importAll(require.context('src/javascript/controllers/', true, /.*/));
importAll(require.context('../src/javascript/services/', true, /.*/)); importAll(require.context('src/javascript/services/', true, /.*/));
importAll(require.context('../src/javascript/directives/', true, /.*/)); importAll(require.context('src/javascript/directives/', true, /.*/));
importAll(require.context('../src/javascript/filters/', true, /.*/)); importAll(require.context('src/javascript/filters/', true, /.*/));
importAll(require.context('../src/javascript/typings/', true, /.*/)); importAll(require.context('src/javascript/typings/', true, /.*/));
importAll(require.context('../images', true)); importAll(require.context('images', true));
importAll(require.context('../templates', true)); importAll(require.context('templates', true));

View File

@ -15,4 +15,4 @@
@import '~angular-aside/dist/css/angular-aside'; @import '~angular-aside/dist/css/angular-aside';
@import '~codemirror/lib/codemirror'; @import '~codemirror/lib/codemirror';
@import '../src/stylesheets/application.scss'; @import 'src/stylesheets/application.scss';

View File

@ -1,2 +0,0 @@
@import '../src/stylesheets/app.printer';

View File

@ -0,0 +1,2 @@
@import 'src/stylesheets/app.printer';

View File

@ -3,7 +3,7 @@ import { AxiosResponse } from 'axios';
import { Space } from '../models/space'; import { Space } from '../models/space';
export default class SpaceAPI { export default class SpaceAPI {
static async index (): Promise<Array<any>> { static async index (): Promise<Array<Space>> {
const res: AxiosResponse<Array<Space>> = await apiClient.get('/api/spaces'); const res: AxiosResponse<Array<Space>> = await apiClient.get('/api/spaces');
return res?.data; return res?.data;
} }
@ -12,5 +12,4 @@ export default class SpaceAPI {
const res: AxiosResponse<Space> = await apiClient.get(`/api/spaces/${id}`); const res: AxiosResponse<Space> = await apiClient.get(`/api/spaces/${id}`);
return res?.data; return res?.data;
} }
} }

View File

@ -5,6 +5,7 @@
* creating namespaces and moduled for controllers, filters, services, and directives. * creating namespaces and moduled for controllers, filters, services, and directives.
*/ */
// eslint-disable-next-line no-var -- Application is a global variable.
var Application = Application || {}; var Application = Application || {};
Application.Components = angular.module('application.components', []); Application.Components = angular.module('application.components', []);
@ -17,22 +18,17 @@ angular.module('application', ['ngCookies', 'ngResource', 'ngSanitize', 'ui.rout
'ngUpload', 'duScroll', 'application.filters', 'application.services', 'application.directives', 'ngUpload', 'duScroll', 'application.filters', 'application.services', 'application.directives',
'frapontillo.bootstrap-switch', 'application.controllers', 'application.router', 'application.components', 'frapontillo.bootstrap-switch', 'application.controllers', 'application.router', 'application.components',
'ui.select', 'ui.calendar', 'angularMoment', 'Devise', 'angular-growl', 'xeditable', 'ui.select', 'ui.calendar', 'angularMoment', 'Devise', 'angular-growl', 'xeditable',
'checklist-model', 'unsavedChanges', 'angular-loading-bar', 'ngTouch', 'angular-google-analytics', 'checklist-model', 'unsavedChanges', 'angular-loading-bar', 'ngTouch',
'angularUtils.directives.dirDisqus', 'summernote', 'elasticsearch', 'angular-medium-editor', 'naif.base64', 'angularUtils.directives.dirDisqus', 'summernote', 'elasticsearch', 'angular-medium-editor', 'naif.base64',
'minicolors', 'pascalprecht.translate', 'ngFitText', 'ngAside', 'ngCapsLock', 'vcRecaptcha', 'ui.codemirror', 'minicolors', 'pascalprecht.translate', 'ngFitText', 'ngAside', 'ngCapsLock', 'vcRecaptcha', 'ui.codemirror',
'bm.uiTour']) 'bm.uiTour'])
.config(['$httpProvider', 'AuthProvider', 'growlProvider', 'unsavedWarningsConfigProvider', 'AnalyticsProvider', 'uibDatepickerPopupConfig', '$provide', '$translateProvider', 'TourConfigProvider', .config(['$httpProvider', 'AuthProvider', 'growlProvider', 'unsavedWarningsConfigProvider', 'uibDatepickerPopupConfig', '$provide', '$translateProvider', 'TourConfigProvider', '$sceDelegateProvider',
function ($httpProvider, AuthProvider, growlProvider, unsavedWarningsConfigProvider, AnalyticsProvider, uibDatepickerPopupConfig, $provide, $translateProvider, TourConfigProvider) { function ($httpProvider, AuthProvider, growlProvider, unsavedWarningsConfigProvider, uibDatepickerPopupConfig, $provide, $translateProvider, TourConfigProvider, $sceDelegateProvider) {
// Google analytics // Google analytics
// first we check the user acceptance // first we check the user acceptance
const cookiesConsent = document.cookie.replace(/(?:(?:^|.*;\s*)fab-manager-cookies-consent\s*=\s*([^;]*).*$)|^.*$/, '$1'); const cookiesConsent = document.cookie.replace(/(?:(?:^|.*;\s*)fab-manager-cookies-consent\s*=\s*([^;]*).*$)|^.*$/, '$1');
if (cookiesConsent === 'accept') { if (cookiesConsent === 'accept') {
AnalyticsProvider.setAccount(Fablab.trackingId); GTM.enableAnalytics(Fablab.trackingId);
// track all routes (or not)
AnalyticsProvider.trackPages(true);
AnalyticsProvider.setDomainName(Fablab.baseHostUrl);
AnalyticsProvider.useAnalytics(true);
AnalyticsProvider.setPageEvent('$stateChangeSuccess');
} else { } else {
// if the cookies were not explicitly accepted, delete them // if the cookies were not explicitly accepted, delete them
document.cookie = '_ga=; expires=Thu, 01 Jan 1970 00:00:00 GMT'; document.cookie = '_ga=; expires=Thu, 01 Jan 1970 00:00:00 GMT';
@ -65,8 +61,10 @@ angular.module('application', ['ngCookies', 'ngResource', 'ngSanitize', 'ui.rout
$translateProvider.preferredLanguage(Fablab.locale); $translateProvider.preferredLanguage(Fablab.locale);
// End the tour when the user clicks the forward or back buttons of the browser // End the tour when the user clicks the forward or back buttons of the browser
TourConfigProvider.enableNavigationInterceptors(); TourConfigProvider.enableNavigationInterceptors();
}]).run(['$rootScope', '$log', 'Auth', 'amMoment', '$state', 'editableOptions', 'Analytics',
function ($rootScope, $log, Auth, amMoment, $state, editableOptions, Analytics) { $sceDelegateProvider.resourceUrlWhitelist(['self']);
}]).run(['$rootScope', '$transitions', '$log', 'Auth', 'amMoment', '$state', 'editableOptions',
function ($rootScope, $transitions, $log, Auth, amMoment, $state, editableOptions) {
// Angular-moment (date-time manipulations library) // Angular-moment (date-time manipulations library)
amMoment.changeLocale(Fablab.moment_locale); amMoment.changeLocale(Fablab.moment_locale);
@ -75,9 +73,12 @@ angular.module('application', ['ngCookies', 'ngResource', 'ngSanitize', 'ui.rout
// Alter the UI-Router's $state, registering into some information concerning the previous $state. // Alter the UI-Router's $state, registering into some information concerning the previous $state.
// This is used to allow the user to navigate to the previous state // This is used to allow the user to navigate to the previous state
$rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams) { $transitions.onSuccess({ }, function (trans) {
$state.prevState = fromState; $state.prevState = trans.$from().name;
$state.prevParams = fromParams; $state.prevParams = trans.$from().params;
const path = trans.router.stateService.href(trans.$to(), {}, { absolute: true });
GTM.trackPage(path, trans.$to().name);
}); });
// Global function to allow the user to navigate to the previous screen (ie. $state). // Global function to allow the user to navigate to the previous screen (ie. $state).
@ -85,7 +86,7 @@ angular.module('application', ['ngCookies', 'ngResource', 'ngSanitize', 'ui.rout
$rootScope.backPrevLocation = function (event) { $rootScope.backPrevLocation = function (event) {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
if ($state.prevState.name === '') { if ($state.prevState === '') {
$state.prevState = 'app.public.home'; $state.prevState = 'app.public.home';
} }
$state.go($state.prevState, $state.prevParams); $state.go($state.prevState, $state.prevParams);
@ -112,9 +113,9 @@ angular.module('application', ['ngCookies', 'ngResource', 'ngSanitize', 'ui.rout
// Prevent the usage of the application for members with incomplete profiles: they will be redirected to // Prevent the usage of the application for members with incomplete profiles: they will be redirected to
// the 'profile completion' page. This is especially useful for user's accounts imported through SSO. // the 'profile completion' page. This is especially useful for user's accounts imported through SSO.
$rootScope.$on('$stateChangeStart', function (event, toState) { $transitions.onStart({}, function (trans) {
Auth.currentUser().then(function (currentUser) { Auth.currentUser().then(function (currentUser) {
if (currentUser.need_completion && toState.name !== 'app.logged.profileCompletion') { if (currentUser.need_completion && trans.$to().name !== 'app.logged.profileCompletion') {
$state.go('app.logged.profileCompletion'); $state.go('app.logged.profileCompletion');
} }
}).catch(() => { }).catch(() => {
@ -122,10 +123,6 @@ angular.module('application', ['ngCookies', 'ngResource', 'ngSanitize', 'ui.rout
}); });
}); });
// This code does nothing but it is here to remember to not remove the Analytics dependency,
// see https://github.com/revolunet/angular-google-analytics#automatic-page-view-tracking
Analytics.pageView();
/** /**
* This helper method builds and return an array containing every integers between * This helper method builds and return an array containing every integers between
* the provided start and end. * the provided start and end.

View File

@ -1,5 +1,6 @@
import React, { ReactNode } from 'react'; import React, { ReactNode } from 'react';
import { FieldErrors, UseFormRegister, Validate } from 'react-hook-form'; import { FieldErrors, UseFormRegister, Validate } from 'react-hook-form';
import { FieldValues } from 'react-hook-form/dist/types/fields';
type inputType = string|number|readonly string []; type inputType = string|number|readonly string [];
type ruleTypes = { type ruleTypes = {
@ -9,12 +10,12 @@ type ruleTypes = {
maxLenght?: number, maxLenght?: number,
min?: number, min?: number,
max?: number, max?: number,
validate?: Validate<any>; validate?: Validate<FieldValues>;
}; };
interface RHFInputProps { interface RHFInputProps {
id: string, id: string,
register: UseFormRegister<any>, register: UseFormRegister<FieldValues>,
label?: string, label?: string,
tooltip?: string, tooltip?: string,
defaultValue?: inputType, defaultValue?: inputType,

View File

@ -3,7 +3,7 @@ import { Node } from '@tiptap/core';
export interface IframeOptions { export interface IframeOptions {
allowFullscreen: boolean, allowFullscreen: boolean,
HTMLAttributes: { HTMLAttributes: {
[key: string]: any [key: string]: string
}, },
} }

View File

@ -14,6 +14,7 @@ import WalletAPI from '../../api/wallet';
import { Invoice } from '../../models/invoice'; import { Invoice } from '../../models/invoice';
import SettingAPI from '../../api/setting'; import SettingAPI from '../../api/setting';
import { SettingName } from '../../models/setting'; import { SettingName } from '../../models/setting';
import { GoogleTagManager } from '../../models/gtm';
import { ComputePriceResult } from '../../models/price'; import { ComputePriceResult } from '../../models/price';
import { Wallet } from '../../models/wallet'; import { Wallet } from '../../models/wallet';
import FormatLib from '../../lib/format'; import FormatLib from '../../lib/format';
@ -52,6 +53,8 @@ interface AbstractPaymentModalProps {
modalSize?: ModalSize, modalSize?: ModalSize,
} }
declare const GTM: GoogleTagManager;
/** /**
* This component is an abstract modal that must be extended by each payment gateway to include its payment form. * This component is an abstract modal that must be extended by each payment gateway to include its payment form.
* *
@ -90,7 +93,9 @@ export const AbstractPaymentModal: React.FC<AbstractPaymentModalProps> = ({ isOp
CustomAssetAPI.get(CustomAssetName.CgvFile).then(asset => setCgv(asset)); CustomAssetAPI.get(CustomAssetName.CgvFile).then(asset => setCgv(asset));
SettingAPI.get(SettingName.PaymentGateway).then((setting) => { SettingAPI.get(SettingName.PaymentGateway).then((setting) => {
// we capitalize the first letter of the name // we capitalize the first letter of the name
if (setting.value) {
setGateway(setting.value.replace(/^\w/, (c) => c.toUpperCase())); setGateway(setting.value.replace(/^\w/, (c) => c.toUpperCase()));
}
}); });
return () => { mounted.current = false; }; return () => { mounted.current = false; };
@ -154,6 +159,7 @@ export const AbstractPaymentModal: React.FC<AbstractPaymentModalProps> = ({ isOp
*/ */
const handleFormSuccess = async (result: Invoice|PaymentSchedule): Promise<void> => { const handleFormSuccess = async (result: Invoice|PaymentSchedule): Promise<void> => {
setSubmitState(false); setSubmitState(false);
GTM.trackPurchase(result.id, result.total);
afterSuccess(result); afterSuccess(result);
}; };

View File

@ -11,7 +11,7 @@ import { PaymentSchedule } from '../../../models/payment-schedule';
* A form component to collect the credit card details and to create the payment method on Stripe. * A form component to collect the credit card details and to create the payment method on Stripe.
* The form validation button must be created elsewhere, using the attribute form={formId}. * The form validation button must be created elsewhere, using the attribute form={formId}.
*/ */
export const StripeForm: React.FC<GatewayFormProps> = ({ onSubmit, onSuccess, onError, children, className, paymentSchedule = false, cart, customer, operator, formId }) => { export const StripeForm: React.FC<GatewayFormProps> = ({ onSubmit, onSuccess, onError, children, className, paymentSchedule = false, cart, formId }) => {
const { t } = useTranslation('shared'); const { t } = useTranslation('shared');
const stripe = useStripe(); const stripe = useStripe();

View File

@ -26,7 +26,6 @@ interface FreeExtendModalProps {
* Modal dialog shown to extend the current subscription of a customer, for free * Modal dialog shown to extend the current subscription of a customer, for free
*/ */
const FreeExtendModal: React.FC<FreeExtendModalProps> = ({ isOpen, toggleModal, subscription, customerId, onError, onSuccess }) => { const FreeExtendModal: React.FC<FreeExtendModalProps> = ({ isOpen, toggleModal, subscription, customerId, onError, onSuccess }) => {
// we do not render the modal if the subscription was not provided // we do not render the modal if the subscription was not provided
if (!subscription) return null; if (!subscription) return null;

View File

@ -318,8 +318,8 @@ Application.Controllers.controller('NewAuthenticationController', ['$scope', '$s
/** /**
* Page to edit an already added authentication provider * Page to edit an already added authentication provider
*/ */
Application.Controllers.controller('EditAuthenticationController', ['$scope', '$state', '$stateParams', '$rootScope', '$uibModal', 'dialogs', 'growl', 'providerPromise', 'mappingFieldsPromise', 'AuthProvider', '_t', Application.Controllers.controller('EditAuthenticationController', ['$scope', '$state', '$rootScope', '$uibModal', 'dialogs', 'growl', 'providerPromise', 'mappingFieldsPromise', 'AuthProvider', '_t',
function ($scope, $state, $stateParams, $rootScope, $uibModal, dialogs, growl, providerPromise, mappingFieldsPromise, AuthProvider, _t) { function ($scope, $state, $rootScope, $uibModal, dialogs, growl, providerPromise, mappingFieldsPromise, AuthProvider, _t) {
// parameters of the currently edited authentication provider // parameters of the currently edited authentication provider
$scope.provider = providerPromise; $scope.provider = providerPromise;

View File

@ -619,12 +619,12 @@ Application.Controllers.controller('NewEventController', ['$scope', '$state', 'C
/** /**
* Controller used in the events edition page * Controller used in the events edition page
*/ */
Application.Controllers.controller('EditEventController', ['$scope', '$state', '$stateParams', 'CSRF', 'eventPromise', 'categoriesPromise', 'themesPromise', 'ageRangesPromise', 'priceCategoriesPromise', '$uibModal', 'growl', '_t', Application.Controllers.controller('EditEventController', ['$scope', '$state', '$transition$', 'CSRF', 'eventPromise', 'categoriesPromise', 'themesPromise', 'ageRangesPromise', 'priceCategoriesPromise', '$uibModal', 'growl', '_t',
function ($scope, $state, $stateParams, CSRF, eventPromise, categoriesPromise, themesPromise, ageRangesPromise, priceCategoriesPromise, $uibModal, growl, _t) { function ($scope, $state, $transition$, CSRF, eventPromise, categoriesPromise, themesPromise, ageRangesPromise, priceCategoriesPromise, $uibModal, growl, _t) {
/* PUBLIC SCOPE */ /* PUBLIC SCOPE */
// API URL where the form will be posted // API URL where the form will be posted
$scope.actionUrl = `/api/events/${$stateParams.id}`; $scope.actionUrl = `/api/events/${$transition$.params().id}`;
// Form action on the above URL // Form action on the above URL
$scope.method = 'put'; $scope.method = 'put';

View File

@ -4,7 +4,7 @@
no-undef, no-undef,
no-unreachable, no-unreachable,
no-unused-vars, no-unused-vars,
standard/no-callback-literal, n/no-callback-literal,
*/ */
// TODO: This file was created by bulk-decaffeinate. // TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint. // Fix any style issues and re-enable lint.
@ -17,8 +17,8 @@
*/ */
'use strict'; 'use strict';
Application.Controllers.controller('GraphsController', ['$scope', '$state', '$rootScope', 'es', 'Statistics', '_t', Application.Controllers.controller('GraphsController', ['$scope', '$state', '$rootScope', '$transitions', 'es', 'Statistics', '_t',
function ($scope, $state, $rootScope, es, Statistics, _t) { function ($scope, $state, $rootScope, $transitions, es, Statistics, _t) {
/* PRIVATE STATIC CONSTANTS */ /* PRIVATE STATIC CONSTANTS */
// height of the HTML/SVG charts elements in pixels // height of the HTML/SVG charts elements in pixels
@ -167,8 +167,8 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
// workaround for angular-bootstrap::tabs behavior: on tab deletion, another tab will be selected // workaround for angular-bootstrap::tabs behavior: on tab deletion, another tab will be selected
// which will cause every tabs to reload, one by one, when the view is closed // which will cause every tabs to reload, one by one, when the view is closed
$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) { $transitions.onStart({ to: 'app.admin.stats_graphs' }, function (trans) {
if ((fromState.name === 'app.admin.stats_graphs') && (Object.keys(fromParams).length === 0)) { if (Object.keys(trans.from().params).length === 0) {
return $scope.preventRefresh = true; return $scope.preventRefresh = true;
} }
}); });
@ -179,7 +179,7 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
* @param $event {Object} jQuery event object * @param $event {Object} jQuery event object
* @param datePicker {Object} settings object of the concerned datepicker. Must have an 'opened' property * @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.preventDefault();
$event.stopPropagation(); $event.stopPropagation();
return datePicker.opened = !datePicker.opened; return datePicker.opened = !datePicker.opened;
@ -188,7 +188,7 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
/** /**
* Query elasticSearch according to the current parameters and update the chart * Query elasticSearch according to the current parameters and update the chart
*/ */
var refreshChart = function () { const refreshChart = function () {
if ($scope.selectedIndex && !$scope.preventRefresh) { if ($scope.selectedIndex && !$scope.preventRefresh) {
return query($scope.selectedIndex, function (aggregations, error) { return query($scope.selectedIndex, function (aggregations, error) {
if (error) { if (error) {
@ -239,7 +239,7 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
* Format aggregations as retuned by elasticSearch to an understandable format for NVD3 * Format aggregations as retuned by elasticSearch to an understandable format for NVD3
* @param aggs {Object} as returned by elasticsearch * @param aggs {Object} as returned by elasticsearch
*/ */
var formatAggregations = function (aggs) { const formatAggregations = function (aggs) {
const format = {}; const format = {};
angular.forEach(aggs, function (type, type_key) { // go through aggs[$TYPE] where $TYPE = month|year|hour|booking|... angular.forEach(aggs, function (type, type_key) { // go through aggs[$TYPE] where $TYPE = month|year|hour|booking|...
@ -254,7 +254,7 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
const cur_subtype = cur_type.subtypes[it_st]; const cur_subtype = cur_type.subtypes[it_st];
if (subgroup.key === cur_subtype.key) { // ... which match $SUBTYPE if (subgroup.key === cur_subtype.key) { // ... which match $SUBTYPE
// then we construct NVD3 dataSource according to these information // then we construct NVD3 dataSource according to these information
var dataSource = { const dataSource = {
values: [], values: [],
key: cur_subtype.label, key: cur_subtype.label,
total: 0, total: 0,
@ -292,7 +292,7 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
* @param limit {number} limit the number of stats in the bar chart * @param limit {number} limit the number of stats in the bar chart
* @param typeKey {String} field name witch results are grouped by * @param typeKey {String} field name witch results are grouped by
*/ */
var formatRankingAggregations = function (aggs, limit, typeKey) { const formatRankingAggregations = function (aggs, limit, typeKey) {
const format = const format =
{ ranking: [] }; { ranking: [] };
@ -325,7 +325,7 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
* @param key {string} raw value of the label * @param key {string} raw value of the label
* @param typeKey {string} name of the field the results are grouped by * @param typeKey {string} name of the field the results are grouped by
*/ */
var getRankingLabel = function (key, typeKey) { const getRankingLabel = function (key, typeKey) {
if ($scope.selectedIndex) { if ($scope.selectedIndex) {
if (typeKey === 'subType') { if (typeKey === 'subType') {
for (const type of Array.from($scope.selectedIndex.types)) { for (const type of Array.from($scope.selectedIndex.types)) {
@ -356,7 +356,7 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
* @param callback {function} function be to run after results were retrieved, * @param callback {function} function be to run after results were retrieved,
* it will receive two parameters : results {Array}, error {String} (if any) * it will receive two parameters : results {Array}, error {String} (if any)
*/ */
var query = function (index, callback) { const query = function (index, callback) {
// invalid callback handeling // invalid callback handeling
if (typeof (callback) !== 'function') { if (typeof (callback) !== 'function') {
console.error('[graphsController::query] Error: invalid callback provided'); console.error('[graphsController::query] Error: invalid callback provided');
@ -384,7 +384,7 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
let type_it = 0; let type_it = 0;
const results = {}; const results = {};
let error = ''; let error = '';
var recursiveCb = function () { const recursiveCb = function () {
if (type_it < stat_types.length) { if (type_it < stat_types.length) {
return queryElasticStats(index.es_type_key, stat_types[type_it], function (prevResults, prevError) { return queryElasticStats(index.es_type_key, stat_types[type_it], function (prevResults, prevError) {
if (prevError) { if (prevError) {
@ -418,7 +418,7 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
* @param callback {function} function be to run after results were retrieved, * @param callback {function} function be to run after results were retrieved,
* it will receive two parameters : results {Array}, error {String} (if any) * it will receive two parameters : results {Array}, error {String} (if any)
*/ */
var queryElasticStats = function (esType, statType, callback) { const queryElasticStats = function (esType, statType, callback) {
// handle invalid callback // handle invalid callback
if (typeof (callback) !== 'function') { if (typeof (callback) !== 'function') {
console.error('[graphsController::queryElasticStats] Error: invalid callback provided'); console.error('[graphsController::queryElasticStats] Error: invalid callback provided');
@ -457,7 +457,7 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
* @param callback {function} function be to run after results were retrieved, * @param callback {function} function be to run after results were retrieved,
* it will receive two parameters : results {Array}, error {String} (if any) * it will receive two parameters : results {Array}, error {String} (if any)
*/ */
var queryElasticRanking = function (esType, groupKey, sortKey, callback) { const queryElasticRanking = function (esType, groupKey, sortKey, callback) {
// handle invalid callback // handle invalid callback
if (typeof (callback) !== 'function') { if (typeof (callback) !== 'function') {
return console.error('[graphsController::queryElasticRanking] Error: invalid callback provided'); return console.error('[graphsController::queryElasticRanking] Error: invalid callback provided');
@ -497,15 +497,13 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
* @param intervalBegin {moment} statitics interval beginning (moment.js type) * @param intervalBegin {moment} statitics interval beginning (moment.js type)
* @param intervalEnd {moment} statitics interval ending (moment.js type) * @param intervalEnd {moment} statitics interval ending (moment.js type)
*/ */
var buildElasticAggregationsQuery = function (type, interval, intervalBegin, intervalEnd) { const buildElasticAggregationsQuery = function (type, interval, intervalBegin, intervalEnd) {
const q = { const q = {
query: { query: {
bool: { bool: {
must: [ must: [
{ {
match: { match: { type }
type: type
}
}, },
{ {
range: { range: {
@ -527,7 +525,7 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
intervals: { intervals: {
date_histogram: { date_histogram: {
field: 'date', field: 'date',
interval: interval, interval,
min_doc_count: 0, min_doc_count: 0,
extended_bounds: { extended_bounds: {
min: intervalBegin.valueOf(), min: intervalBegin.valueOf(),
@ -566,7 +564,7 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
* @param intervalBegin {moment} statitics interval beginning (moment.js type) * @param intervalBegin {moment} statitics interval beginning (moment.js type)
* @param intervalEnd {moment} statitics interval ending (moment.js type) * @param intervalEnd {moment} statitics interval ending (moment.js type)
*/ */
var buildElasticAggregationsRankingQuery = function (groupKey, sortKey, intervalBegin, intervalEnd) { const buildElasticAggregationsRankingQuery = function (groupKey, sortKey, intervalBegin, intervalEnd) {
const q = { const q = {
query: { query: {
bool: { bool: {
@ -635,7 +633,7 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
* @param data {Array} array of NVD3 dataSources * @param data {Array} array of NVD3 dataSources
* @param type {String} which chart to update (statistic type key) * @param type {String} which chart to update (statistic type key)
*/ */
var updateChart = function (chart_type, data, type) { const updateChart = function (chart_type, data, type) {
const id = `#chart-${type} svg`; const id = `#chart-${type} svg`;
// clean old charts // clean old charts
@ -695,7 +693,7 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
/** /**
* Given an NVD3 line chart axis, scale it to display ordinated dates, according to the given arguments * Given an NVD3 line chart axis, scale it to display ordinated dates, according to the given arguments
*/ */
var setTimeScale = function (nvd3Axis, nvd3Scale, argsArray) { const setTimeScale = function (nvd3Axis, nvd3Scale, argsArray) {
const scale = d3.time.scale(); const scale = d3.time.scale();
nvd3Axis.scale(scale); nvd3Axis.scale(scale);
@ -710,7 +708,7 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
/** /**
* Translate line chart data in dates row to bar chart data, one bar per type. * Translate line chart data in dates row to bar chart data, one bar per type.
*/ */
var prepareDataForBarChart = function (data, type) { const prepareDataForBarChart = function (data, type) {
const newData = [{ const newData = [{
key: type, key: type,
values: [] values: []
@ -738,7 +736,7 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
* @param getValue {function} the callback which will return the value on which the sort will occurs * @param getValue {function} the callback which will return the value on which the sort will occurs
* @returns {Array} * @returns {Array}
*/ */
var stableSort = function (array, order, getValue) { const stableSort = function (array, order, getValue) {
// prepare sorting // prepare sorting
const keys_order = []; const keys_order = [];
const result = []; const result = [];

View File

@ -55,13 +55,13 @@ Application.Controllers.controller('GroupsController', ['$scope', 'groupsPromise
$scope.saveGroup = function (data, id) { $scope.saveGroup = function (data, id) {
if (id != null) { if (id != null) {
return Group.update({ id }, { group: data }, response => growl.success(_t('app.admin.members.group_form.changes_successfully_saved')) return Group.update({ id }, { group: data }, response => growl.success(_t('app.admin.members.group_form.changes_successfully_saved'))
, error => growl.error(_t('app.admin.members.group_form.an_error_occurred_while_saving_changes'))); , () => growl.error(_t('app.admin.members.group_form.an_error_occurred_while_saving_changes')));
} else { } else {
return Group.save({ group: data }, function (resp) { return Group.save({ group: data }, function (resp) {
growl.success(_t('app.admin.members.group_form.new_group_successfully_saved')); growl.success(_t('app.admin.members.group_form.new_group_successfully_saved'));
return $scope.groups[$scope.groups.length - 1].id = resp.id; return $scope.groups[$scope.groups.length - 1].id = resp.id;
} }
, function (error) { , function () {
growl.error(_t('app.admin.members.group_form.an_error_occurred_when_saving_the_new_group')); growl.error(_t('app.admin.members.group_form.an_error_occurred_when_saving_the_new_group'));
return $scope.groups.splice($scope.groups.length - 1, 1); return $scope.groups.splice($scope.groups.length - 1, 1);
}); });
@ -77,7 +77,7 @@ Application.Controllers.controller('GroupsController', ['$scope', 'groupsPromise
growl.success(_t('app.admin.members.group_form.group_successfully_deleted')); growl.success(_t('app.admin.members.group_form.group_successfully_deleted'));
return $scope.groups.splice(index, 1); return $scope.groups.splice(index, 1);
} }
, error => growl.error(_t('app.admin.members.group_form.unable_to_delete_group_because_some_users_and_or_groups_are_still_linked_to_it'))); , () => growl.error(_t('app.admin.members.group_form.unable_to_delete_group_because_some_users_and_or_groups_are_still_linked_to_it')));
/** /**
* Enable/disable the group at the specified index * Enable/disable the group at the specified index
@ -92,7 +92,7 @@ Application.Controllers.controller('GroupsController', ['$scope', 'groupsPromise
$scope.groups[index] = response; $scope.groups[index] = response;
return growl.success(_t('app.admin.members.group_form.group_successfully_enabled_disabled', { STATUS: response.disabled })); return growl.success(_t('app.admin.members.group_form.group_successfully_enabled_disabled', { STATUS: response.disabled }));
} }
, error => growl.error(_t('app.admin.members.group_form.unable_to_enable_disable_group', { STATUS: !group.disabled }))); , () => growl.error(_t('app.admin.members.group_form.unable_to_enable_disable_group', { STATUS: !group.disabled })));
} }
}; };
} }

View File

@ -195,6 +195,14 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
name: 'accounting_Space_label', name: 'accounting_Space_label',
value: settings.accounting_Space_label value: settings.accounting_Space_label
}, },
packCode: {
name: 'accounting_Pack_code',
value: settings.accounting_Pack_code
},
packLabel: {
name: 'accounting_Pack_label',
value: settings.accounting_Pack_label
},
errorCode: { errorCode: {
name: 'accounting_Error_code', name: 'accounting_Error_code',
value: settings.accounting_Error_code value: settings.accounting_Error_code
@ -1239,7 +1247,7 @@ Application.Controllers.controller('AvoirModalController', ['$scope', '$uibModal
function (avoir) { // success function (avoir) { // success
$uibModalInstance.close({ avoir, invoice: $scope.invoice }); $uibModalInstance.close({ avoir, invoice: $scope.invoice });
}, },
function (err) { // failed function () { // failed
growl.error(_t('app.admin.invoices.unable_to_create_the_refund')); growl.error(_t('app.admin.invoices.unable_to_create_the_refund'));
} }
); );

View File

@ -650,12 +650,12 @@ Application.Controllers.controller('AdminMembersController', ['$scope', '$sce',
/** /**
* Controller used in the member edition page * Controller used in the member edition page
*/ */
Application.Controllers.controller('EditMemberController', ['$scope', '$state', '$stateParams', 'Member', 'Training', 'dialogs', 'growl', 'Group', 'Subscription', 'CSRF', 'memberPromise', 'tagsPromise', '$uibModal', 'Plan', '$filter', '_t', 'walletPromise', 'transactionsPromise', 'activeProviderPromise', 'Wallet', 'settingsPromise', Application.Controllers.controller('EditMemberController', ['$scope', '$state', '$transition$', 'Member', 'Training', 'dialogs', 'growl', 'Group', 'Subscription', 'CSRF', 'memberPromise', 'tagsPromise', '$uibModal', 'Plan', '$filter', '_t', 'walletPromise', 'transactionsPromise', 'activeProviderPromise', 'Wallet', 'settingsPromise',
function ($scope, $state, $stateParams, Member, Training, dialogs, growl, Group, Subscription, CSRF, memberPromise, tagsPromise, $uibModal, Plan, $filter, _t, walletPromise, transactionsPromise, activeProviderPromise, Wallet, settingsPromise) { function ($scope, $state, $transition$, Member, Training, dialogs, growl, Group, Subscription, CSRF, memberPromise, tagsPromise, $uibModal, Plan, $filter, _t, walletPromise, transactionsPromise, activeProviderPromise, Wallet, settingsPromise) {
/* PUBLIC SCOPE */ /* PUBLIC SCOPE */
// API URL where the form will be posted // API URL where the form will be posted
$scope.actionUrl = `/api/members/${$stateParams.id}`; $scope.actionUrl = `/api/members/${$transition$.params().id}`;
// Form action on the above URL // Form action on the above URL
$scope.method = 'patch'; $scope.method = 'patch';
@ -922,8 +922,8 @@ Application.Controllers.controller('EditMemberController', ['$scope', '$state',
/** /**
* Controller used in the member's creation page (admin view) * Controller used in the member's creation page (admin view)
*/ */
Application.Controllers.controller('NewMemberController', ['$scope', '$state', '$stateParams', 'Member', 'Training', 'Group', 'CSRF', 'settingsPromise', Application.Controllers.controller('NewMemberController', ['$scope', '$state', 'Member', 'Training', 'Group', 'CSRF', 'settingsPromise',
function ($scope, $state, $stateParams, Member, Training, Group, CSRF, settingsPromise) { function ($scope, $state, Member, Training, Group, CSRF, settingsPromise) {
CSRF.setMetaTags(); CSRF.setMetaTags();
/* PUBLIC SCOPE */ /* PUBLIC SCOPE */

View File

@ -224,8 +224,8 @@ Application.Controllers.controller('NewPlanController', ['$scope', '$uibModal',
/** /**
* Controller used in the plan edition form * Controller used in the plan edition form
*/ */
Application.Controllers.controller('EditPlanController', ['$scope', 'groups', 'plans', 'planPromise', 'machines', 'spaces', 'prices', 'partners', 'CSRF', '$state', '$stateParams', 'growl', '$filter', '_t', 'Plan', 'planCategories', Application.Controllers.controller('EditPlanController', ['$scope', 'groups', 'plans', 'planPromise', 'machines', 'spaces', 'prices', 'partners', 'CSRF', '$state', '$transition$', 'growl', '$filter', '_t', 'Plan', 'planCategories',
function ($scope, groups, plans, planPromise, machines, spaces, prices, partners, CSRF, $state, $stateParams, growl, $filter, _t, Plan, planCategories) { function ($scope, groups, plans, planPromise, machines, spaces, prices, partners, CSRF, $state, $transition$, growl, $filter, _t, Plan, planCategories) {
/* PUBLIC SCOPE */ /* PUBLIC SCOPE */
// List of spaces // List of spaces
@ -254,7 +254,7 @@ Application.Controllers.controller('EditPlanController', ['$scope', 'groups', 'p
if ($scope.plan.disabled) { $scope.plan.disabled = 'true'; } if ($scope.plan.disabled) { $scope.plan.disabled = 'true'; }
// API URL where the form will be posted // API URL where the form will be posted
$scope.actionUrl = `/api/plans/${$stateParams.id}`; $scope.actionUrl = `/api/plans/${$transition$.params().id}`;
// HTTP method for the rest API // HTTP method for the rest API
$scope.method = 'PATCH'; $scope.method = 'PATCH';

View File

@ -403,7 +403,7 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
$scope.spaceCredits[$scope.spaceCredits.length - 1].id = resp.id; $scope.spaceCredits[$scope.spaceCredits.length - 1].id = resp.id;
return growl.success(_t('app.admin.pricing.credit_was_successfully_saved')); return growl.success(_t('app.admin.pricing.credit_was_successfully_saved'));
} }
, function (err) { , function () {
$scope.spaceCredits.pop(); $scope.spaceCredits.pop();
return growl.error(_t('app.admin.pricing.error_creating_credit')); return growl.error(_t('app.admin.pricing.error_creating_credit'));
}); });

View File

@ -2,7 +2,7 @@
no-constant-condition, no-constant-condition,
no-return-assign, no-return-assign,
no-undef, no-undef,
standard/no-callback-literal, n/no-callback-literal,
*/ */
// TODO: This file was created by bulk-decaffeinate. // TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint. // Fix any style issues and re-enable lint.
@ -15,8 +15,8 @@
*/ */
'use strict'; 'use strict';
Application.Controllers.controller('StatisticsController', ['$scope', '$state', '$rootScope', '$uibModal', 'es', 'Member', '_t', 'membersPromise', 'statisticsPromise', 'uiTourService', 'settingsPromise', Application.Controllers.controller('StatisticsController', ['$scope', '$state', '$transitions', '$rootScope', '$uibModal', 'es', 'Member', '_t', 'membersPromise', 'statisticsPromise', 'uiTourService', 'settingsPromise',
function ($scope, $state, $rootScope, $uibModal, es, Member, _t, membersPromise, statisticsPromise, uiTourService, settingsPromise) { function ($scope, $state, $transitions, $rootScope, $uibModal, es, Member, _t, membersPromise, statisticsPromise, uiTourService, settingsPromise) {
/* PRIVATE STATIC CONSTANTS */ /* PRIVATE STATIC CONSTANTS */
// search window size // search window size
@ -407,8 +407,8 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
const initialize = function () { const initialize = function () {
// workaround for angular-bootstrap::tabs behavior: on tab deletion, another tab will be selected // workaround for angular-bootstrap::tabs behavior: on tab deletion, another tab will be selected
// which will cause every tabs to reload, one by one, when the view is closed // which will cause every tabs to reload, one by one, when the view is closed
$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) { $transitions.onStart({ to: 'app.admin.statistics' }, function (trans) {
if ((fromState.name === 'app.admin.statistics') && (Object.keys(fromParams).length === 0)) { if (Object.keys(trans.from().params).length === 0) {
return $scope.preventRefresh = true; return $scope.preventRefresh = true;
} }
}); });
@ -522,9 +522,7 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
bool: { bool: {
must: [ must: [
{ {
term: { term: { type }
type: type
}
}, },
{ {
range: { range: {

View File

@ -45,13 +45,13 @@ Application.Controllers.controller('TagsController', ['$scope', 'tagsPromise', '
$scope.saveTag = function (data, id) { $scope.saveTag = function (data, id) {
if (id != null) { if (id != null) {
return Tag.update({ id }, { tag: data }, response => growl.success(_t('app.admin.members.tag_form.changes_successfully_saved')) return Tag.update({ id }, { tag: data }, response => growl.success(_t('app.admin.members.tag_form.changes_successfully_saved'))
, error => growl.error(_t('app.admin.members.tag_form.an_error_occurred_while_saving_changes'))); , () => growl.error(_t('app.admin.members.tag_form.an_error_occurred_while_saving_changes')));
} else { } else {
return Tag.save({ tag: data }, function (resp) { return Tag.save({ tag: data }, function (resp) {
growl.success(_t('app.admin.members.tag_form.new_tag_successfully_saved')); growl.success(_t('app.admin.members.tag_form.new_tag_successfully_saved'));
return $scope.tags[$scope.tags.length - 1].id = resp.id; return $scope.tags[$scope.tags.length - 1].id = resp.id;
} }
, function (error) { , function () {
growl.error(_t('app.admin.members.tag_form.an_error_occurred_while_saving_the_new_tag')); growl.error(_t('app.admin.members.tag_form.an_error_occurred_while_saving_the_new_tag'));
return $scope.tags.splice($scope.tags.length - 1, 1); return $scope.tags.splice($scope.tags.length - 1, 1);
}); });
@ -78,7 +78,7 @@ Application.Controllers.controller('TagsController', ['$scope', 'tagsPromise', '
growl.success(_t('app.admin.members.tag_form.tag_successfully_deleted')); growl.success(_t('app.admin.members.tag_form.tag_successfully_deleted'));
return $scope.tags.splice(index, 1); return $scope.tags.splice(index, 1);
} }
, error => growl.error(_t('app.admin.members.tag_form.an_error_occurred_and_the_tag_deletion_failed'))); , () => growl.error(_t('app.admin.members.tag_form.an_error_occurred_and_the_tag_deletion_failed')));
}); });
} }

View File

@ -114,15 +114,15 @@ Application.Controllers.controller('NewTrainingController', ['$scope', '$state',
/** /**
* Controller used in the training edition page (admin) * Controller used in the training edition page (admin)
*/ */
Application.Controllers.controller('EditTrainingController', ['$scope', '$state', '$stateParams', 'trainingPromise', 'machinesPromise', 'CSRF', Application.Controllers.controller('EditTrainingController', ['$scope', '$state', '$transition$', 'trainingPromise', 'machinesPromise', 'CSRF',
function ($scope, $state, $stateParams, trainingPromise, machinesPromise, CSRF) { function ($scope, $state, $transition$, trainingPromise, machinesPromise, CSRF) {
/* PUBLIC SCOPE */ /* PUBLIC SCOPE */
// Form action on the following URL // Form action on the following URL
$scope.method = 'patch'; $scope.method = 'patch';
// API URL where the form will be posted // API URL where the form will be posted
$scope.actionUrl = `/api/trainings/${$stateParams.id}`; $scope.actionUrl = `/api/trainings/${$transition$.params().id}`;
// Details of the training to edit (id in URL) // Details of the training to edit (id in URL)
$scope.training = trainingPromise; $scope.training = trainingPromise;

View File

@ -12,8 +12,8 @@
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/ */
Application.Controllers.controller('ApplicationController', ['$rootScope', '$scope', '$window', '$locale', '$timeout', 'Session', 'AuthService', 'Auth', '$uibModal', '$state', 'growl', 'Notification', '$interval', 'Setting', '_t', 'Version', 'Help', Application.Controllers.controller('ApplicationController', ['$rootScope', '$scope', '$transitions', '$window', '$locale', '$timeout', 'Session', 'AuthService', 'Auth', '$uibModal', '$state', 'growl', 'Notification', '$interval', 'Setting', '_t', 'Version', 'Help',
function ($rootScope, $scope, $window, $locale, $timeout, Session, AuthService, Auth, $uibModal, $state, growl, Notification, $interval, Setting, _t, Version, Help) { function ($rootScope, $scope, $transitions, $window, $locale, $timeout, Session, AuthService, Auth, $uibModal, $state, growl, Notification, $interval, Setting, _t, Version, Help) {
/* PRIVATE STATIC CONSTANTS */ /* PRIVATE STATIC CONSTANTS */
// User's notifications will get refreshed every 30s // User's notifications will get refreshed every 30s
@ -325,19 +325,18 @@ Application.Controllers.controller('ApplicationController', ['$rootScope', '$sco
$rootScope.toCheckNotifications = false; $rootScope.toCheckNotifications = false;
}); });
// bind to the $stateChangeStart event (AngularJS/UI-Router) // bind to the $transitions.onStart event (UI-Router)
$rootScope.$on('$stateChangeStart', function (event, toState, toParams) { $transitions.onStart({}, function (trans) {
if (!toState.data) { return; } if (!trans.$to().data) { return; }
const { authorizedRoles } = toState.data; const { authorizedRoles } = trans.$to().data;
if (!AuthService.isAuthorized(authorizedRoles)) { if (!AuthService.isAuthorized(authorizedRoles)) {
event.preventDefault();
if (AuthService.isAuthenticated()) { if (AuthService.isAuthenticated()) {
// user is not allowed // user is not allowed
console.error('[ApplicationController::initialize] user is not allowed'); console.error('[ApplicationController::initialize] user is not allowed');
} else { } else {
// user is not logged in // user is not logged in
openLoginModal(toState, toParams); openLoginModal(trans.$to().name, trans.$to().params);
} }
} }
}); });
@ -462,6 +461,7 @@ Application.Controllers.controller('ApplicationController', ['$rootScope', '$sco
// what to do when the modal is closed // what to do when the modal is closed
// authentication succeeded, set the session, gather the notifications and redirect // authentication succeeded, set the session, gather the notifications and redirect
GTM.trackLogin();
$scope.setCurrentUser(user); $scope.setCurrentUser(user);
if ((toState !== null) && (toParams !== null)) { if ((toState !== null) && (toParams !== null)) {

View File

@ -13,28 +13,20 @@ Application.Controllers.controller('CookiesController', ['$scope', '$cookies', '
// link pointed by "learn more" // link pointed by "learn more"
$scope.learnMoreUrl = 'https://www.cookiesandyou.com/'; $scope.learnMoreUrl = 'https://www.cookiesandyou.com/';
// current user wallet // add a cookie to the browser, saving the user choice to refuse cookies
$scope.declineCookies = function () { $scope.declineCookies = function () {
const expires = moment().add(13, 'months').toDate(); const expires = moment().add(13, 'months').toDate();
$cookies.put('fab-manager-cookies-consent', 'decline', { expires }); $cookies.put('fab-manager-cookies-consent', 'decline', { expires });
readCookie(); readCookie();
}; };
// current wallet transactions // add a cookie to the browser, saving the user choice to accept cookies.
// Then enable the analytics
$scope.acceptCookies = function () { $scope.acceptCookies = function () {
const expires = moment().add(13, 'months').toDate(); const expires = moment().add(13, 'months').toDate();
$cookies.put('fab-manager-cookies-consent', 'accept', { expires }); $cookies.put('fab-manager-cookies-consent', 'accept', { expires });
readCookie(); readCookie();
// enable tracking using code provided by google analytics GTM.enableAnalytics(Fablab.trackingId);
/* eslint-disable */
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', Fablab.trackingId, 'auto');
ga('send', 'pageview');
/* eslint-enable */
}; };
/* PRIVATE SCOPE */ /* PRIVATE SCOPE */
@ -44,7 +36,7 @@ Application.Controllers.controller('CookiesController', ['$scope', '$cookies', '
*/ */
const initialize = function () { const initialize = function () {
readCookie(); readCookie();
// if the privacy policy was defined, redirect the user to it // if the privacy policy was defined, redirect the user to it when clicking on "read more"
Setting.get({ name: 'privacy_body' }, data => { Setting.get({ name: 'privacy_body' }, data => {
if (data.setting.value) { if (data.setting.value) {
$scope.learnMoreUrl = '#!/privacy-policy'; $scope.learnMoreUrl = '#!/privacy-policy';

View File

@ -126,8 +126,8 @@ Application.Controllers.controller('EventsController', ['$scope', '$state', 'Eve
} }
]); ]);
Application.Controllers.controller('ShowEventController', ['$scope', '$state', '$stateParams', '$rootScope', 'Event', '$uibModal', 'Member', 'Reservation', 'Price', 'CustomAsset', 'Slot', 'eventPromise', 'growl', '_t', 'Wallet', 'AuthService', 'helpers', 'dialogs', 'priceCategoriesPromise', 'settingsPromise', 'LocalPayment', Application.Controllers.controller('ShowEventController', ['$scope', '$state', '$rootScope', 'Event', '$uibModal', 'Member', 'Reservation', 'Price', 'CustomAsset', 'Slot', 'eventPromise', 'growl', '_t', 'Wallet', 'AuthService', 'helpers', 'dialogs', 'priceCategoriesPromise', 'settingsPromise', 'LocalPayment',
function ($scope, $state, $stateParams, $rootScope, Event, $uibModal, Member, Reservation, Price, CustomAsset, Slot, eventPromise, growl, _t, Wallet, AuthService, helpers, dialogs, priceCategoriesPromise, settingsPromise, LocalPayment) { function ($scope, $state,$rootScope, Event, $uibModal, Member, Reservation, Price, CustomAsset, Slot, eventPromise, growl, _t, Wallet, AuthService, helpers, dialogs, priceCategoriesPromise, settingsPromise, LocalPayment) {
/* PUBLIC SCOPE */ /* PUBLIC SCOPE */
// reservations for the currently shown event // reservations for the currently shown event

View File

@ -1,11 +1,11 @@
'use strict'; 'use strict';
Application.Controllers.controller('HeaderController', ['$scope', '$rootScope', '$state', 'settingsPromise', Application.Controllers.controller('HeaderController', ['$scope', '$transitions', '$state', 'settingsPromise',
function ($scope, $rootScope, $state, settingsPromise) { function ($scope, $transitions, $state, settingsPromise) {
$scope.aboutPage = ($state.current.name === 'app.public.about'); $scope.aboutPage = ($state.current.name === 'app.public.about');
$rootScope.$on('$stateChangeStart', function (event, toState) { $transitions.onStart({}, function (trans) {
$scope.aboutPage = (toState.name === 'app.public.about'); $scope.aboutPage = (trans.$to().name === 'app.public.about');
}); });
/** /**

View File

@ -1,7 +1,7 @@
'use strict'; 'use strict';
Application.Controllers.controller('HomeController', ['$scope', '$stateParams', '$translatePartialLoader', 'AuthService', 'settingsPromise', 'Member', 'uiTourService', '_t', Application.Controllers.controller('HomeController', ['$scope', '$transition$', '$translatePartialLoader', 'AuthService', 'settingsPromise', 'Member', 'uiTourService', '_t',
function ($scope, $stateParams, $translatePartialLoader, AuthService, settingsPromise, Member, uiTourService, _t) { function ($scope, $transition$, $translatePartialLoader, AuthService, settingsPromise, Member, uiTourService, _t) {
/* PUBLIC SCOPE */ /* PUBLIC SCOPE */
// Home page HTML content // Home page HTML content
@ -38,8 +38,8 @@ Application.Controllers.controller('HomeController', ['$scope', '$stateParams',
const initialize = function () { const initialize = function () {
// if we receive 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 // changePassword modal from the parent controller
if ($stateParams.reset_password_token) { if ($transition$.params().reset_password_token) {
return $scope.$parent.editPassword($stateParams.reset_password_token); return $scope.$parent.editPassword($transition$.params().reset_password_token);
} }
// We set the home page content, with the directives replacing the placeholders // We set the home page content, with the directives replacing the placeholders

View File

@ -245,12 +245,12 @@ Application.Controllers.controller('NewMachineController', ['$scope', '$state',
/** /**
* Controller used in the machine edition page (admin) * Controller used in the machine edition page (admin)
*/ */
Application.Controllers.controller('EditMachineController', ['$scope', '$state', '$stateParams', 'machinePromise', 'CSRF', Application.Controllers.controller('EditMachineController', ['$scope', '$state', '$transition$', 'machinePromise', 'CSRF',
function ($scope, $state, $stateParams, machinePromise, CSRF) { function ($scope, $state, $transition$, machinePromise, CSRF) {
/* PUBLIC SCOPE */ /* PUBLIC SCOPE */
// API URL where the form will be posted // API URL where the form will be posted
$scope.actionUrl = `/api/machines/${$stateParams.id}`; $scope.actionUrl = `/api/machines/${$transition$.params().id}`;
// Form action on the above URL // Form action on the above URL
$scope.method = 'put'; $scope.method = 'put';
@ -278,8 +278,8 @@ Application.Controllers.controller('EditMachineController', ['$scope', '$state',
/** /**
* Controller used in the machine details page (public) * Controller used in the machine details page (public)
*/ */
Application.Controllers.controller('ShowMachineController', ['$scope', '$state', '$uibModal', '$stateParams', '_t', 'Machine', 'growl', 'machinePromise', 'dialogs', Application.Controllers.controller('ShowMachineController', ['$scope', '$state', '$uibModal', '_t', 'Machine', 'growl', 'machinePromise', 'dialogs',
function ($scope, $state, $uibModal, $stateParams, _t, Machine, growl, machinePromise, dialogs) { function ($scope, $state, $uibModal, _t, Machine, growl, machinePromise, dialogs) {
// Retrieve the details for the machine id in the URL, if an error occurs redirect the user to the machines list // Retrieve the details for the machine id in the URL, if an error occurs redirect the user to the machines list
$scope.machine = machinePromise; $scope.machine = machinePromise;
@ -357,8 +357,8 @@ Application.Controllers.controller('ShowMachineController', ['$scope', '$state',
* This controller workflow is pretty similar to the trainings reservation controller. * This controller workflow is pretty similar to the trainings reservation controller.
*/ */
Application.Controllers.controller('ReserveMachineController', ['$scope', '$stateParams', '_t', 'moment', 'Auth', '$timeout', 'Member', 'Availability', 'plansPromise', 'groupsPromise', 'machinePromise', 'settingsPromise', 'uiCalendarConfig', 'CalendarConfig', 'Reservation', 'growl', Application.Controllers.controller('ReserveMachineController', ['$scope', '$transition$', '_t', 'moment', 'Auth', '$timeout', 'Member', 'Availability', 'plansPromise', 'groupsPromise', 'machinePromise', 'settingsPromise', 'uiCalendarConfig', 'CalendarConfig', 'Reservation', 'growl',
function ($scope, $stateParams, _t, moment, Auth, $timeout, Member, Availability, plansPromise, groupsPromise, machinePromise, settingsPromise, uiCalendarConfig, CalendarConfig, Reservation, growl) { function ($scope, $transition$, _t, moment, Auth, $timeout, Member, Availability, plansPromise, groupsPromise, machinePromise, settingsPromise, uiCalendarConfig, CalendarConfig, Reservation, growl) {
/* PRIVATE STATIC CONSTANTS */ /* PRIVATE STATIC CONSTANTS */
// Slot free to be booked // Slot free to be booked
@ -660,7 +660,7 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
const initialize = function () { const initialize = function () {
$scope.eventSources.push({ $scope.eventSources.push({
events: function (start, end, timezone, callback) { events: function (start, end, timezone, callback) {
Availability.machine({ machineId: $stateParams.id }, function (availabilities) { Availability.machine({ machineId: $transition$.params().id }, function (availabilities) {
callback(availabilities); callback(availabilities);
}); });
}, },

View File

@ -323,7 +323,7 @@ Application.Controllers.controller('ShowProfileController', ['$scope', 'memberPr
* and return the filtered networks * and return the filtered networks
* @return {Array} * @return {Array}
*/ */
var filterNetworks = function () { const filterNetworks = function () {
const networks = []; const networks = [];
for (const network of Array.from(SocialNetworks)) { for (const network of Array.from(SocialNetworks)) {
if ($scope.user.profile[network] && ($scope.user.profile[network].length > 0)) { if ($scope.user.profile[network] && ($scope.user.profile[network].length > 0)) {

View File

@ -480,12 +480,12 @@ Application.Controllers.controller('NewProjectController', ['$rootScope', '$scop
/** /**
* Controller used in the project edition page * Controller used in the project edition page
*/ */
Application.Controllers.controller('EditProjectController', ['$rootScope', '$scope', '$state', '$stateParams', 'Project', 'Machine', 'Member', 'Component', 'Theme', 'Licence', '$document', 'CSRF', 'projectPromise', 'Diacritics', 'dialogs', 'allowedExtensions', '_t', Application.Controllers.controller('EditProjectController', ['$rootScope', '$scope', '$state', '$transition$', 'Project', 'Machine', 'Member', 'Component', 'Theme', 'Licence', '$document', 'CSRF', 'projectPromise', 'Diacritics', 'dialogs', 'allowedExtensions', '_t',
function ($rootScope, $scope, $state, $stateParams, Project, Machine, Member, Component, Theme, Licence, $document, CSRF, projectPromise, Diacritics, dialogs, allowedExtensions, _t) { function ($rootScope, $scope, $state, $transition$, Project, Machine, Member, Component, Theme, Licence, $document, CSRF, projectPromise, Diacritics, dialogs, allowedExtensions, _t) {
/* PUBLIC SCOPE */ /* PUBLIC SCOPE */
// API URL where the form will be posted // API URL where the form will be posted
$scope.actionUrl = `/api/projects/${$stateParams.id}`; $scope.actionUrl = `/api/projects/${$transition$.params().id}`;
// Form action on the above URL // Form action on the above URL
$scope.method = 'put'; $scope.method = 'put';
@ -618,7 +618,7 @@ Application.Controllers.controller('ShowProjectController', ['$scope', '$state',
growl.success(_t('app.public.projects_show.your_report_was_successful_thanks')); growl.success(_t('app.public.projects_show.your_report_was_successful_thanks'));
return $uibModalInstance.close(res); return $uibModalInstance.close(res);
} }
, function (error) { , function () {
// creation failed... // creation failed...
growl.error(_t('app.public.projects_show.an_error_occured_while_sending_your_report')); growl.error(_t('app.public.projects_show.an_error_occured_while_sending_your_report'));
} }

View File

@ -234,12 +234,12 @@ Application.Controllers.controller('NewSpaceController', ['$scope', '$state', 'C
/** /**
* Controller used in the space edition page (admin) * Controller used in the space edition page (admin)
*/ */
Application.Controllers.controller('EditSpaceController', ['$scope', '$state', '$stateParams', 'spacePromise', 'CSRF', Application.Controllers.controller('EditSpaceController', ['$scope', '$state', '$transition$', 'spacePromise', 'CSRF',
function ($scope, $state, $stateParams, spacePromise, CSRF) { function ($scope, $state, $transition$, spacePromise, CSRF) {
CSRF.setMetaTags(); CSRF.setMetaTags();
// API URL where the form will be posted // API URL where the form will be posted
$scope.actionUrl = `/api/spaces/${$stateParams.id}`; $scope.actionUrl = `/api/spaces/${$transition$.params().id}`;
// Form action on the above URL // Form action on the above URL
$scope.method = 'put'; $scope.method = 'put';
@ -307,8 +307,8 @@ Application.Controllers.controller('ShowSpaceController', ['$scope', '$state', '
* per slots. * per slots.
*/ */
Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateParams', 'Auth', '$timeout', 'Availability', 'Member', 'plansPromise', 'groupsPromise', 'settingsPromise', 'spacePromise', '_t', 'uiCalendarConfig', 'CalendarConfig', 'Reservation', Application.Controllers.controller('ReserveSpaceController', ['$scope', '$transition$', 'Auth', '$timeout', 'Availability', 'Member', 'plansPromise', 'groupsPromise', 'settingsPromise', 'spacePromise', '_t', 'uiCalendarConfig', 'CalendarConfig', 'Reservation',
function ($scope, $stateParams, Auth, $timeout, Availability, Member, plansPromise, groupsPromise, settingsPromise, spacePromise, _t, uiCalendarConfig, CalendarConfig, Reservation) { function ($scope, $transition$, Auth, $timeout, Availability, Member, plansPromise, groupsPromise, settingsPromise, spacePromise, _t, uiCalendarConfig, CalendarConfig, Reservation) {
/* PRIVATE STATIC CONSTANTS */ /* PRIVATE STATIC CONSTANTS */
// Color of the selected event backgound // Color of the selected event backgound
@ -601,7 +601,7 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
// in the router because this allows to refetchEvents from fullCalendar API. // in the router because this allows to refetchEvents from fullCalendar API.
$scope.eventSources.push({ $scope.eventSources.push({
events: function (start, end, timezone, callback) { events: function (start, end, timezone, callback) {
Availability.spaces({ spaceId: $stateParams.id }, function (availabilities) { Availability.spaces({ spaceId: $transition$.params().id }, function (availabilities) {
callback(availabilities); callback(availabilities);
}); });
}, },

View File

@ -91,8 +91,8 @@ Application.Controllers.controller('ShowTrainingController', ['$scope', '$state'
* training can be reserved during the reservation process (the shopping cart may contains only one training and a subscription). * training can be reserved during the reservation process (the shopping cart may contains only one training and a subscription).
*/ */
Application.Controllers.controller('ReserveTrainingController', ['$scope', '$stateParams', 'Auth', 'AuthService', '$timeout', 'Availability', 'Member', 'plansPromise', 'groupsPromise', 'settingsPromise', 'trainingPromise', '_t', 'uiCalendarConfig', 'CalendarConfig', 'Reservation', Application.Controllers.controller('ReserveTrainingController', ['$scope', '$transition$', 'Auth', 'AuthService', '$timeout', 'Availability', 'Member', 'plansPromise', 'groupsPromise', 'settingsPromise', 'trainingPromise', '_t', 'uiCalendarConfig', 'CalendarConfig', 'Reservation',
function ($scope, $stateParams, Auth, AuthService, $timeout, Availability, Member, plansPromise, groupsPromise, settingsPromise, trainingPromise, _t, uiCalendarConfig, CalendarConfig, Reservation) { function ($scope, $transition$, Auth, AuthService, $timeout, Availability, Member, plansPromise, groupsPromise, settingsPromise, trainingPromise, _t, uiCalendarConfig, CalendarConfig, Reservation) {
/* PRIVATE STATIC CONSTANTS */ /* PRIVATE STATIC CONSTANTS */
// Color of the selected event backgound // Color of the selected event backgound
@ -144,7 +144,7 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
$scope.training = trainingPromise; $scope.training = trainingPromise;
// 'all' OR training's slug // 'all' OR training's slug
$scope.mode = $stateParams.id; $scope.mode = $transition$.params().id;
// fullCalendar (v2) configuration // fullCalendar (v2) configuration
$scope.calendarConfig = CalendarConfig({ $scope.calendarConfig = CalendarConfig({
@ -279,7 +279,7 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
if ($scope.ctrl.member) { if ($scope.ctrl.member) {
Member.get({ id: $scope.ctrl.member.id }, function (member) { Member.get({ id: $scope.ctrl.member.id }, function (member) {
$scope.ctrl.member = member; $scope.ctrl.member = member;
const id = $stateParams.id === 'all' ? $stateParams.id : $scope.training.id; const id = $transition$.params().id === 'all' ? $transition$.params().id : $scope.training.id;
return Availability.trainings({ trainingId: id, member_id: $scope.ctrl.member.id }, function (trainings) { return Availability.trainings({ trainingId: id, member_id: $scope.ctrl.member.id }, function (trainings) {
uiCalendarConfig.calendars.calendar.fullCalendar('removeEvents'); uiCalendarConfig.calendars.calendar.fullCalendar('removeEvents');
return $scope.eventSources.splice(0, 1, { return $scope.eventSources.splice(0, 1, {
@ -391,7 +391,7 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
// in the router because this allows to refetchEvents from fullCalendar API. // in the router because this allows to refetchEvents from fullCalendar API.
$scope.eventSources.push({ $scope.eventSources.push({
events: function (start, end, timezone, callback) { events: function (start, end, timezone, callback) {
Availability.trainings({ trainingId: $stateParams.id }, function (availabilities) { Availability.trainings({ trainingId: $transition$.params().id }, function (availabilities) {
callback(availabilities); callback(availabilities);
}); });
}, },
@ -408,7 +408,7 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
*/ */
const calendarEventClickCb = function (event, jsEvent, view) { const calendarEventClickCb = function (event, jsEvent, view) {
$scope.selectedEvent = event; $scope.selectedEvent = event;
if ($stateParams.id === 'all') { if ($transition$.params().id === 'all') {
$scope.training = event.training; $scope.training = event.training;
} }
return $scope.selectionTime = new Date(); return $scope.selectionTime = new Date();

View File

@ -4,9 +4,9 @@ Application.Directives.directive('bsJasnyFileinput', [function () {
return { return {
require: ['ngModel'], require: ['ngModel'],
link: function ($scope, elm, attrs, requiredCtrls) { link: function ($scope, elm, attrs, requiredCtrls) {
var ngModelCtrl = requiredCtrls[0]; const ngModelCtrl = requiredCtrls[0];
var fileinput = elm.parents('[data-provides=fileinput]'); const fileinput = elm.parents('[data-provides=fileinput]');
var filetypeRegex = attrs.bsJasnyFileinput; const filetypeRegex = attrs.bsJasnyFileinput;
fileinput.on('clear.bs.fileinput', function (e) { fileinput.on('clear.bs.fileinput', function (e) {
if (ngModelCtrl) { if (ngModelCtrl) {
ngModelCtrl.$setViewValue(null); ngModelCtrl.$setViewValue(null);

View File

@ -1,8 +1,3 @@
/* eslint-disable
no-undef,
*/
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
/* /*
* decaffeinate suggestions: * decaffeinate suggestions:
* DS101: Remove unnecessary use of Array.from * DS101: Remove unnecessary use of Array.from
@ -135,7 +130,7 @@ Application.Filters.filter('projectsCollabored', [function () {
}; };
}]); }]);
// depend on humanize.js lib in /vendor // depend on app/frontend/src/javascript/lib/humanize.js
Application.Filters.filter('humanize', [function () { Application.Filters.filter('humanize', [function () {
return (element, param) => Humanize.truncate(element, param, null); return (element, param) => Humanize.truncate(element, param, null);
}]); }]);
@ -157,6 +152,8 @@ Application.Filters.filter('breakFilter', [function () {
Application.Filters.filter('simpleText', [function () { Application.Filters.filter('simpleText', [function () {
return function (text) { return function (text) {
if (text != null) { if (text != null) {
// add a line break after specific closing tags
text = text.replace(/(<\/p>|<\/h4>|<\/h5>|<\/h6>|<\/pre>|<\/blockquote>)/g, '\n');
text = text.replace(/<br\s*\/?>/g, '\n'); text = text.replace(/<br\s*\/?>/g, '\n');
return text.replace(/<\/?\w+[^>]*>/g, ''); return text.replace(/<\/?\w+[^>]*>/g, '');
} else { } else {
@ -166,7 +163,7 @@ Application.Filters.filter('simpleText', [function () {
}]); }]);
Application.Filters.filter('toTrusted', ['$sce', function ($sce) { Application.Filters.filter('toTrusted', ['$sce', function ($sce) {
return text => $sce.getTrustedHtml(text); return text => $sce.trustAsHtml(text);
}]); }]);
Application.Filters.filter('planIntervalFilter', [function () { Application.Filters.filter('planIntervalFilter', [function () {

View File

@ -11,7 +11,7 @@
'Auth', 'Auth',
'$rootScope', '$rootScope',
function ($uibModal, $http, Auth, $rootScope) { function ($uibModal, $http, Auth, $rootScope) {
var promise = null; let promise = null;
function reset () { function reset () {
promise = null; promise = null;
} }

View File

@ -46,7 +46,7 @@ angular.module('angularUtils.directives.dirDisqus', [])
// get the remote Disqus script and insert it into the DOM, but only if it not already loaded (as that will cause warnings) // get the remote Disqus script and insert it into the DOM, but only if it not already loaded (as that will cause warnings)
if (!$window.DISQUS) { if (!$window.DISQUS) {
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; const dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
dsq.src = '//' + scope.disqus_shortname + '.disqus.com/embed.js'; dsq.src = '//' + scope.disqus_shortname + '.disqus.com/embed.js';
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
} else { } else {

View File

@ -9,7 +9,7 @@ export default class FormatLib {
*/ */
static date = (date: Date): string => { static date = (date: Date): string => {
return Intl.DateTimeFormat().format(moment(date).toDate()); return Intl.DateTimeFormat().format(moment(date).toDate());
} };
/** /**
* Return the formatted localized time for the given date * Return the formatted localized time for the given date
@ -23,12 +23,12 @@ export default class FormatLib {
*/ */
static duration = (interval: unitOfTime.DurationConstructor, intervalCount: number): string => { static duration = (interval: unitOfTime.DurationConstructor, intervalCount: number): string => {
return moment.duration(intervalCount, interval).locale(Fablab.moment_locale).humanize(); return moment.duration(intervalCount, interval).locale(Fablab.moment_locale).humanize();
} };
/** /**
* Return the formatted localized amount for the given price (eg. 20.5 => "20,50 €") * Return the formatted localized amount for the given price (eg. 20.5 => "20,50 €")
*/ */
static price = (price: number): string => { static price = (price: number): string => {
return new Intl.NumberFormat(Fablab.intl_locale, { style: 'currency', currency: Fablab.intl_currency }).format(price); return new Intl.NumberFormat(Fablab.intl_locale, { style: 'currency', currency: Fablab.intl_currency }).format(price);
} };
} }

View File

@ -0,0 +1,43 @@
// this script loads the google tag manager, used by Google Analytics V4
(function () {
const GTM = {};
window.dataLayer = window.dataLayer || [];
function gtag () { window.dataLayer.push(arguments); }
GTM.enableAnalytics = function (trackingId) {
gtag('js', new Date());
gtag('config', trackingId);
const node = document.createElement('script');
const firstScript = document.getElementsByTagName('script')[0];
node.async = true;
node.src = `//www.googletagmanager.com/gtag/js?id=${trackingId}`;
firstScript.parentNode.insertBefore(node, firstScript);
};
GTM.trackPage = function (url, title) {
gtag('event', 'page_view', {
page_location: url,
page_title: title
});
};
GTM.trackLogin = function () {
gtag('event', 'login');
};
GTM.trackPurchase = function (transactionId, value) {
gtag('event', 'purchase', {
transaction_id: transactionId,
value,
currency: Fablab.intl_currency
});
};
this.GTM = GTM;
if (typeof module !== 'undefined' && module !== null) {
module.exports = GTM;
}
}).call(this);

View File

@ -1,23 +1,21 @@
(function () { (function () {
var Humanize, isArray, isFinite, isNaN, objectRef, timeFormats, toString; const objectRef = new function () {}();
objectRef = new function () {}(); const toString = objectRef.toString;
toString = objectRef.toString; const isNaN = function (value) {
isNaN = function (value) {
return Number.isNaN(value); return Number.isNaN(value);
}; };
isFinite = function (value) { const isFinite = function (value) {
return ((typeof window !== 'undefined' && window !== null ? window.isFinite : undefined) || global.isFinite)(value) && !isNaN(parseFloat(value)); return ((typeof window !== 'undefined' && window !== null ? window.isFinite : undefined) || global.isFinite)(value) && !isNaN(parseFloat(value));
}; };
isArray = function (value) { const isArray = function (value) {
return toString.call(value) === '[object Array]'; return toString.call(value) === '[object Array]';
}; };
timeFormats = [ const timeFormats = [
{ {
name: 'second', name: 'second',
value: 1e3 value: 1e3
@ -36,7 +34,7 @@
} }
]; ];
Humanize = {}; const Humanize = {};
Humanize.intword = function (number, charWidth, decimals) { Humanize.intword = function (number, charWidth, decimals) {
if (decimals == null) { if (decimals == null) {
@ -51,18 +49,18 @@
}; };
Humanize.compactInteger = function (input, decimals) { Humanize.compactInteger = function (input, decimals) {
var bigNumPrefixes, decimalIndex, decimalPart, decimalPartArray, length, number, numberLength, numberLengths, output, outputNumber, signString, unsignedNumber, unsignedNumberCharacterArray, unsignedNumberString, wholePart, wholePartArray, _i, _len, _length; let decimalPart, length, output, outputNumber, unsignedNumberString, _i, _len, _length;
if (decimals == null) { if (decimals == null) {
decimals = 0; decimals = 0;
} }
decimals = Math.max(decimals, 0); decimals = Math.max(decimals, 0);
number = parseInt(input, 10); const number = parseInt(input, 10);
signString = number < 0 ? '-' : ''; const signString = number < 0 ? '-' : '';
unsignedNumber = Math.abs(number); const unsignedNumber = Math.abs(number);
unsignedNumberString = '' + unsignedNumber; unsignedNumberString = '' + unsignedNumber;
numberLength = unsignedNumberString.length; const numberLength = unsignedNumberString.length;
numberLengths = [13, 10, 7, 4]; const numberLengths = [13, 10, 7, 4];
bigNumPrefixes = ['T', 'B', 'M', 'k']; const bigNumPrefixes = ['T', 'B', 'M', 'k'];
if (unsignedNumber < 1000) { if (unsignedNumber < 1000) {
if (decimals > 0) { if (decimals > 0) {
unsignedNumberString += '.' + (Array(decimals + 1).join('0')); unsignedNumberString += '.' + (Array(decimals + 1).join('0'));
@ -79,11 +77,11 @@
break; break;
} }
} }
decimalIndex = numberLength - length + 1; const decimalIndex = numberLength - length + 1;
unsignedNumberCharacterArray = unsignedNumberString.split(''); const unsignedNumberCharacterArray = unsignedNumberString.split('');
wholePartArray = unsignedNumberCharacterArray.slice(0, decimalIndex); const wholePartArray = unsignedNumberCharacterArray.slice(0, decimalIndex);
decimalPartArray = unsignedNumberCharacterArray.slice(decimalIndex, decimalIndex + decimals + 1); const decimalPartArray = unsignedNumberCharacterArray.slice(decimalIndex, decimalIndex + decimals + 1);
wholePart = wholePartArray.join(''); const wholePart = wholePartArray.join('');
decimalPart = decimalPartArray.join(''); decimalPart = decimalPartArray.join('');
if (decimalPart.length < decimals) { if (decimalPart.length < decimals) {
decimalPart += '' + (Array(decimals - decimalPart.length + 1).join('0')); decimalPart += '' + (Array(decimals - decimalPart.length + 1).join('0'));
@ -105,7 +103,7 @@
}; };
Humanize.filesize = Humanize.fileSize = function (filesize) { Humanize.filesize = Humanize.fileSize = function (filesize) {
var sizeStr; let sizeStr;
if (filesize >= 1073741824) { if (filesize >= 1073741824) {
sizeStr = Humanize.formatNumber(filesize / 1073741824, 2, '') + ' GB'; sizeStr = Humanize.formatNumber(filesize / 1073741824, 2, '') + ' GB';
} else if (filesize >= 1048576) { } else if (filesize >= 1048576) {
@ -119,7 +117,6 @@
}; };
Humanize.formatNumber = function (number, precision, thousand, decimal) { Humanize.formatNumber = function (number, precision, thousand, decimal) {
var base; var commas; var decimals; var firstComma; var mod; var negative; var usePrecision;
if (precision == null) { if (precision == null) {
precision = 0; precision = 0;
} }
@ -129,36 +126,35 @@
if (decimal == null) { if (decimal == null) {
decimal = '.'; decimal = '.';
} }
firstComma = function (number, thousand, position) { const firstComma = function (number, thousand, position) {
if (position) { if (position) {
return number.substr(0, position) + thousand; return number.substr(0, position) + thousand;
} else { } else {
return ''; return '';
} }
}; };
commas = function (number, thousand, position) { const commas = function (number, thousand, position) {
return number.substr(position).replace(/(\d{3})(?=\d)/g, '$1' + thousand); return number.substr(position).replace(/(\d{3})(?=\d)/g, '$1' + thousand);
}; };
decimals = function (number, decimal, usePrecision) { const decimals = function (number, decimal, usePrecision) {
if (usePrecision) { if (usePrecision) {
return decimal + Humanize.toFixed(Math.abs(number), usePrecision).split('.')[1]; return decimal + Humanize.toFixed(Math.abs(number), usePrecision).split('.')[1];
} else { } else {
return ''; return '';
} }
}; };
usePrecision = Humanize.normalizePrecision(precision); const usePrecision = Humanize.normalizePrecision(precision);
negative = number < 0 ? '-' : ''; const negative = number < 0 ? '-' : '';
base = parseInt(Humanize.toFixed(Math.abs(number || 0), usePrecision), 10) + ''; const base = parseInt(Humanize.toFixed(Math.abs(number || 0), usePrecision), 10) + '';
mod = base.length > 3 ? base.length % 3 : 0; const mod = base.length > 3 ? base.length % 3 : 0;
return negative + firstComma(base, thousand, mod) + commas(base, thousand, mod) + decimals(number, decimal, usePrecision); return negative + firstComma(base, thousand, mod) + commas(base, thousand, mod) + decimals(number, decimal, usePrecision);
}; };
Humanize.toFixed = function (value, precision) { Humanize.toFixed = function (value, precision) {
var power;
if (precision == null) { if (precision == null) {
precision = Humanize.normalizePrecision(precision, 0); precision = Humanize.normalizePrecision(precision, 0);
} }
power = Math.pow(10, precision); const power = Math.pow(10, precision);
return (Math.round(value * power) / power).toFixed(precision); return (Math.round(value * power) / power).toFixed(precision);
}; };
@ -172,16 +168,16 @@
}; };
Humanize.ordinal = function (value) { Humanize.ordinal = function (value) {
var end, leastSignificant, number, specialCase; let end;
number = parseInt(value, 10); const number = parseInt(value, 10);
if (number === 0) { if (number === 0) {
return value; return value;
} }
specialCase = number % 100; const specialCase = number % 100;
if (specialCase === 11 || specialCase === 12 || specialCase === 13) { if (specialCase === 11 || specialCase === 12 || specialCase === 13) {
return '' + number + 'th'; return '' + number + 'th';
} }
leastSignificant = number % 10; const leastSignificant = number % 10;
switch (leastSignificant) { switch (leastSignificant) {
case 1: case 1:
end = 'st'; end = 'st';
@ -199,7 +195,7 @@
}; };
Humanize.times = function (value, overrides) { Humanize.times = function (value, overrides) {
var number, smallTimes, _ref; let number, smallTimes, _ref;
if (overrides == null) { if (overrides == null) {
overrides = {}; overrides = {};
} }
@ -243,8 +239,8 @@
}; };
Humanize.truncatewords = Humanize.truncateWords = function (string, length) { Humanize.truncatewords = Humanize.truncateWords = function (string, length) {
var array, i, result; let i, result;
array = string.split(' '); const array = string.split(' ');
result = ''; result = '';
i = 0; i = 0;
while (i < length) { while (i < length) {
@ -259,7 +255,7 @@
}; };
Humanize.truncatenumber = Humanize.boundedNumber = function (num, bound, ending) { Humanize.truncatenumber = Humanize.boundedNumber = function (num, bound, ending) {
var result; let result;
if (bound == null) { if (bound == null) {
bound = 100; bound = 100;
} }
@ -276,8 +272,8 @@
}; };
Humanize.oxford = function (items, limit, limitStr) { Humanize.oxford = function (items, limit, limitStr) {
var extra, limitIndex, numItems; let extra, limitIndex;
numItems = items.length; const numItems = items.length;
if (numItems < 2) { if (numItems < 2) {
return '' + items; return '' + items;
} else if (numItems === 2) { } else if (numItems === 2) {
@ -296,7 +292,7 @@
}; };
Humanize.dictionary = function (object, joiner, separator) { Humanize.dictionary = function (object, joiner, separator) {
var defs, key, result, val; let defs, key, result, val;
if (joiner == null) { if (joiner == null) {
joiner = ' is '; joiner = ' is ';
} }
@ -316,12 +312,12 @@
}; };
Humanize.frequency = function (list, verb) { Humanize.frequency = function (list, verb) {
var len, str, times; let str;
if (!isArray(list)) { if (!isArray(list)) {
return; return;
} }
len = list.length; const len = list.length;
times = Humanize.times(len); const times = Humanize.times(len);
if (len === 0) { if (len === 0) {
str = '' + times + ' ' + verb; str = '' + times + ' ' + verb;
} else { } else {
@ -331,7 +327,7 @@
}; };
Humanize.pace = function (value, intervalMs, unit) { Humanize.pace = function (value, intervalMs, unit) {
var f, prefix, rate, relativePace, roundedPace, timeUnit, _i, _len; let f, prefix, relativePace, timeUnit, _i, _len;
if (unit == null) { if (unit == null) {
unit = 'time'; unit = 'time';
} }
@ -340,7 +336,7 @@
} }
prefix = 'Approximately'; prefix = 'Approximately';
timeUnit = null; timeUnit = null;
rate = value / intervalMs; const rate = value / intervalMs;
for (_i = 0, _len = timeFormats.length; _i < _len; _i++) { for (_i = 0, _len = timeFormats.length; _i < _len; _i++) {
f = timeFormats[_i]; f = timeFormats[_i];
relativePace = rate * f.value; relativePace = rate * f.value;
@ -354,7 +350,7 @@
relativePace = 1; relativePace = 1;
timeUnit = timeFormats[timeFormats.length - 1].name; timeUnit = timeFormats[timeFormats.length - 1].name;
} }
roundedPace = Math.round(relativePace); const roundedPace = Math.round(relativePace);
unit = Humanize.pluralize(roundedPace, unit); unit = Humanize.pluralize(roundedPace, unit);
return '' + prefix + ' ' + roundedPace + ' ' + unit + ' per ' + timeUnit; return '' + prefix + ' ' + roundedPace + ' ' + unit + ' per ' + timeUnit;
}; };
@ -387,21 +383,20 @@
}; };
Humanize.titlecase = Humanize.titleCase = function (string) { Humanize.titlecase = Humanize.titleCase = function (string) {
var doTitleCase; var internalCaps; var smallWords; var splitOnHyphensRegex; var splitOnWhiteSpaceRegex; const smallWords = /\b(a|an|and|at|but|by|de|en|for|if|in|of|on|or|the|to|via|vs?\.?)\b/i;
smallWords = /\b(a|an|and|at|but|by|de|en|for|if|in|of|on|or|the|to|via|vs?\.?)\b/i; const internalCaps = /\S+[A-Z]+\S*/;
internalCaps = /\S+[A-Z]+\S*/; const splitOnWhiteSpaceRegex = /\s+/;
splitOnWhiteSpaceRegex = /\s+/; const splitOnHyphensRegex = /-/;
splitOnHyphensRegex = /-/; const doTitleCase = function (_string, hyphenated, firstOrLast) {
doTitleCase = function (_string, hyphenated, firstOrLast) { let index, word, _i, _len;
var index, stringArray, titleCasedArray, word, _i, _len;
if (hyphenated == null) { if (hyphenated == null) {
hyphenated = false; hyphenated = false;
} }
if (firstOrLast == null) { if (firstOrLast == null) {
firstOrLast = true; firstOrLast = true;
} }
titleCasedArray = []; const titleCasedArray = [];
stringArray = _string.split(hyphenated ? splitOnHyphensRegex : splitOnWhiteSpaceRegex); const stringArray = _string.split(hyphenated ? splitOnHyphensRegex : splitOnWhiteSpaceRegex);
for (index = _i = 0, _len = stringArray.length; _i < _len; index = ++_i) { for (index = _i = 0, _len = stringArray.length; _i < _len; index = ++_i) {
word = stringArray[index]; word = stringArray[index];
if (word.indexOf('-') !== -1) { if (word.indexOf('-') !== -1) {

View File

@ -7,13 +7,13 @@ if (typeof Object.assign !== 'function') {
throw new TypeError('Cannot convert undefined or null to object'); throw new TypeError('Cannot convert undefined or null to object');
} }
var to = Object(target); const to = Object(target);
for (var index = 1; index < arguments.length; index++) { for (let index = 1; index < arguments.length; index++) {
var nextSource = arguments[index]; const nextSource = arguments[index];
if (nextSource != null) { // Skip over if undefined or null if (nextSource != null) { // Skip over if undefined or null
for (var nextKey in nextSource) { for (const nextKey in nextSource) {
// Avoid bugs when hasOwnProperty is shadowed // Avoid bugs when hasOwnProperty is shadowed
if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
to[nextKey] = nextSource[nextKey]; to[nextKey] = nextSource[nextKey];

View File

@ -18,5 +18,5 @@ export default class UserLib {
} }
return false; return false;
} };
} }

View File

@ -16,5 +16,5 @@ export default class WalletLib {
} else { } else {
return price - this.wallet.amount; return price - this.wallet.amount;
} }
} };
} }

View File

@ -0,0 +1,6 @@
export interface GoogleTagManager {
enableAnalytics: (trackingId: string) => void,
trackPage: (url: string, title: string) => void,
trackLogin: () => void,
trackPurchase: (transactionId: number, value: number) => void,
}

View File

@ -1,14 +1,3 @@
/* eslint-disable
no-return-assign,
no-undef,
*/
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
angular.module('application.router', ['ui.router']) angular.module('application.router', ['ui.router'])
.config(['$stateProvider', '$urlRouterProvider', '$locationProvider', function ($stateProvider, $urlRouterProvider, $locationProvider) { .config(['$stateProvider', '$urlRouterProvider', '$locationProvider', function ($stateProvider, $urlRouterProvider, $locationProvider) {
$locationProvider.hashPrefix('!'); $locationProvider.hashPrefix('!');
@ -243,7 +232,7 @@ angular.module('application.router', ['ui.router'])
} }
}, },
resolve: { resolve: {
memberPromise: ['$stateParams', 'Member', function ($stateParams, Member) { return Member.get({ id: $stateParams.id }).$promise; }] memberPromise: ['$transition$', 'Member', function ($transition$, Member) { return Member.get({ id: $transition$.params().id }).$promise; }]
} }
}) })
.state('app.logged.members', { .state('app.logged.members', {
@ -297,7 +286,7 @@ angular.module('application.router', ['ui.router'])
} }
}, },
resolve: { resolve: {
projectPromise: ['$stateParams', 'Project', function ($stateParams, Project) { return Project.get({ id: $stateParams.id }).$promise; }], projectPromise: ['$transition$', 'Project', function ($transition$, Project) { return Project.get({ id: $transition$.params().id }).$promise; }],
shortnamePromise: ['Setting', function (Setting) { return Setting.get({ name: 'disqus_shortname' }).$promise; }] shortnamePromise: ['Setting', function (Setting) { return Setting.get({ name: 'disqus_shortname' }).$promise; }]
} }
}) })
@ -310,7 +299,7 @@ angular.module('application.router', ['ui.router'])
} }
}, },
resolve: { resolve: {
projectPromise: ['$stateParams', 'Project', function ($stateParams, Project) { return Project.get({ id: $stateParams.id }).$promise; }], projectPromise: ['$transition$', 'Project', function ($transition$, Project) { return Project.get({ id: $transition$.params().id }).$promise; }],
allowedExtensions: ['Setting', function (Setting) { return Setting.get({ name: 'allowed_cad_extensions' }).$promise; }] allowedExtensions: ['Setting', function (Setting) { return Setting.get({ name: 'allowed_cad_extensions' }).$promise; }]
} }
}) })
@ -347,7 +336,7 @@ angular.module('application.router', ['ui.router'])
} }
}, },
resolve: { resolve: {
machinePromise: ['Machine', '$stateParams', function (Machine, $stateParams) { return Machine.get({ id: $stateParams.id }).$promise; }] machinePromise: ['Machine', '$transition$', function (Machine, $transition$) { return Machine.get({ id: $transition$.params().id }).$promise; }]
} }
}) })
.state('app.logged.machines_reserve', { .state('app.logged.machines_reserve', {
@ -361,7 +350,7 @@ angular.module('application.router', ['ui.router'])
resolve: { resolve: {
plansPromise: ['Plan', function (Plan) { return Plan.query().$promise; }], plansPromise: ['Plan', function (Plan) { return Plan.query().$promise; }],
groupsPromise: ['Group', function (Group) { return Group.query().$promise; }], groupsPromise: ['Group', function (Group) { return Group.query().$promise; }],
machinePromise: ['Machine', '$stateParams', function (Machine, $stateParams) { return Machine.get({ id: $stateParams.id }).$promise; }], machinePromise: ['Machine', '$transition$', function (Machine, $transition$) { return Machine.get({ id: $transition$.params().id }).$promise; }],
settingsPromise: ['Setting', function (Setting) { settingsPromise: ['Setting', function (Setting) {
return Setting.query({ return Setting.query({
names: "['machine_explications_alert', 'booking_window_start', 'booking_window_end', 'booking_move_enable', " + names: "['machine_explications_alert', 'booking_window_start', 'booking_window_end', 'booking_move_enable', " +
@ -380,7 +369,7 @@ angular.module('application.router', ['ui.router'])
} }
}, },
resolve: { resolve: {
machinePromise: ['Machine', '$stateParams', function (Machine, $stateParams) { return Machine.get({ id: $stateParams.id }).$promise; }] machinePromise: ['Machine', '$transition$', function (Machine, $transition$) { return Machine.get({ id: $transition$.params().id }).$promise; }]
} }
}) })
@ -419,7 +408,7 @@ angular.module('application.router', ['ui.router'])
} }
}, },
resolve: { resolve: {
spacePromise: ['Space', '$stateParams', function (Space, $stateParams) { return Space.get({ id: $stateParams.id }).$promise; }] spacePromise: ['Space', '$transition$', function (Space, $transition$) { return Space.get({ id: $transition$.params().id }).$promise; }]
} }
}) })
.state('app.admin.space_edit', { .state('app.admin.space_edit', {
@ -432,7 +421,7 @@ angular.module('application.router', ['ui.router'])
} }
}, },
resolve: { resolve: {
spacePromise: ['Space', '$stateParams', function (Space, $stateParams) { return Space.get({ id: $stateParams.id }).$promise; }] spacePromise: ['Space', '$transition$', function (Space, $transition$) { return Space.get({ id: $transition$.params().id }).$promise; }]
} }
}) })
.state('app.logged.space_reserve', { .state('app.logged.space_reserve', {
@ -445,7 +434,7 @@ angular.module('application.router', ['ui.router'])
} }
}, },
resolve: { resolve: {
spacePromise: ['Space', '$stateParams', function (Space, $stateParams) { return Space.get({ id: $stateParams.id }).$promise; }], spacePromise: ['Space', '$transition$', function (Space, $transition$) { return Space.get({ id: $transition$.params().id }).$promise; }],
plansPromise: ['Plan', function (Plan) { return Plan.query().$promise; }], plansPromise: ['Plan', function (Plan) { return Plan.query().$promise; }],
groupsPromise: ['Group', function (Group) { return Group.query().$promise; }], groupsPromise: ['Group', function (Group) { return Group.query().$promise; }],
settingsPromise: ['Setting', function (Setting) { settingsPromise: ['Setting', function (Setting) {
@ -482,7 +471,7 @@ angular.module('application.router', ['ui.router'])
} }
}, },
resolve: { resolve: {
trainingPromise: ['Training', '$stateParams', function (Training, $stateParams) { return Training.get({ id: $stateParams.id }).$promise; }] trainingPromise: ['Training', '$transition$', function (Training, $transition$) { return Training.get({ id: $transition$.params().id }).$promise; }]
} }
}) })
.state('app.logged.trainings_reserve', { .state('app.logged.trainings_reserve', {
@ -498,8 +487,8 @@ angular.module('application.router', ['ui.router'])
explicationAlertPromise: ['Setting', function (Setting) { return Setting.get({ name: 'training_explications_alert' }).$promise; }], explicationAlertPromise: ['Setting', function (Setting) { return Setting.get({ name: 'training_explications_alert' }).$promise; }],
plansPromise: ['Plan', function (Plan) { return Plan.query().$promise; }], plansPromise: ['Plan', function (Plan) { return Plan.query().$promise; }],
groupsPromise: ['Group', function (Group) { return Group.query().$promise; }], groupsPromise: ['Group', function (Group) { return Group.query().$promise; }],
trainingPromise: ['Training', '$stateParams', function (Training, $stateParams) { trainingPromise: ['Training', '$transition$', function (Training, $transition$) {
if ($stateParams.id !== 'all') { return Training.get({ id: $stateParams.id }).$promise; } if ($transition$.params().id !== 'all') { return Training.get({ id: $transition$.params().id }).$promise; }
}], }],
settingsPromise: ['Setting', function (Setting) { settingsPromise: ['Setting', function (Setting) {
return Setting.query({ return Setting.query({
@ -563,7 +552,7 @@ angular.module('application.router', ['ui.router'])
} }
}, },
resolve: { resolve: {
eventPromise: ['Event', '$stateParams', function (Event, $stateParams) { return Event.get({ id: $stateParams.id }).$promise; }], eventPromise: ['Event', '$transition$', function (Event, $transition$) { return Event.get({ id: $transition$.params().id }).$promise; }],
priceCategoriesPromise: ['PriceCategory', function (PriceCategory) { return PriceCategory.query().$promise; }], priceCategoriesPromise: ['PriceCategory', function (PriceCategory) { return PriceCategory.query().$promise; }],
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['booking_move_enable', 'booking_move_delay', 'booking_cancel_enable', 'booking_cancel_delay', 'event_explications_alert', 'online_payment_module']" }).$promise; }] settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['booking_move_enable', 'booking_move_delay', 'booking_cancel_enable', 'booking_cancel_delay', 'event_explications_alert', 'online_payment_module']" }).$promise; }]
} }
@ -694,7 +683,7 @@ angular.module('application.router', ['ui.router'])
} }
}, },
resolve: { resolve: {
trainingPromise: ['Training', '$stateParams', function (Training, $stateParams) { return Training.get({ id: $stateParams.id }).$promise; }], trainingPromise: ['Training', '$transition$', function (Training, $transition$) { return Training.get({ id: $transition$.params().id }).$promise; }],
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }] machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }]
} }
}) })
@ -740,7 +729,7 @@ angular.module('application.router', ['ui.router'])
} }
}, },
resolve: { resolve: {
eventPromise: ['Event', '$stateParams', function (Event, $stateParams) { return Event.get({ id: $stateParams.id }).$promise; }], eventPromise: ['Event', '$transition$', function (Event, $transition$) { return Event.get({ id: $transition$.params().id }).$promise; }],
categoriesPromise: ['Category', function (Category) { return Category.query().$promise; }], categoriesPromise: ['Category', function (Category) { return Category.query().$promise; }],
themesPromise: ['EventTheme', function (EventTheme) { return EventTheme.query().$promise; }], themesPromise: ['EventTheme', function (EventTheme) { return EventTheme.query().$promise; }],
ageRangesPromise: ['AgeRange', function (AgeRange) { return AgeRange.query().$promise; }], ageRangesPromise: ['AgeRange', function (AgeRange) { return AgeRange.query().$promise; }],
@ -756,8 +745,8 @@ angular.module('application.router', ['ui.router'])
} }
}, },
resolve: { resolve: {
eventPromise: ['Event', '$stateParams', function (Event, $stateParams) { return Event.get({ id: $stateParams.id }).$promise; }], eventPromise: ['Event', '$transition$', function (Event, $transition$) { return Event.get({ id: $transition$.params().id }).$promise; }],
reservationsPromise: ['Reservation', '$stateParams', function (Reservation, $stateParams) { return Reservation.query({ reservable_id: $stateParams.id, reservable_type: 'Event' }).$promise; }] reservationsPromise: ['Reservation', '$transition$', function (Reservation, $transition$) { return Reservation.query({ reservable_id: $transition$.params().id, reservable_type: 'Event' }).$promise; }]
} }
}) })
@ -820,7 +809,7 @@ angular.module('application.router', ['ui.router'])
spaces: ['Space', function (Space) { return Space.query().$promise; }], spaces: ['Space', function (Space) { return Space.query().$promise; }],
machines: ['Machine', function (Machine) { return Machine.query().$promise; }], machines: ['Machine', function (Machine) { return Machine.query().$promise; }],
plans: ['Plan', function (Plan) { return Plan.query().$promise; }], plans: ['Plan', function (Plan) { return Plan.query().$promise; }],
planPromise: ['Plan', '$stateParams', function (Plan, $stateParams) { return Plan.get({ id: $stateParams.id }).$promise; }], planPromise: ['Plan', '$transition$', function (Plan, $transition$) { return Plan.get({ id: $transition$.params().id }).$promise; }],
planCategories: ['PlanCategory', function (PlanCategory) { return PlanCategory.query().$promise; }] planCategories: ['PlanCategory', function (PlanCategory) { return PlanCategory.query().$promise; }]
} }
}) })
@ -854,7 +843,7 @@ angular.module('application.router', ['ui.router'])
} }
}, },
resolve: { resolve: {
couponPromise: ['Coupon', '$stateParams', function (Coupon, $stateParams) { return Coupon.get({ id: $stateParams.id }).$promise; }] couponPromise: ['Coupon', '$transition$', function (Coupon, $transition$) { return Coupon.get({ id: $transition$.params().id }).$promise; }]
} }
}) })
@ -879,7 +868,8 @@ angular.module('application.router', ['ui.router'])
"'accounting_Machine_code', 'accounting_Machine_label', 'accounting_Training_code', 'accounting_Training_label', " + "'accounting_Machine_code', 'accounting_Machine_label', 'accounting_Training_code', 'accounting_Training_label', " +
"'accounting_Event_code', 'accounting_Event_label', 'accounting_Space_code', 'accounting_Space_label', " + "'accounting_Event_code', 'accounting_Event_label', 'accounting_Space_code', 'accounting_Space_label', " +
"'payment_gateway', 'accounting_Error_code', 'accounting_Error_label', 'payment_schedule_prefix', " + "'payment_gateway', 'accounting_Error_code', 'accounting_Error_label', 'payment_schedule_prefix', " +
"'feature_tour_display', 'online_payment_module', 'stripe_public_key', 'stripe_currency', 'invoice_prefix']" "'feature_tour_display', 'online_payment_module', 'stripe_public_key', 'stripe_currency', 'invoice_prefix', " +
"'accounting_Pack_code', 'accounting_Pack_label']"
}).$promise; }).$promise;
}], }],
stripeSecretKey: ['Setting', function (Setting) { return Setting.isPresent({ name: 'stripe_secret_key' }).$promise; }], stripeSecretKey: ['Setting', function (Setting) { return Setting.isPresent({ name: 'stripe_secret_key' }).$promise; }],
@ -958,7 +948,7 @@ angular.module('application.router', ['ui.router'])
} }
}, },
resolve: { resolve: {
importItem: ['Import', '$stateParams', function (Import, $stateParams) { return Import.get({ id: $stateParams.id }).$promise; }] importItem: ['Import', '$transition$', function (Import, $transition$) { return Import.get({ id: $transition$.params().id }).$promise; }]
} }
}) })
.state('app.admin.members_edit', { .state('app.admin.members_edit', {
@ -970,9 +960,9 @@ angular.module('application.router', ['ui.router'])
} }
}, },
resolve: { resolve: {
memberPromise: ['Member', '$stateParams', function (Member, $stateParams) { return Member.get({ id: $stateParams.id }).$promise; }], memberPromise: ['Member', '$transition$', function (Member, $transition$) { return Member.get({ id: $transition$.params().id }).$promise; }],
activeProviderPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.active().$promise; }], activeProviderPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.active().$promise; }],
walletPromise: ['Wallet', '$stateParams', function (Wallet, $stateParams) { return Wallet.getWalletByUser({ user_id: $stateParams.id }).$promise; }], walletPromise: ['Wallet', '$transition$', function (Wallet, $transition$) { return Wallet.getWalletByUser({ user_id: $transition$.params().id }).$promise; }],
transactionsPromise: ['Wallet', 'walletPromise', function (Wallet, walletPromise) { return Wallet.transactions({ id: walletPromise.id }).$promise; }], transactionsPromise: ['Wallet', 'walletPromise', function (Wallet, walletPromise) { return Wallet.transactions({ id: walletPromise.id }).$promise; }],
tagsPromise: ['Tag', function (Tag) { return Tag.query().$promise; }], tagsPromise: ['Tag', function (Tag) { return Tag.query().$promise; }],
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['phone_required', 'address_required']" }).$promise; }] settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['phone_required', 'address_required']" }).$promise; }]
@ -1027,7 +1017,7 @@ angular.module('application.router', ['ui.router'])
} }
}, },
resolve: { resolve: {
providerPromise: ['AuthProvider', '$stateParams', function (AuthProvider, $stateParams) { return AuthProvider.get({ id: $stateParams.id }).$promise; }], providerPromise: ['AuthProvider', '$transition$', function (AuthProvider, $transition$) { return AuthProvider.get({ id: $transition$.params().id }).$promise; }],
mappingFieldsPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.mapping_fields().$promise; }] mappingFieldsPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.mapping_fields().$promise; }]
} }
}) })
@ -1083,7 +1073,7 @@ angular.module('application.router', ['ui.router'])
"'display_name_enable', 'machines_sort_by', 'fab_analytics', 'statistics_module', 'address_required', " + "'display_name_enable', 'machines_sort_by', 'fab_analytics', 'statistics_module', 'address_required', " +
"'link_name', 'home_content', 'home_css', 'phone_required', 'upcoming_events_shown', 'public_agenda_module'," + "'link_name', 'home_content', 'home_css', 'phone_required', 'upcoming_events_shown', 'public_agenda_module'," +
"'renew_pack_threshold', 'pack_only_for_subscription', 'overlapping_categories', 'public_registrations'," + "'renew_pack_threshold', 'pack_only_for_subscription', 'overlapping_categories', 'public_registrations'," +
"'extended_prices_in_same_day']" "'extended_prices_in_same_day', 'recaptcha_site_key', 'recaptcha_secret_key']"
}).$promise; }).$promise;
}], }],
privacyDraftsPromise: ['Setting', function (Setting) { return Setting.get({ name: 'privacy_draft', history: true }).$promise; }], privacyDraftsPromise: ['Setting', function (Setting) { return Setting.get({ name: 'privacy_draft', history: true }).$promise; }],

View File

@ -14,7 +14,7 @@ Application.Services.service('Diacritics', [
* @returns {string} without diacritics * @returns {string} without diacritics
*/ */
remove: function (str) { remove: function (str) {
var defaultDiacriticsRemovalap = [ const defaultDiacriticsRemovalap = [
{ base: 'A', letters: '\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F' }, { base: 'A', letters: '\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F' },
{ base: 'AA', letters: '\uA732' }, { base: 'AA', letters: '\uA732' },
{ base: 'AE', letters: '\u00C6\u01FC\u01E2' }, { base: 'AE', letters: '\u00C6\u01FC\u01E2' },
@ -103,10 +103,10 @@ Application.Services.service('Diacritics', [
{ base: 'z', letters: '\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763' } { base: 'z', letters: '\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763' }
]; ];
var diacriticsMap = {}; const diacriticsMap = {};
for (var i = 0; i < defaultDiacriticsRemovalap.length; i++) { for (let i = 0; i < defaultDiacriticsRemovalap.length; i++) {
var letters = defaultDiacriticsRemovalap[i].letters.split(''); const letters = defaultDiacriticsRemovalap[i].letters.split('');
for (var j = 0; j < letters.length; j++) { for (let j = 0; j < letters.length; j++) {
diacriticsMap[letters[j]] = defaultDiacriticsRemovalap[i].base; diacriticsMap[letters[j]] = defaultDiacriticsRemovalap[i].base;
} }
} }

View File

@ -1,3 +1,5 @@
@use "sass:math";
// This is the default html and body font-size for the base rem value. // This is the default html and body font-size for the base rem value.
$rem-base: 10px !default; $rem-base: 10px !default;
@ -20,12 +22,12 @@ $modules: () !default;
// STRIP UNIT // STRIP UNIT
// It strips the unit of measure and returns it // It strips the unit of measure and returns it
@function strip-unit($num) { @function strip-unit($num) {
@return $num / ($num * 0 + 1); @return math.div($num, $num * 0 + 1);
} }
// CONVERT TO REM // CONVERT TO REM
@function convert-to-rem($value, $base-value: $rem-base) { @function convert-to-rem($value, $base-value: $rem-base) {
$value: strip-unit($value) / strip-unit($base-value) * 1rem; $value: math.div(strip-unit($value), strip-unit($base-value)) * 1rem;
@if $value == 0rem { @if $value == 0rem {
$value: 0; $value: 0;

View File

@ -1,3 +1,5 @@
@use 'sass:math';
/*layout*/ /*layout*/
.header, .header,
.footer { .footer {
@ -286,8 +288,8 @@ body.container {
height: $header-md-height; height: $header-md-height;
.navbar-form { .navbar-form {
margin-top: floor(($header-md-height - 30) / 2); margin-top: floor(math.div($header-md-height - 30, 2));
margin-bottom: floor(($header-md-height - 30) / 2); margin-bottom: floor(math.div($header-md-height - 30, 2));
} }
} }

View File

@ -1,3 +1,5 @@
@use 'sass:math';
/*primary nav*/ /*primary nav*/
.navbar-header { .navbar-header {
position: relative; position: relative;
@ -42,7 +44,7 @@
.nav-primary { .nav-primary {
li { li {
> a > i { > a > i {
margin: floor(-($nav-primary-height - $line-height-computed) / 2) -10px; margin: floor(math.div(-($nav-primary-height - $line-height-computed), 2)) -10px;
line-height: $nav-primary-height; line-height: $nav-primary-height;
width: $nav-primary-height; width: $nav-primary-height;
float: left; float: left;
@ -61,7 +63,7 @@
ul.nav { ul.nav {
> li { > li {
> a { > a {
padding: floor(($nav-primary-height - $line-height-computed) / 2) 15px; padding: floor(math.div($nav-primary-height - $line-height-computed, 2)) 15px;
position: relative; position: relative;
font-size: 14px; font-size: 14px;
@ -245,7 +247,7 @@
> .vbox > .header, > .vbox > .header,
> .vbox > .footer { > .vbox > .footer {
padding: 0 floor(($nav-xs-width - 30px) / 2); padding: 0 floor(math.div($nav-xs-width - 30px, 2));
} }
.hidden-nav-xs { .hidden-nav-xs {
@ -309,7 +311,7 @@
> li { > li {
> a { > a {
.header-md & { .header-md & {
padding: floor(($header-md-height - $line-height-computed) / 2 - 1); padding: floor(math.div($header-md-height - $line-height-computed, 2) - 1);
} }
} }
} }

View File

@ -1 +1,3 @@
@import "~fullcalendar/dist/fullcalendar.print"; @media print {
@import "~fullcalendar/dist/fullcalendar.print";
}

View File

@ -1,25 +1,28 @@
.cookies-consent { .cookies-consent {
display: flex; display: flex;
position: fixed; position: fixed;
bottom: 3rem; right: 0;
left: 3rem; bottom: 0;
width: 40rem; left: 0;
background-color: #f5f5f5; background-color: #f5f5f5;
padding: 3rem; padding: 3rem;
flex-direction: column; flex-direction: column;
z-index: 100; z-index: 100;
-webkit-box-shadow: 0 4px 10px 2px rgba(224, 224, 224, 0.43); -webkit-box-shadow: 0 4px 10px 2px rgba(0, 0, 0, 0.25);
-moz-box-shadow: 0 4px 10px 2px rgba(224, 224, 224, 0.43); -moz-box-shadow: 0 4px 10px 2px rgba(0, 0, 0, 0.25);
box-shadow: 0 4px 10px 2px rgba(224, 224, 224, 0.43); box-shadow: 0 4px 10px 2px rgba(0, 0, 0, 0.25);
.cookies-actions { .cookies-actions {
flex-wrap: wrap;
display: flex; display: flex;
height: 45px; justify-content: space-between;
gap: 1rem;
margin-top: 1rem;
button { button {
flex-basis: 50%; @extend .fab-button;
flex: 1;
} }
button.decline { button.decline {
background-color: transparent; background-color: transparent;
border: 0; border: 0;
@ -31,4 +34,10 @@
font-size: 17px; font-size: 17px;
} }
} }
@media (min-width: 480px) {
bottom: 3rem;
left: 3rem;
width: 40rem;
}
} }

View File

@ -90,4 +90,15 @@
</div> </div>
</div> </div>
<div class="form-group" ng-class="{'has-error': providerForm['auth_provider[scopes]'].$dirty && providerForm['auth_provider[scopes]'].$invalid}">
<label for="provider_client_secret" class="col-sm-3 control-label" translate>{{ 'app.shared.oauth2.scopes' }}</label>
<div class="col-sm-9">
<input type="text"
ng-model="provider.providable_attributes.scopes"
class="form-control"
name="auth_provider[scopes]"
id="provider_scopes"
placeholder="profile,email...">
</div>
</div>
<ng-include src="'/admin/authentications/_oauth2_mapping.html'"></ng-include> <ng-include src="'/admin/authentications/_oauth2_mapping.html'"></ng-include>

View File

@ -106,6 +106,16 @@
<input type="text" id="spaceLabel" ng-model="settings.spaceLabel.value" class="form-control" placeholder="{{ 'app.admin.invoices.general_space_label' | translate }}"/> <input type="text" id="spaceLabel" ng-model="settings.spaceLabel.value" class="form-control" placeholder="{{ 'app.admin.invoices.general_space_label' | translate }}"/>
</div> </div>
</div> </div>
<div class="row">
<div class="col-md-6">
<label for="packCode" translate>{{ 'app.admin.invoices.accounting_Pack_code' }}</label>
<input type="text" id="packCode" ng-model="settings.packCode.value" class="form-control" placeholder="{{ 'app.admin.invoices.general_pack_code' | translate }}"/>
</div>
<div class="col-md-6">
<label for="packLabel" translate>{{ 'app.admin.invoices.accounting_Pack_label' }}</label>
<input type="text" id="packLabel" ng-model="settings.packLabel.value" class="form-control" placeholder="{{ 'app.admin.invoices.general_pack_label' | translate }}"/>
</div>
</div>
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-md-6">
<label for="spaceCode" translate>{{ 'app.admin.invoices.accounting_Error_code' }}</label> <label for="spaceCode" translate>{{ 'app.admin.invoices.accounting_Error_code' }}</label>

View File

@ -42,7 +42,7 @@
<div class="form-group"> <div class="form-group">
<div class="input-group"> <div class="input-group">
<div class="input-group-addon"><i class="fa fa-search"></i></div> <div class="input-group-addon"><i class="fa fa-search"></i></div>
<input type="search" class="form-control" placeholder="Mots-clés" ng-model="search.q"/> <input type="search" class="form-control" placeholder="{{ 'app.public.projects_list.keywords' | translate }}" ng-model="search.q"/>
<div class="input-group-btn"> <div class="input-group-btn">
<button type="submit" class="btn btn-warning" translate>{{ 'app.public.projects_list.search' }}</button> <button type="submit" class="btn btn-warning" translate>{{ 'app.public.projects_list.search' }}</button>
</div> </div>

View File

@ -19,6 +19,8 @@ class AccountingPeriod < ApplicationRecord
validates_with PeriodOverlapValidator validates_with PeriodOverlapValidator
validates_with PeriodIntegrityValidator validates_with PeriodIntegrityValidator
belongs_to :user, class_name: 'User', foreign_key: 'closed_by'
def delete def delete
false false
end end
@ -79,13 +81,15 @@ class AccountingPeriod < ApplicationRecord
end end
def compute_totals def compute_totals
period_invoices = invoices_with_vat(invoices.where(type: nil)) period_invoices = invoices_with_vat(invoices.where(type: nil).includes([:invoice_items]))
period_avoirs = invoices_with_vat(invoices.where(type: 'Avoir')) period_avoirs = invoices_with_vat(invoices.where(type: 'Avoir').includes([:invoice_items]))
self.period_total = (period_invoices.map(&method(:price_without_taxe)).reduce(:+) || 0) - self.period_total = (period_invoices.map(&method(:price_without_taxe)).reduce(:+) || 0) -
(period_avoirs.map(&method(:price_without_taxe)).reduce(:+) || 0) (period_avoirs.map(&method(:price_without_taxe)).reduce(:+) || 0)
all_invoices = invoices_with_vat(Invoice.where('CAST(created_at AS DATE) <= :end_date AND type IS NULL', end_date: end_at)) all_invoices = invoices_with_vat(Invoice.where('CAST(created_at AS DATE) <= :end_date AND type IS NULL', end_date: end_at)
all_avoirs = invoices_with_vat(Invoice.where("CAST(created_at AS DATE) <= :end_date AND type = 'Avoir'", end_date: end_at)) .includes([:invoice_items]))
all_avoirs = invoices_with_vat(Invoice.where("CAST(created_at AS DATE) <= :end_date AND type = 'Avoir'", end_date: end_at)
.includes([:invoice_items]))
self.perpetual_total = (all_invoices.map(&method(:price_without_taxe)).reduce(:+) || 0) - self.perpetual_total = (all_invoices.map(&method(:price_without_taxe)).reduce(:+) || 0) -
(all_avoirs.map(&method(:price_without_taxe)).reduce(:+) || 0) (all_avoirs.map(&method(:price_without_taxe)).reduce(:+) || 0)
self.footprint = compute_footprint self.footprint = compute_footprint

View File

@ -8,11 +8,6 @@ class InvoiceItem < Footprintable
has_one :payment_gateway_object, as: :item has_one :payment_gateway_object, as: :item
belongs_to :object, polymorphic: true belongs_to :object, polymorphic: true
belongs_to :reservation, foreign_type: 'Reservation', foreign_key: 'object_id'
belongs_to :subscription, foreign_type: 'Subscription', foreign_key: 'object_id'
belongs_to :wallet_transaction, foreign_type: 'WalletTransaction', foreign_key: 'object_id'
belongs_to :offer_day, foreign_type: 'OfferDay', foreign_key: 'object_id'
belongs_to :statistic_profile_prepaid_pack, foreign_type: 'StatisticProfilePrepaidPack', foreign_key: 'object_id'
after_create :chain_record after_create :chain_record
after_update :log_changes after_update :log_changes

View File

@ -1,4 +0,0 @@
class OpenAPI::CallsCountTracing < ApplicationRecord
belongs_to :projets, foreign_key: :open_api_client_id
validates :projets, :at, presence: true
end

View File

@ -2,8 +2,6 @@
# OpenAPI::Client keeps track of the authorized accesses to the 3-rd party API (aka. OpenAPI) # OpenAPI::Client keeps track of the authorized accesses to the 3-rd party API (aka. OpenAPI)
class OpenAPI::Client < ApplicationRecord class OpenAPI::Client < ApplicationRecord
has_many :calls_count_tracings, foreign_key: :open_api_client_id, dependent: :destroy
validates :name, presence: true validates :name, presence: true
validates_uniqueness_of :token validates_uniqueness_of :token

View File

@ -128,7 +128,9 @@ class Setting < ApplicationRecord
pack_only_for_subscription pack_only_for_subscription
overlapping_categories overlapping_categories
extended_prices_in_same_day extended_prices_in_same_day
public_registrations] } public_registrations
accounting_Pack_code
accounting_Pack_label] }
# WARNING: when adding a new key, you may also want to add it in: # WARNING: when adding a new key, you may also want to add it in:
# - config/locales/en.yml#settings # - config/locales/en.yml#settings
# - app/frontend/src/javascript/models/setting.ts#SettingName # - app/frontend/src/javascript/models/setting.ts#SettingName
@ -195,4 +197,11 @@ class Setting < ApplicationRecord
setting = find_or_initialize_by(name: name) setting = find_or_initialize_by(name: name)
setting.save && setting.history_values.create(invoicing_profile: user.invoicing_profile, value: value.to_s) setting.save && setting.history_values.create(invoicing_profile: user.invoicing_profile, value: value.to_s)
end end
##
# Check if the given setting was set
##
def self.set?(name)
find_by(name: name)&.value.nil? ? false : true
end
end end

View File

@ -49,6 +49,8 @@ class User < ApplicationRecord
has_one :payment_gateway_object, as: :item has_one :payment_gateway_object, as: :item
has_many :accounting_periods, foreign_key: 'closed_by', dependent: :nullify
# fix for create admin user # fix for create admin user
before_save do before_save do
email&.downcase! email&.downcase!

View File

@ -25,9 +25,9 @@ class PDF::Invoice < Prawn::Document
) )
# logo # logo
img_b64 = Setting.find_by(name: 'invoice_logo') img_b64 = Setting.get('invoice_logo')
begin begin
image StringIO.new(Base64.decode64(img_b64.value)), fit: [415, 40] image StringIO.new(Base64.decode64(img_b64)), fit: [415, 40]
rescue StandardError => e rescue StandardError => e
puts "Unable to decode invoice logo from base64: #{e}" puts "Unable to decode invoice logo from base64: #{e}"
end end
@ -97,9 +97,9 @@ class PDF::Invoice < Prawn::Document
DATE: I18n.l(invoice.main_item.object.slots[0].start_at.to_date), DATE: I18n.l(invoice.main_item.object.slots[0].start_at.to_date),
TIME: I18n.l(invoice.main_item.object.slots[0].start_at, format: :hour_minute)) TIME: I18n.l(invoice.main_item.object.slots[0].start_at, format: :hour_minute))
invoice.invoice_items.each do |item| invoice.invoice_items.each do |item|
next unless item.subscription next unless item.object_type == Subscription.name
subscription = item.subscription subscription = item.object
cancellation = invoice.is_a?(Avoir) ? I18n.t('invoices.cancellation') + ' - ' : '' cancellation = invoice.is_a?(Avoir) ? I18n.t('invoices.cancellation') + ' - ' : ''
object = "\n- #{object}\n- #{cancellation + subscription_verbose(subscription, name)}" object = "\n- #{object}\n- #{cancellation + subscription_verbose(subscription, name)}"
break break
@ -135,7 +135,7 @@ class PDF::Invoice < Prawn::Document
details = invoice.is_a?(Avoir) ? I18n.t('invoices.cancellation') + ' - ' : '' details = invoice.is_a?(Avoir) ? I18n.t('invoices.cancellation') + ' - ' : ''
if item.object_type == Subscription.name if item.object_type == Subscription.name
subscription = item.subscription subscription = item.object
if invoice.main_item.object_type == 'OfferDay' if invoice.main_item.object_type == 'OfferDay'
details += I18n.t('invoices.subscription_extended_for_free_from_START_to_END', details += I18n.t('invoices.subscription_extended_for_free_from_START_to_END',
START: I18n.l(invoice.main_item.object.start_at.to_date), START: I18n.l(invoice.main_item.object.start_at.to_date),

View File

@ -28,9 +28,9 @@ class PDF::PaymentSchedule < Prawn::Document
) )
# logo # logo
img_b64 = Setting.find_by(name: 'invoice_logo') img_b64 = Setting.get('invoice_logo')
begin begin
image StringIO.new(Base64.decode64(img_b64.value)), fit: [415, 40] image StringIO.new(Base64.decode64(img_b64)), fit: [415, 40]
rescue StandardError => e rescue StandardError => e
puts "Unable to decode invoice logo from base64: #{e}" puts "Unable to decode invoice logo from base64: #{e}"
end end

View File

@ -20,6 +20,6 @@ class ProjectPolicy < ApplicationPolicy
end end
def destroy? def destroy?
user.admin? or record.author.user_id == user user.admin? or record.author.user_id == user.id
end end
end end

View File

@ -3,7 +3,7 @@
# Check the access policies for API::SubscriptionsController # Check the access policies for API::SubscriptionsController
class SubscriptionPolicy < ApplicationPolicy class SubscriptionPolicy < ApplicationPolicy
def show? def show?
user.admin? or record.user_id == user.id user.admin? || user.manager? || record.user.id == user.id
end end
def payment_details? def payment_details?

View File

@ -69,6 +69,8 @@ class AccountingExportService
end end
elsif invoice.main_item.object_type == 'WalletTransaction' elsif invoice.main_item.object_type == 'WalletTransaction'
rows << "#{wallet_row(invoice)}\n" rows << "#{wallet_row(invoice)}\n"
elsif invoice.main_item.object_type == 'StatisticProfilePrepaidPack'
rows << "#{pack_row(invoice)}\n"
elsif invoice.main_item.object_type == 'Error' elsif invoice.main_item.object_type == 'Error'
items = invoice.invoice_items.reject { |ii| ii.object_type == 'Subscription' } items = invoice.invoice_items.reject { |ii| ii.object_type == 'Subscription' }
items.each do |item| items.each do |item|
@ -131,6 +133,16 @@ class AccountingExportService
) )
end end
def pack_row(invoice)
row(
invoice,
account(invoice, :pack),
account(invoice, :pack, type: :label),
invoice.invoice_items.first.net_amount / 100.00,
line_label: label(invoice)
)
end
# Generate the "VAT" row, which contains the credit to the VAT account, with VAT amount only # Generate the "VAT" row, which contains the credit to the VAT account, with VAT amount only
def vat_row(invoice) def vat_row(invoice)
total = invoice.invoice_items.map(&:net_amount).sum total = invoice.invoice_items.map(&:net_amount).sum
@ -195,29 +207,35 @@ class AccountingExportService
def account(invoice, account, type: :code, means: :other) def account(invoice, account, type: :code, means: :other)
case account case account
when :projets when :projets
Setting.find_by(name: "accounting_#{means}_client_#{type}")&.value Setting.get("accounting_#{means}_client_#{type}")
when :vat when :vat
Setting.find_by(name: "accounting_VAT_#{type}")&.value Setting.get("accounting_VAT_#{type}")
when :subscription when :subscription
if invoice.subscription_invoice? if invoice.subscription_invoice?
Setting.find_by(name: "accounting_subscription_#{type}")&.value Setting.get("accounting_subscription_#{type}")
else else
puts "WARN: Invoice #{invoice.id} has no subscription" puts "WARN: Invoice #{invoice.id} has no subscription"
end end
when :reservation when :reservation
if invoice.main_item.object_type == 'Reservation' if invoice.main_item.object_type == 'Reservation'
Setting.find_by(name: "accounting_#{invoice.main_item.object.reservable_type}_#{type}")&.value Setting.get("accounting_#{invoice.main_item.object.reservable_type}_#{type}")
else else
puts "WARN: Invoice #{invoice.id} has no reservation" puts "WARN: Invoice #{invoice.id} has no reservation"
end end
when :wallet when :wallet
if invoice.main_item.object_type == 'WalletTransaction' if invoice.main_item.object_type == 'WalletTransaction'
Setting.find_by(name: "accounting_wallet_#{type}")&.value Setting.get("accounting_wallet_#{type}")
else else
puts "WARN: Invoice #{invoice.id} is not a wallet credit" puts "WARN: Invoice #{invoice.id} is not a wallet credit"
end end
when :pack
if invoice.main_item.object_type == 'StatisticProfilePrepaidPack'
Setting.get("accounting_Pack_#{type}")
else
puts "WARN: Invoice #{invoice.id} has no prepaid-pack"
end
when :error when :error
Setting.find_by(name: "accounting_Error_#{type}")&.value Setting.get("accounting_Error_#{type}")
else else
puts "Unsupported account #{account}" puts "Unsupported account #{account}"
end || '' end || ''

View File

@ -46,7 +46,7 @@ class Members::MembersService
@member.update_statistic_profile @member.update_statistic_profile
@member.generate_subscription_invoice(current_user.id) @member.generate_subscription_invoice(current_user.id)
@member.send_confirmation_instructions @member.send_confirmation_instructions
UsersMailer.delay.notify_user_account_created(@member, @member.password) UsersMailer.notify_user_account_created(@member, @member.password).deliver_later
true true
else else
false false

View File

@ -126,13 +126,11 @@ class StatisticService
def subscriptions_list(options = default_options) def subscriptions_list(options = default_options)
result = [] result = []
InvoiceItem.where('invoice_items.created_at >= :start_date AND invoice_items.created_at <= :end_date', options) InvoiceItem.where("object_type = '#{Subscription.name}' AND invoice_items.created_at >= :start_date AND invoice_items.created_at <= :end_date", options)
.eager_load(invoice: [:coupon], subscription: [:plan, statistic_profile: [:group]]).each do |i| .eager_load(invoice: [:coupon]).each do |i|
next if i.invoice.is_a?(Avoir) next if i.invoice.is_a?(Avoir)
sub = i.subscription sub = i.object
next unless sub
ca = i.amount.to_i ca = i.amount.to_i
cs = CouponService.new cs = CouponService.new

View File

@ -46,7 +46,7 @@ class UserService
admin.send_confirmation_instructions admin.send_confirmation_instructions
admin.add_role(:admin) admin.add_role(:admin)
admin.remove_role(:member) admin.remove_role(:member)
UsersMailer.delay.notify_user_account_created(admin, generated_password) UsersMailer.notify_user_account_created(admin, generated_password).deliver_later
end end
{ saved: saved, user: admin } { saved: saved, user: admin }
end end
@ -61,7 +61,7 @@ class UserService
manager.send_confirmation_instructions manager.send_confirmation_instructions
manager.add_role(:manager) manager.add_role(:manager)
manager.remove_role(:member) manager.remove_role(:member)
UsersMailer.delay.notify_user_account_created(manager, generated_password) UsersMailer.notify_user_account_created(manager, generated_password).deliver_later
end end
{ saved: saved, user: manager } { saved: saved, user: manager }
end end

View File

@ -4,7 +4,7 @@ json.partial! 'api/auth_providers/auth_provider', auth_provider: @provider
if @provider.providable_type == OAuth2Provider.name if @provider.providable_type == OAuth2Provider.name
json.providable_attributes do json.providable_attributes do
json.extract! @provider.providable, :id, :base_url, :token_endpoint, :authorization_endpoint, :profile_url, :client_id, :client_secret json.extract! @provider.providable, :id, :base_url, :token_endpoint, :authorization_endpoint, :profile_url, :client_id, :client_secret, :scopes
json.o_auth2_mappings_attributes @provider.providable.o_auth2_mappings do |m| json.o_auth2_mappings_attributes @provider.providable.o_auth2_mappings do |m|
json.extract! m, :id, :local_model, :local_field, :api_field, :api_endpoint, :api_data_type, :transformation json.extract! m, :id, :local_model, :local_field, :api_field, :api_endpoint, :api_data_type, :transformation
end end

View File

@ -67,9 +67,7 @@
Fablab.sessionTours = []; Fablab.sessionTours = [];
</script> </script>
<%= stylesheet_packs_with_chunks_tag 'application', media: 'all' %> <%= stylesheet_pack_tag 'application', 'plugins', 'printer' %>
<%= stylesheet_packs_with_chunks_tag 'plugins', media: 'all' %>
<%= stylesheet_packs_with_chunks_tag 'printer', media: 'print' %>
<% unless Stylesheet.theme.nil? %> <% unless Stylesheet.theme.nil? %>
<link rel="stylesheet" media="all" href="<%= stylesheet_path(Stylesheet.theme.id) %>-<%= Stylesheet.theme.updated_at.to_i.to_s %>.css" /> <link rel="stylesheet" media="all" href="<%= stylesheet_path(Stylesheet.theme.id) %>-<%= Stylesheet.theme.updated_at.to_i.to_s %>.css" />
<% end %> <% end %>
@ -134,6 +132,6 @@
<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> </div>
<%= javascript_packs_with_chunks_tag 'application' %> <%= javascript_pack_tag 'application' %>
</body> </body>
</html> </html>

View File

@ -1,10 +0,0 @@
class OpenAPITraceCallsCountWorker < Sidekiq::Workers
include Sidekiq::Worker
sidekiq_options queue: 'default', retry: true
def perform
OpenAPI::Client.find_each do |client|
OpenAPI::CallsCountTracing.create!(projets: client, calls_count: client.calls_count, at: DateTime.current)
end
end
end

View File

@ -7,7 +7,7 @@ class OpenlabWorker
def initialize def initialize
client = Openlab::Client.new(app_secret: Setting.get('openlab_app_secret')) client = Openlab::Client.new(app_secret: Setting.get('openlab_app_secret'))
@projets = Openlab::Projects.new(client) @projects = Openlab::Projects.new(client)
super super
end end
@ -17,12 +17,12 @@ class OpenlabWorker
case action.to_s case action.to_s
when /create/ when /create/
project = Project.find(project_id) project = Project.find(project_id)
response = @projets.create(project.openlab_attributes) response = @projects.create(project.openlab_attributes)
when /update/ when /update/
project = Project.find(project_id) project = Project.find(project_id)
response = @projets.update(project_id, project.openlab_attributes) response = @projects.update(project_id, project.openlab_attributes)
when /destroy/ when /destroy/
response = @projets.destroy(project_id) response = @projects.destroy(project_id)
else else
raise NotImplementedError raise NotImplementedError
end end

View File

@ -1,3 +1,6 @@
# frozen_string_literal: true
# Send a reminder email to the user who has made a reservation
class ReservationReminderWorker class ReservationReminderWorker
include Sidekiq::Worker include Sidekiq::Worker
@ -5,8 +8,8 @@ class ReservationReminderWorker
DEFAULT_REMINDER_DELAY = 24.hours DEFAULT_REMINDER_DELAY = 24.hours
def perform def perform
enabled = Setting.find_by(name: 'reminder_enable').try(:value) return unless Setting.get('reminder_enable')
if enabled == 'true'
delay = Setting.find_by(name: 'reminder_delay').try(:value).try(:to_i).try(:hours) || DEFAULT_REMINDER_DELAY delay = Setting.find_by(name: 'reminder_delay').try(:value).try(:to_i).try(:hours) || DEFAULT_REMINDER_DELAY
starting = DateTime.current.beginning_of_hour + delay starting = DateTime.current.beginning_of_hour + delay
@ -18,12 +21,11 @@ class ReservationReminderWorker
attached_object_id: r.id, attached_object_id: r.id,
notification_type_id: NotificationType.find_by_name('notify_member_reservation_reminder') notification_type_id: NotificationType.find_by_name('notify_member_reservation_reminder')
).count ).count
unless already_sent > 0 next if already_sent.positive?
NotificationCenter.call type: 'notify_member_reservation_reminder', NotificationCenter.call type: 'notify_member_reservation_reminder',
receiver: r.user, receiver: r.user,
attached_object: r attached_object: r
end end
end end
end
end
end end

View File

@ -4,7 +4,6 @@ module.exports = function (api) {
const isDevelopmentEnv = api.env('development'); const isDevelopmentEnv = api.env('development');
const isProductionEnv = api.env('production'); const isProductionEnv = api.env('production');
const isTestEnv = api.env('test'); const isTestEnv = api.env('test');
const isWebpackDevServer = process.env.WEBPACK_DEV_SERVER;
if (!validEnv.includes(currentEnv)) { if (!validEnv.includes(currentEnv)) {
throw new Error( throw new Error(
@ -16,39 +15,20 @@ module.exports = function (api) {
); );
} }
return { const defaultConfigFunc = require('shakapacker/package/babel/preset.js');
const resultConfig = defaultConfigFunc(api);
const changesOnDefault = {
presets: [ presets: [
isTestEnv && [
'@babel/preset-env',
{
targets: {
node: 'current'
},
modules: 'commonjs'
},
'@babel/preset-react'
],
(isProductionEnv || isDevelopmentEnv) && [
'@babel/preset-env',
{
forceAllTransforms: true,
useBuiltIns: 'entry',
corejs: 3,
modules: false,
exclude: ['transform-typeof-symbol']
}
],
[ [
'@babel/preset-react', '@babel/preset-react',
{ {
development: isDevelopmentEnv || isTestEnv, development: isDevelopmentEnv || isTestEnv,
useBuiltIns: true useBuiltIns: true
} }
], ]
['@babel/preset-typescript', { allExtensions: true, isTSX: true }]
].filter(Boolean), ].filter(Boolean),
plugins: [ plugins: [
isWebpackDevServer && 'react-refresh/babel',
'babel-plugin-macros', 'babel-plugin-macros',
'@babel/plugin-syntax-dynamic-import', '@babel/plugin-syntax-dynamic-import',
isTestEnv && 'babel-plugin-dynamic-import-node', isTestEnv && 'babel-plugin-dynamic-import-node',
@ -56,7 +36,7 @@ module.exports = function (api) {
[ [
'@babel/plugin-proposal-class-properties', '@babel/plugin-proposal-class-properties',
{ {
loose: false loose: true
} }
], ],
[ [
@ -65,26 +45,28 @@ module.exports = function (api) {
useBuiltIns: true useBuiltIns: true
} }
], ],
[
'@babel/plugin-transform-runtime',
{
helpers: false,
regenerator: true,
corejs: false
}
],
[ [
'@babel/plugin-transform-regenerator', '@babel/plugin-transform-regenerator',
{ {
async: false async: false
} }
], ],
isProductionEnv && [ isProductionEnv && ['babel-plugin-transform-react-remove-prop-types',
'babel-plugin-transform-react-remove-prop-types',
{ {
removeImport: true removeImport: true
} }
],
process.env.WEBPACK_SERVE && [
'react-refresh/babel',
{
exclude: 'node_modules/**'
}
] ]
].filter(Boolean) ].filter(Boolean)
}; };
resultConfig.presets = [...resultConfig.presets, ...changesOnDefault.presets];
resultConfig.plugins = [...resultConfig.plugins, ...changesOnDefault.plugins];
return resultConfig;
}; };

15
bin/webpacker Executable file
View File

@ -0,0 +1,15 @@
#!/usr/bin/env ruby
require "pathname"
require "bundler/setup"
require "webpacker"
require "webpacker/webpack_runner"
ENV["RAILS_ENV"] ||= "development"
ENV["NODE_ENV"] ||= ENV["RAILS_ENV"]
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", Pathname.new(__FILE__).realpath)
APP_ROOT = File.expand_path("..", __dir__)
Dir.chdir(APP_ROOT) do
Webpacker::WebpackRunner.run(ARGV)
end

18
bin/webpacker-dev-server Executable file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env ruby
ENV["RAILS_ENV"] ||= "development"
ENV["NODE_ENV"] ||= ENV["RAILS_ENV"]
require "pathname"
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
Pathname.new(__FILE__).realpath)
require "bundler/setup"
require "webpacker"
require "webpacker/dev_server_runner"
APP_ROOT = File.expand_path("..", __dir__)
Dir.chdir(APP_ROOT) do
Webpacker::DevServerRunner.run(ARGV)
end

View File

@ -1,9 +1,16 @@
#!/usr/bin/env ruby #!/usr/bin/env ruby
APP_ROOT = File.expand_path('..', __dir__)
APP_ROOT = File.expand_path("..", __dir__)
Dir.chdir(APP_ROOT) do Dir.chdir(APP_ROOT) do
begin yarn = ENV["PATH"].split(File::PATH_SEPARATOR).
exec "yarnpkg", *ARGV select { |dir| File.expand_path(dir) != __dir__ }.
rescue Errno::ENOENT product(["yarn", "yarnpkg", "yarn.cmd", "yarn.ps1"]).
map { |dir, file| File.expand_path(file, dir) }.
find { |file| File.executable?(file) }
if yarn
exec yarn, *ARGV
else
$stderr.puts "Yarn executable was not detected in the system." $stderr.puts "Yarn executable was not detected in the system."
$stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install" $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install"
exit 1 exit 1

View File

@ -1,10 +1,14 @@
# frozen_string_literal: true
# Be sure to restart your server when you modify this file. # Be sure to restart your server when you modify this file.
# Define an application-wide content security policy # Define an application-wide content security policy
# For further information see the following documentation # For further information see the following documentation
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
# Rails.application.config.content_security_policy do |policy| Rails.application.config.content_security_policy do |policy| # # If you are using webpack-dev-server then specify webpack-dev-server host
policy.connect_src :self, :https, 'http://localhost:3035', 'ws://localhost:3035' if Rails.env.development?
# policy.default_src :self, :https # policy.default_src :self, :https
# policy.font_src :self, :https, :data # policy.font_src :self, :https, :data
# policy.img_src :self, :https, :data # policy.img_src :self, :https, :data
@ -14,7 +18,7 @@
# # Specify URI for violation reports # # Specify URI for violation reports
# # policy.report_uri "/csp-violation-report-endpoint" # # policy.report_uri "/csp-violation-report-endpoint"
# end end
# If you are using UJS then enable automatic nonce generation # If you are using UJS then enable automatic nonce generation
# Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } # Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) }

View File

@ -1,3 +1,5 @@
Openlab.configure do |config| Openlab.configure do |config|
config.base_uri = Rails.application.secrets.openlab_base_uri unless Rails.env.production? config.base_uri = Rails.application.secrets.openlab_base_uri if Rails.application.secrets.openlab_base_uri
config.httparty_verify = Rails.application.secrets.openlab_ssl_verify
config.httparty_verify_peer = Rails.application.secrets.openlab_ssl_verify_peer
end end

View File

@ -1,25 +1,42 @@
# frozen_string_literal: true # frozen_string_literal: true
require 'sidekiq'
require 'sidekiq-scheduler'
redis_host = ENV['REDIS_HOST'] || 'localhost' redis_host = ENV['REDIS_HOST'] || 'localhost'
redis_url = "redis://#{redis_host}:6379" redis_url = "redis://#{redis_host}:6379"
Sidekiq.configure_server do |config| Sidekiq.configure_server do |config|
config.redis = { url: redis_url } config.redis = { url: redis_url }
# load sidekiq-cron schedule config config.client_middleware do |chain|
schedule_file = 'config/schedule.yml' chain.add SidekiqUniqueJobs::Middleware::Client
end
config.server_middleware do |chain|
chain.add SidekiqUniqueJobs::Middleware::Server
end
SidekiqUniqueJobs::Server.configure(config)
config.on(:startup) do
# load sidekiq-scheduler schedule config
schedule_file = 'config/schedule.yml'
if File.exist?(schedule_file) if File.exist?(schedule_file)
rendered_schedule_file = ERB.new(File.read(schedule_file)).result rendered_schedule_file = ERB.new(File.read(schedule_file)).result
Sidekiq::Cron::Job.load_from_hash YAML.safe_load(rendered_schedule_file) Sidekiq.schedule = YAML.safe_load(rendered_schedule_file)
SidekiqScheduler::Scheduler.instance.reload_schedule!
end
end end
end end
Sidekiq.configure_client do |config| Sidekiq.configure_client do |config|
config.redis = { url: redis_url } config.redis = { url: redis_url }
end
Sidekiq::Extensions.enable_delay! config.client_middleware do |chain|
chain.add SidekiqUniqueJobs::Middleware::Client
end
end
# Quieting logging in the test environment # Quieting logging in the test environment
if Rails.env.test? if Rails.env.test?

View File

@ -78,8 +78,8 @@ de:
slots_not_deleted: "Von {TOTAL} Slots {COUNT, plural, one {} =1{wurde einer wurde nicht gelöscht} other{wurden {COUNT} nicht gelöscht}}. Möglicherweise {COUNT, plural, =1{ist er} other{sind sie}} bereits reserviert." slots_not_deleted: "Von {TOTAL} Slots {COUNT, plural, one {} =1{wurde einer wurde nicht gelöscht} other{wurden {COUNT} nicht gelöscht}}. Möglicherweise {COUNT, plural, =1{ist er} other{sind sie}} bereits reserviert."
you_should_select_at_least_a_machine: "Sie sollten mindestens eine Maschine auf diesem Slot auswählen." you_should_select_at_least_a_machine: "Sie sollten mindestens eine Maschine auf diesem Slot auswählen."
inconsistent_times: "Fehler: das Ende der Verfügbarkeit liegt vor dem Beginn." inconsistent_times: "Fehler: das Ende der Verfügbarkeit liegt vor dem Beginn."
min_one_slot: "The availability must be split in one slot at least." min_one_slot: "Die Verfügbarkeit muss auf mindestens einen Slot aufgeteilt werden."
min_slot_duration: "You must specify a valid duration for the slots." min_slot_duration: "Sie müssen eine gültige Dauer für die Slots angeben."
export_is_running_you_ll_be_notified_when_its_ready: "Export wird ausgeführt. Sie werden nach Fertigstellung benachrichtigt." export_is_running_you_ll_be_notified_when_its_ready: "Export wird ausgeführt. Sie werden nach Fertigstellung benachrichtigt."
actions: "Aktionen" actions: "Aktionen"
block_reservations: "Reservierungen blockieren" block_reservations: "Reservierungen blockieren"
@ -98,8 +98,8 @@ de:
delete_this_slot: "Nur diesen Slot" delete_this_slot: "Nur diesen Slot"
delete_this_and_next: "Diesen Slot und die folgenden" delete_this_and_next: "Diesen Slot und die folgenden"
delete_all: "Alle Slots" delete_all: "Alle Slots"
event_in_the_past: "Create a slot in the past" event_in_the_past: "Slot in der Vergangenheit erstellen"
confirm_create_event_in_the_past: "You are about to create a slot in the past. Are you sure you want to do this? Members will not be able to book this slot." confirm_create_event_in_the_past: "Sie erstellen einen Slot in der Vergangenheit. Sind Sie sicher? Mitglieder werden diesen Slot nicht buchen können."
edit_event: "Veranstaltung bearbeiten" edit_event: "Veranstaltung bearbeiten"
view_reservations: "Reservierungen anzeigen" view_reservations: "Reservierungen anzeigen"
legend: "Legende" legend: "Legende"
@ -370,70 +370,70 @@ de:
status_disabled: "Deaktiviert" status_disabled: "Deaktiviert"
status_all: "Alle" status_all: "Alle"
spaces_pricing: spaces_pricing:
prices_match_space_hours_rates_html: "The prices below match one hour of space reservation, <strong>without subscription</strong>." prices_match_space_hours_rates_html: "Die unten aufgeführten Preise entsprechen einer Stunde Raumbelegung <strong>ohne Abonnement</strong>."
prices_calculated_on_hourly_rate_html: "All the prices will be automatically calculated based on the hourly rate defined here.<br/><em>For example</em>, if you define an hourly rate at {RATE}: a slot of {DURATION} minutes, will be charged <strong>{PRICE}</strong>." prices_calculated_on_hourly_rate_html: "Alle Preise werden automatisch nach dem hier definierten Stundensatz berechnet.<br/><em>Zum Beispiel</em> wird bei einem veranschlagten Stundensatz von {RATE} ein Slot von {DURATION} Minuten zum Preis von <strong>{PRICE}</strong> berechnet."
you_can_override: "You can override this duration for each availability you create in the agenda. The price will then be adjusted accordingly." you_can_override: "Sie können diese Dauer für jede Verfügbarkeit überschreiben, die Sie in der Agenda erstellen. Der Preis wird dann entsprechend angepasst."
extended_prices: "Moreover, you can define extended prices which will apply in priority over the hourly rate below. Extended prices allow you, for example, to set a favorable price for a booking of several hours." extended_prices: "Darüber hinaus können Sie erweiterte Preise festlegen, die vorrangig zum unten stehenden Stundensatz gelten. Mit erweiterten Preisen können Sie zum Beispiel einen günstigen Preis für eine Buchung über mehrere Stunden festlegen."
spaces: "Spaces" spaces: "Räume"
price_updated: "Price successfully updated" price_updated: "Preis erfolgreich aktualisiert"
machines_pricing: machines_pricing:
prices_match_machine_hours_rates_html: "Die unten aufgeführten Preise entsprechen einer Stunde Maschinengebrauch, <strong>ohne Abonnement</strong>." prices_match_machine_hours_rates_html: "Die unten aufgeführten Preise entsprechen einer Stunde Maschinengebrauch, <strong>ohne Abonnement</strong>."
prices_calculated_on_hourly_rate_html: "Alle Preise werden automatisch nach dem hier definierten Stundensatz berechnet.<br/><em>Zum Beispiel</em> wird bei einem veranschlagten Stundensatz von {RATE} ein Slot von {DURATION} Minuten, zum Preis von <strong>{PRICE}</strong> berechnet." prices_calculated_on_hourly_rate_html: "Alle Preise werden automatisch nach dem hier definierten Stundensatz berechnet.<br/><em>Zum Beispiel</em> wird bei einem veranschlagten Stundensatz von {RATE} ein Slot von {DURATION} Minuten, zum Preis von <strong>{PRICE}</strong> berechnet."
you_can_override: "Sie können diese Dauer für jede Verfügbarkeit überschreiben, die Sie in der Agenda erstellen. Der Preis wird dann entsprechend angepasst." you_can_override: "Sie können diese Dauer für jede Verfügbarkeit überschreiben, die Sie in der Agenda erstellen. Der Preis wird dann entsprechend angepasst."
machines: "Maschinen" machines: "Maschinen"
price_updated: "Price successfully updated" price_updated: "Preis erfolgreich aktualisiert"
configure_packs_button: configure_packs_button:
packs: "Prepaid packs" packs: "Vorausbezahlte Pakete"
no_packs: "No packs for now" no_packs: "Momentan keine Pakete"
pack_DURATION: "{DURATION} hours" pack_DURATION: "{DURATION} Stunden"
configure_extended_prices_button: configure_extended_prices_button:
extended_prices: "Extended prices" extended_prices: "Erweiterter Preis"
no_extended_prices: "No extended price for now" no_extended_prices: "Momentan kein erweiterter Preis"
extended_price_DURATION: "{DURATION} hours" extended_price_DURATION: "{DURATION} Stunden"
extended_price_form: extended_price_form:
duration: "Duration (hours)" duration: "Dauer (Stunden)"
amount: "Price" amount: "Preis"
pack_form: pack_form:
hours: "Hours" hours: "Stunden"
amount: "Price" amount: "Preis"
disabled: "Disabled" disabled: "Deaktiviert"
validity_count: "Maximum validity" validity_count: "Maximale Gültigkeit"
select_interval: "Interval..." select_interval: "Zeitraum..."
intervals: intervals:
day: "{COUNT, plural, one{Day} other{Days}}" day: "{COUNT, plural, one {Tag} other {Tage}}"
week: "{COUNT, plural, one{Week} other{Weeks}}" week: "{COUNT, plural, one{Woche} other{Wochen}}"
month: "{COUNT, plural, one{Month} other{Months}}" month: "{COUNT, plural, one{Monat} other{Monate}}"
year: "{COUNT, plural, one{Year} other{Years}}" year: "{COUNT, plural, one {Jahr} other {Jahre}}"
create_pack: create_pack:
new_pack: "New prepaid pack" new_pack: "Neues vorausbezahltes Paket"
new_pack_info: "A prepaid pack allows users to buy {TYPE, select, Machine{machine} Space{space} other{}} hours before booking any slots. These packs can provide discounts on volumes purchases." new_pack_info: "Ein vorausbezahltes Paket erlaubt den Kauf von {TYPE, select, Machine{Maschinen-} Space{Raum-} other{}}Stunden vor der Buchung eines Slots. Diese Pakete können Rabatte auf Volumenkäufe bieten."
create_pack: "Create this pack" create_pack: "Dieses Paket erstellen"
pack_successfully_created: "The new prepaid pack was successfully created." pack_successfully_created: "Das neue Vorausbezahlungs-Paket wurde erfolgreich erstellt."
delete_pack: delete_pack:
pack_deleted: "The prepaid pack was successfully deleted." pack_deleted: "Das Vorausbezahlungs-Paket wurde erfolgreich gelöscht."
unable_to_delete: "Unable to delete the prepaid pack: " unable_to_delete: "Paket konnte nicht gelöscht werden: "
delete_pack: "Delete the prepaid pack" delete_pack: "Vorausbezahlungs-Paket löschen"
confirm_delete: "Delete" confirm_delete: "Löschen"
delete_confirmation: "Are you sure you want to delete this prepaid pack? This won't be possible if the pack was already bought by users." delete_confirmation: "Sind Sie sicher, dass Sie dieses Paket löschen möchten? Dies ist nicht möglich, wenn das Paket bereits von Benutzern gekauft wurde."
edit_pack: edit_pack:
edit_pack: "Edit the pack" edit_pack: "Das Paket bearbeiten"
confirm_changes: "Confirm changes" confirm_changes: "Änderungen bestätigen"
pack_successfully_updated: "The prepaid pack was successfully updated." pack_successfully_updated: "Das Vorausbezahlungs-Paket wurde erfolgreich aktualisiert."
create_extended_price: create_extended_price:
new_extended_price: "New extended price" new_extended_price: "Neuer erweiterter Preis"
new_extended_price_info: "Extended prices allows you to define prices based on custom durations, instead of the default hourly rates." new_extended_price_info: "Erweiterte Preise erlauben Ihnen die Festlegung von Preisen basierend auf benutzerdefinierten Zeitdauern anstelle der Standard-Stundensätze."
create_extended_price: "Create extended price" create_extended_price: "Erweiterten Preis erstellen"
extended_price_successfully_created: "The new extended price was successfully created." extended_price_successfully_created: "Der neue erweiterte Preis wurde erfolgreich erstellt."
delete_extended_price: delete_extended_price:
extended_price_deleted: "The extended price was successfully deleted." extended_price_deleted: "Der erweiterte Preis wurde erfolgreich gelöscht."
unable_to_delete: "Unable to delete the extended price: " unable_to_delete: "Der erweiterte Preis konnte nicht gelöscht werden: "
delete_extended_price: "Delete the extended price" delete_extended_price: "Erweiterten Preis löschen"
confirm_delete: "Delete" confirm_delete: "Löschen"
delete_confirmation: "Are you sure you want to delete this extended price?" delete_confirmation: "Sind Sie sicher, dass Sie diesen erweiterten Preis löschen möchten?"
edit_extended_price: edit_extended_price:
edit_extended_price: "Edit the extended price" edit_extended_price: "Erweiterten Preis bearbeiten"
confirm_changes: "Confirm changes" confirm_changes: "Änderungen bestätigen"
extended_price_successfully_updated: "The extended price was successfully updated." extended_price_successfully_updated: "Der erweiterte Preis wurde erfolgreich aktualisiert."
#ajouter un code promotionnel #ajouter un code promotionnel
coupons_new: coupons_new:
add_a_coupon: "Gutschein hinzufügen" add_a_coupon: "Gutschein hinzufügen"
@ -496,7 +496,7 @@ de:
details: "Details" details: "Details"
amount: "Betrag" amount: "Betrag"
machine_booking-3D_printer: "Maschinen-Buchung - 3D-Drucker" machine_booking-3D_printer: "Maschinen-Buchung - 3D-Drucker"
training_booking-3D_print: "Training booking - initiation to 3d printing" training_booking-3D_print: "Schulungsbuchung - Einstieg ins 3D-Drucken"
total_amount: "Gesamtbetrag" total_amount: "Gesamtbetrag"
total_including_all_taxes: "Gesamtpreis inkl. Steuern" total_including_all_taxes: "Gesamtpreis inkl. Steuern"
VAT_disabled: "MwSt. deaktiviert" VAT_disabled: "MwSt. deaktiviert"
@ -553,15 +553,15 @@ de:
enable_VAT: "MwSt. aktivieren" enable_VAT: "MwSt. aktivieren"
VAT_rate: "MwSt.-Satz" VAT_rate: "MwSt.-Satz"
VAT_history: "MwSt.-Sätze Historie" VAT_history: "MwSt.-Sätze Historie"
VAT_notice: "This parameter configures the general case of the VAT rate and applies to everything sold by the Fablab. It is possible to override this parameter by setting a specific VAT rate for each object." VAT_notice: "Dieser Parameter legt den allgemeinen Fall des MwSt.-Satzes fest und gilt für alles, was der Fablab verkauft. Der Parameter kann überschreiben werden, indem ein spezieller Mehrwertsteuersatz für jedes Objekt festgelegt wird."
edit_multi_VAT_button: "More options" edit_multi_VAT_button: "Weitere Optionen"
multiVAT: "Advanced VAT" multiVAT: "Erweiterte MwSt."
multi_VAT_notice: "<strong>Please note</strong>: The current general rate is {RATE}%. Here you can define different VAT rates for each category.</br></br>For example, you can override this value, only for machine reservations, by filling in the corresponding field below. If no value is filled in, the general rate will apply." multi_VAT_notice: "<strong>Bitte beachten Sie</strong>: Der aktuelle allgemeine MwSt.-Satz beträgt {RATE}%. Hier können Sie unterschiedliche Mehrwertsteuersätze für jede Kategorie festlegen.</br></br>Zum Beispiel können Sie diesen Wert für Maschinenreservierungen überschreiben, indem Sie das entsprechende Feld unten ausfüllen. Wird kein Wert ausgefüllt, gilt der allgemeine Satz."
VAT_rate_machine: "Machine reservation" VAT_rate_machine: "Maschinenreservierung"
VAT_rate_space: "Space reservation" VAT_rate_space: "Raumreservierung"
VAT_rate_training: "Training reservation" VAT_rate_training: "Schulungsreservierung"
VAT_rate_event: "Event reservation" VAT_rate_event: "Veranstaltungsreservierung"
VAT_rate_subscription: "Subscription" VAT_rate_subscription: "Abonnement"
changed_at: "Geändert am" changed_at: "Geändert am"
changed_by: "Von" changed_by: "Von"
deleted_user: "Gelöschter Nutzer" deleted_user: "Gelöschter Nutzer"
@ -603,9 +603,9 @@ de:
logo_successfully_saved: "Logo erfolgreich gespeichert." logo_successfully_saved: "Logo erfolgreich gespeichert."
an_error_occurred_while_saving_the_logo: "Beim Speichern des Logos ist ein Fehler aufgetreten." an_error_occurred_while_saving_the_logo: "Beim Speichern des Logos ist ein Fehler aufgetreten."
filename: "Dateiname" filename: "Dateiname"
schedule_filename: "Schedule file name" schedule_filename: "Dateiname des Zeitplans"
prefix_info: "Die Rechnungen werden als PDF-Dateien generiert, die mit dem folgenden Präfix benannt sind." prefix_info: "Die Rechnungen werden als PDF-Dateien generiert, die mit dem folgenden Präfix benannt sind."
schedule_prefix_info: "The payment schedules will be generated as PDF files, named with the following prefix." schedule_prefix_info: "Die Zahlungspläne werden als PDF-Dateien mit dem folgenden Prefix generiert."
prefix: "Präfix" prefix: "Präfix"
prefix_successfully_saved: "Dateipräfix erfolgreich gespeichert" prefix_successfully_saved: "Dateipräfix erfolgreich gespeichert"
an_error_occurred_while_saving_the_prefix: "Beim Speichern des Dateipräfix ist ein Fehler aufgetreten" an_error_occurred_while_saving_the_prefix: "Beim Speichern des Dateipräfix ist ein Fehler aufgetreten"
@ -673,16 +673,20 @@ de:
general_space_code: "Abrechnungscode für alle Räume" general_space_code: "Abrechnungscode für alle Räume"
accounting_Space_label: "Raumbezeichnung" accounting_Space_label: "Raumbezeichnung"
general_space_label: "Abrechnungs-Label für alle Räume" general_space_label: "Abrechnungs-Label für alle Räume"
accounting_Error_code: "Errors code" accounting_Pack_code: "Prepaid-pack code"
general_error_code: "Accounting code for erroneous invoices" general_pack_code: "Accounting code for prepaid-packs"
accounting_Error_label: "Errors label" accounting_Pack_label: "Prepaid-pack label"
general_error_label: "Account label for erroneous invoices" general_pack_label: "Account label for prepaid-packs"
accounting_Error_code: "Fehlercode"
general_error_code: "Rechnungscode für fehlerhafte Rechnungen"
accounting_Error_label: "Fehlerbezeichnung"
general_error_label: "Kontobezeichnung für fehlerhafte Rechnungen"
codes_customization_success: "Anpassung der Abrechnungscodes erfolgreich gespeichert." codes_customization_success: "Anpassung der Abrechnungscodes erfolgreich gespeichert."
unexpected_error_occurred: "Beim Speichern der Codes ist ein unerwarteter Fehler aufgetreten. Bitte versuchen Sie es später erneut." unexpected_error_occurred: "Beim Speichern der Codes ist ein unerwarteter Fehler aufgetreten. Bitte versuchen Sie es später erneut."
export_accounting_data: "Abrechnungsdaten exportieren" export_accounting_data: "Abrechnungsdaten exportieren"
export_what: "What do you want to export?" export_what: "Was möchten Sie exportieren?"
export_VAT: "Export the collected VAT" export_VAT: "Die gesammelte MwSt. exportieren"
export_to_ACD: "Export all data to the accounting software ACD" export_to_ACD: "Alle Daten in die Buchhaltungssoftware ACD exportieren"
export_is_running: "Export wird ausgeführt. Sie werden nach Fertigstellung benachrichtigt." export_is_running: "Export wird ausgeführt. Sie werden nach Fertigstellung benachrichtigt."
export_form_date: "Exportieren ab" export_form_date: "Exportieren ab"
export_to_date: "Exportieren bis" export_to_date: "Exportieren bis"
@ -706,10 +710,10 @@ de:
debit_euro: "Soll in Euro" debit_euro: "Soll in Euro"
credit_euro: "Guthaben in Euro" credit_euro: "Guthaben in Euro"
lettering: "Beschriftung" lettering: "Beschriftung"
start_date: "Start date" start_date: "Startdatum"
end_date: "End date" end_date: "Enddatum"
vat_rate: "VAT rate" vat_rate: "MwSt.-Satz"
amount: "Total amount" amount: "Gesamtbetrag"
payment: payment:
payment_settings: "Bezahlungseinstellungen" payment_settings: "Bezahlungseinstellungen"
online_payment: "Online-Bezahlung" online_payment: "Online-Bezahlung"
@ -722,53 +726,53 @@ de:
error_check_keys: "Fehler: Bitte überprüfen Sie Ihre Stripe-Schlüssel." error_check_keys: "Fehler: Bitte überprüfen Sie Ihre Stripe-Schlüssel."
stripe_keys_saved: "Stripe-Schlüssel erfolgreich gespeichert." stripe_keys_saved: "Stripe-Schlüssel erfolgreich gespeichert."
error_saving_stripe_keys: "Die Stripe-Schlüssel konnten nicht gespeichert werden. Bitte versuchen Sie es später erneut." error_saving_stripe_keys: "Die Stripe-Schlüssel konnten nicht gespeichert werden. Bitte versuchen Sie es später erneut."
payzen_keys_info_html: "<p>To be able to collect online payments, you must configure the <a href='https://payzen.eu' target='_blank'>PayZen</a> identifiers and keys.</p><p>Retrieve them from <a href='https://secure.payzen.eu/vads-merchant/' target='_blank'>your merchant back office</a>.</p>" payzen_keys_info_html: "<p>Um Online-Zahlungen zu erhalten, müssen Sie die <a href='https://payzen.eu' target='_blank'>PayZen</a> Identifikatoren und Schlüssel konfigurieren.</p><p>Holen Sie sie aus <a href='https://secure.payzen.eu/vads-merchant/' target='_blank'>Ihrem Händler-Backend</a>.</p>"
client_keys: "Client key" client_keys: "Kundenschlüssel"
api_keys: "API keys" api_keys: "API-Schlüssel"
edit_keys: "Schlüssel bearbeiten" edit_keys: "Schlüssel bearbeiten"
currency: "Währung" currency: "Währung"
currency_info_html: "Bitte geben Sie unten die Währung an, die für Online-Bezahlung verwendet wird. Sie sollten einen ISO-Code mit drei Buchstaben aus der Liste <a href='https://stripe.com/docs/currencies' target='_blank'>Stripe unterstützter Währungen eingeben</a>." currency_info_html: "Bitte geben Sie unten die Währung an, die für Online-Bezahlung verwendet wird. Sie sollten einen ISO-Code mit drei Buchstaben aus der Liste <a href='https://stripe.com/docs/currencies' target='_blank'>Stripe unterstützter Währungen eingeben</a>."
currency_alert_html: "<strong>Warnung</strong>: Die Währung kann nicht mehr geändert werden, nachdem die erste Online-Zahlung eingegangen ist. Bitte nehmen Sie diese Einstellung sorgfältig vor, bevor Sie Fab-Manager für Mitglieder öffnen." currency_alert_html: "<strong>Warnung</strong>: Die Währung kann nicht mehr geändert werden, nachdem die erste Online-Zahlung eingegangen ist. Bitte nehmen Sie diese Einstellung sorgfältig vor, bevor Sie Fab-Manager für Mitglieder öffnen."
stripe_currency: "Stripe-Währung" stripe_currency: "Stripe-Währung"
gateway_configuration_error: "An error occurred while configuring the payment gateway: " gateway_configuration_error: "Fehler beim Konfigurieren des Zahlungs-Gateways: "
payzen: payzen:
payzen_keys: "PayZen keys" payzen_keys: "PayZen-Schlüssel"
payzen_username: "Benutzername" payzen_username: "Benutzername"
payzen_password: "Passwort" payzen_password: "Passwort"
payzen_endpoint: "REST API server name" payzen_endpoint: "REST API Server Name"
payzen_hmac: "HMAC-SHA-256 key" payzen_hmac: "HMAC-SHA-256 Schlüssel"
payzen_public_key: "Client public key" payzen_public_key: "Öffentlicher Schlüssel des Kunden"
currency: "Währung" currency: "Währung"
payzen_currency: "PayZen Währung" payzen_currency: "PayZen Währung"
currency_info_html: "Bitte geben Sie unten die Währung an, die für Online-Bezahlung verwendet wird. Sie sollten einen ISO-Code mit drei Buchstaben aus der Liste <a href='https://payzen.io/de-DE/payment-file/ips/list-of-supported-currencies.html' target='_blank'>PayZen unterstützter Währungen eingeben</a>." currency_info_html: "Bitte geben Sie unten die Währung an, die für Online-Bezahlung verwendet wird. Sie sollten einen ISO-Code mit drei Buchstaben aus der Liste <a href='https://payzen.io/de-DE/payment-file/ips/list-of-supported-currencies.html' target='_blank'>PayZen unterstützter Währungen eingeben</a>."
save: "Speichern" save: "Speichern"
currency_error: "The inputted value is not a valid currency" currency_error: "Der eingegebene Wert ist keine gültige Währung"
error_while_saving: "An error occurred while saving the currency: " error_while_saving: "Beim Speichern der Währung ist ein Fehler aufgetreten: "
currency_updated: "The PayZen currency was successfully updated to {CURRENCY}." currency_updated: "Die PayZen-Währung wurde erfolgreich auf {CURRENCY} aktualisiert."
#select a payment gateway #select a payment gateway
gateway_modal: gateway_modal:
select_gateway_title: "Select a payment gateway" select_gateway_title: "Zahlungs-Gateway auswählen"
gateway_info: "To securely collect and process payments online, Fab-manager needs to use an third-party service authorized by the financial institutions, called a payment gateway." gateway_info: "Um Zahlungen sicher online zu sammeln und zu verarbeiten, muss Fab-Manager einen von Finanzinstituten autorisierten Drittanbieter nutzen, der als Zahlungsgateway bezeichnet wird."
select_gateway: "Please select an available gateway" select_gateway: "Bitte wählen Sie ein verfügbares Gateway"
stripe: "Stripe" stripe: "Stripe"
payzen: "PayZen" payzen: "PayZen"
confirm_button: "Validate the gateway" confirm_button: "Gateway überprüfen"
payment_schedules: payment_schedules:
filter_schedules: "Pläne filtern" filter_schedules: "Pläne filtern"
no_payment_schedules: "Keine Zahlungspläne zum Anzeigen" no_payment_schedules: "Keine Zahlungspläne zum Anzeigen"
load_more: "Mehr laden" load_more: "Mehr laden"
card_updated_success: "The user's card was successfully updated" card_updated_success: "Die Karte des Nutzers wurde erfolgreich aktualisiert"
document_filters: document_filters:
reference: "Referenz" reference: "Referenz"
customer: "Kunde" customer: "Kunde"
date: "Datum" date: "Datum"
update_payment_mean_modal: update_payment_mean_modal:
title: "Update the payment mean" title: "Zahlungsmittel aktualisieren"
update_info: "Please specify below the new payment mean for this payment schedule to continue." update_info: "Bitte geben Sie unten das neue Zahlungsmittel an, damit der Zahlungszeitplan fortgesetzt werden kann."
select_payment_mean: "Select a new payment mean" select_payment_mean: "Neues Zahlungsmittel auswählen"
method_Transfer: "By bank transfer" method_Transfer: "Per Banküberweisung"
method_Check: "By check" method_Check: "Per Scheck"
confirm_button: "Update" confirm_button: "Aktualisieren"
#management of users, labels, groups, and so on #management of users, labels, groups, and so on
members: members:
users_management: "Benutzer-Verwaltung" users_management: "Benutzer-Verwaltung"
@ -918,7 +922,7 @@ de:
expires_at: "Läuft ab am:" expires_at: "Läuft ab am:"
price_: "Preis:" price_: "Preis:"
offer_free_days: "Kostenlose Tage anbieten" offer_free_days: "Kostenlose Tage anbieten"
renew_subscription: "Renew the subscription" renew_subscription: "Abonnement erneuern"
user_has_no_current_subscription: "Benutzer hat kein aktuelles Abonnement." user_has_no_current_subscription: "Benutzer hat kein aktuelles Abonnement."
subscribe_to_a_plan: "Plan abonnieren" subscribe_to_a_plan: "Plan abonnieren"
trainings: "Schulungen" trainings: "Schulungen"
@ -944,7 +948,7 @@ de:
a_problem_occurred_while_saving_the_date: "Beim Speichern des Datums ist ein Problem aufgetreten." a_problem_occurred_while_saving_the_date: "Beim Speichern des Datums ist ein Problem aufgetreten."
new_subscription: "Neues Abonnement" new_subscription: "Neues Abonnement"
you_are_about_to_purchase_a_subscription_to_NAME: "Sie sind dabei, ein Abonnement für {NAME} zu kaufen." you_are_about_to_purchase_a_subscription_to_NAME: "Sie sind dabei, ein Abonnement für {NAME} zu kaufen."
with_schedule: "Subscribe with a monthly payment schedule" with_schedule: "Mit einem monatlichen Zahlungsplan abonnieren"
subscription_successfully_purchased: "Abonnement erfolgreich gekauft." subscription_successfully_purchased: "Abonnement erfolgreich gekauft."
a_problem_occurred_while_taking_the_subscription: "Bei der Übernahme des Abonnements ist ein Problem aufgetreten" a_problem_occurred_while_taking_the_subscription: "Bei der Übernahme des Abonnements ist ein Problem aufgetreten"
wallet: "Guthabenkonto" wallet: "Guthabenkonto"
@ -953,37 +957,37 @@ de:
cannot_extend_own_subscription: "Sie können Ihr eigenes Abonnement nicht erweitern. Bitte fragen Sie einen anderen Manager oder einen Administrator." cannot_extend_own_subscription: "Sie können Ihr eigenes Abonnement nicht erweitern. Bitte fragen Sie einen anderen Manager oder einen Administrator."
#extend a subscription for free #extend a subscription for free
free_extend_modal: free_extend_modal:
extend_subscription: "Extend the subscription" extend_subscription: "Abonnement verlängern"
offer_free_days_infos: "You are about to extend the user's subscription by offering him free additional days." offer_free_days_infos: "Sie sind dabei, das Abonnement des Benutzers zu verlängern, indem Sie ihm zusätzliche Tage kostenlos anbieten."
credits_will_remain_unchanged: "The balance of free credits (training / machines / spaces) of the user will remain unchanged." credits_will_remain_unchanged: "Der Saldo der freien Gutschriften (Schulungen / Maschinen / Räume) des Nutzers bleibt unverändert."
current_expiration: "Current subscription will expire at:" current_expiration: "Aktuelles Abonnement läuft ab um:"
DATE_TIME: "{DATE} {TIME}" DATE_TIME: "{DATE} {TIME}"
new_expiration_date: "New expiration date:" new_expiration_date: "Neues Ablaufdatum:"
number_of_free_days: "Number of free days:" number_of_free_days: "Anzahl der freien Tage:"
extend: "Extend" extend: "Erweitern"
extend_success: "The subscription was successfully extended for free" extend_success: "Das Abonnement wurde erfolgreich kostenlos erweitert"
#renew a subscription #renew a subscription
renew_subscription_modal: renew_subscription_modal:
renew_subscription: "Renew the subscription" renew_subscription: "Abonnement erneuern"
renew_subscription_info: "You are about to renew the user's subscription by charging him again for his current subscription." renew_subscription_info: "Sie verlängern das Abonnement des Benutzers, indem Sie ihm sein aktuelles Abonnement erneut berechnen."
credits_will_be_reset: "The balance of free credits (training / machines / spaces) of the user will be reset, unused credits will be lost." credits_will_be_reset: "Der Saldo der freien Credits (Schulung / Maschinen / Räume) des Benutzers wird zurückgesetzt, nicht genutzte Credits gehen verloren."
current_expiration: "Current subscription will expire at:" current_expiration: "Aktuelles Abonnement läuft ab um:"
new_start: "The new subscription will start at:" new_start: "Das neue Abonnement beginnt am:"
new_expiration_date: "The new subscription will expire at:" new_expiration_date: "Das neue Abonnement läuft ab um:"
pay_in_one_go: "Pay in one go" pay_in_one_go: "In einem Schritt bezahlen"
renew: "Renew" renew: "Erneuern"
renew_success: "The subscription was successfully renewed" renew_success: "Das Abonnement wurde erfolgreich verlängert"
#take a new subscription #take a new subscription
subscribe_modal: subscribe_modal:
subscribe_USER: "Subscribe {USER}" subscribe_USER: "{USER} abonnieren"
subscribe: "Subscribe" subscribe: "Abonnieren"
select_plan: "Please select a plan" select_plan: "Bitte wählen Sie einen Plan"
pay_in_one_go: "Pay in one go" pay_in_one_go: "In einem Schritt bezahlen"
subscription_success: "" subscription_success: ""
#add a new administrator to the platform #add a new administrator to the platform
admins_new: admins_new:
add_an_administrator: "Administrator hinzufügen" add_an_administrator: "Administrator hinzufügen"
administrator_successfully_created_he_will_receive_his_connection_directives_by_email: "Administrator erfolgreich erstellt. {GENDER, select, female{Sie} other{Er}} erhält {GENDER, select, female{ihre} other{seine}} Verbindungsanweisungen per E-Mail." administrator_successfully_created_he_will_receive_his_connection_directives_by_email: "Administrator erfolgreich erstellt. Er erhält seine Verbindungsanweisungen per E-Mail."
failed_to_create_admin: "Administrator konnte nicht erstellt werden:" failed_to_create_admin: "Administrator konnte nicht erstellt werden:"
man: "Männlich" man: "Männlich"
woman: "Weiblich" woman: "Weiblich"
@ -1001,7 +1005,7 @@ de:
#add a new manager to the platform #add a new manager to the platform
manager_new: manager_new:
add_a_manager: "Manager hinzufügen" add_a_manager: "Manager hinzufügen"
manager_successfully_created: "Manager erfolgreich erstellt. {GENDER, select, female{Sie} other{Er}} erhält {GENDER, select, female{ihre} other{seine}} Verbindungsanweisungen per E-Mail." manager_successfully_created: "Manager erfolgreich erstellt. Er erhält seine Verbindungsanweisungen per E-Mail."
failed_to_create_manager: "Konnte den Manager nicht erstellen:" failed_to_create_manager: "Konnte den Manager nicht erstellen:"
man: "Männlich" man: "Männlich"
woman: "Weiblich" woman: "Weiblich"
@ -1032,7 +1036,7 @@ de:
oauth2_provider_successfully_added: "OAuth 2.0 Provider erfolgreich hinzugefügt." oauth2_provider_successfully_added: "OAuth 2.0 Provider erfolgreich hinzugefügt."
#edit an authentication provider (SSO) #edit an authentication provider (SSO)
authentication_edit: authentication_edit:
provider: "Provider:" provider: "Anbieter:"
it_is_required_to_set_the_matching_between_User.uid_and_the_API_to_add_this_provider: "Um diesen Provider hinzuzufügen, muss die Übereinstimmung zwischen User.uid und der API festgelegt werden." it_is_required_to_set_the_matching_between_User.uid_and_the_API_to_add_this_provider: "Um diesen Provider hinzuzufügen, muss die Übereinstimmung zwischen User.uid und der API festgelegt werden."
provider_successfully_updated: "Anbieter erfolgreich aktualisiert." provider_successfully_updated: "Anbieter erfolgreich aktualisiert."
an_error_occurred_unable_to_update_the_provider: "Ein Fehler ist aufgetreten: Der Anbieter konnte nicht aktualisiert werden." an_error_occurred_unable_to_update_the_provider: "Ein Fehler ist aufgetreten: Der Anbieter konnte nicht aktualisiert werden."
@ -1228,9 +1232,9 @@ de:
error_SETTING_locked: "Die Einstellung konnte nicht aktualisiert werden: {SETTING} ist gesperrt. Bitte kontaktieren Sie Ihren Systemadministrator." error_SETTING_locked: "Die Einstellung konnte nicht aktualisiert werden: {SETTING} ist gesperrt. Bitte kontaktieren Sie Ihren Systemadministrator."
an_error_occurred_saving_the_setting: "Beim Speichern der Einstellung ist ein Fehler aufgetreten. Bitte versuchen Sie es später erneut." an_error_occurred_saving_the_setting: "Beim Speichern der Einstellung ist ein Fehler aufgetreten. Bitte versuchen Sie es später erneut."
book_overlapping_slots_info: "Erlauben / Verhindern der Reservierung von überlappenden Slots" book_overlapping_slots_info: "Erlauben / Verhindern der Reservierung von überlappenden Slots"
allow_booking: "Allow booking" allow_booking: "Buchungen erlauben"
overlapping_categories: "Overlapping categories" overlapping_categories: "Überlappende Kategorien"
overlapping_categories_info: "Preventing booking on overlapping slots will be done by comparing the date and time of the following categories of reservations." overlapping_categories_info: "Die Buchung von überlappenden Zeitnischen wird durch einen Vergleich zwischen Datum und Uhrzeit der folgenden Buchungskategorien verhindert."
default_slot_duration: "Standarddauer für Slots" default_slot_duration: "Standarddauer für Slots"
duration_minutes: "Dauer (in Minuten)" duration_minutes: "Dauer (in Minuten)"
default_slot_duration_info: "Die Verfügbarkeit von Maschinen und Räumen ist in mehrere Slots dieser Dauer aufgeteilt. Dieser Wert kann je Verfügbarkeit überschrieben werden." default_slot_duration_info: "Die Verfügbarkeit von Maschinen und Räumen ist in mehrere Slots dieser Dauer aufgeteilt. Dieser Wert kann je Verfügbarkeit überschrieben werden."
@ -1243,10 +1247,10 @@ de:
plans_info_html: "<p>Abonnements bieten eine Möglichkeit, Ihre Preise zu segmentieren und Vorteile für reguläre Benutzer zu bieten.</p><p><strong>Warnung:</strong> Es wird nicht empfohlen, die Abonnements zu deaktivieren, wenn mindestens ein Abonnement auf dem System aktiv ist.</p>" plans_info_html: "<p>Abonnements bieten eine Möglichkeit, Ihre Preise zu segmentieren und Vorteile für reguläre Benutzer zu bieten.</p><p><strong>Warnung:</strong> Es wird nicht empfohlen, die Abonnements zu deaktivieren, wenn mindestens ein Abonnement auf dem System aktiv ist.</p>"
enable_plans: "Pläne aktivieren" enable_plans: "Pläne aktivieren"
plans_module: "Plan-Modul" plans_module: "Plan-Modul"
trainings: "Trainings" trainings: "Schulungen"
trainings_info_html: "<p>Trainings are fully integrated into the Fab-manger's agenda. If enabled, your members will be able to book and pay trainings.</p><p>Trainings provides a way to prevent members to book some machines, if they do have not taken the prerequisite course.</p>" trainings_info_html: "<p>Schulungen sind vollständig in die Agenda von Fab-Manger integriert. Wenn aktiviert, können Mitglieder Schulungen buchen und bezahlen.</p><p>Schulungen können Mitglieder daran hindern, Maschinen zu buchen, für die sie noch nicht den Grundkurs absolviert haben.</p>"
enable_trainings: "Enable the trainings" enable_trainings: "Schulungen aktivieren"
trainings_module: "trainings module" trainings_module: "Schulungs-Modul"
invoicing: "Rechnungsstellung" invoicing: "Rechnungsstellung"
invoicing_info_html: "<p>Sie können das Rechnungsmodul komplett deaktivieren.</p><p>Das ist nützlich, wenn Sie über Ihr eigenes Rechnungssystem verfügen und nicht wollen, dass Fab-Manager Rechnungen generiert und an Mitglieder sendet.</p><p><strong>Warnung:</strong> Auch wenn Sie das Rechnungsmodul deaktivieren, müssen Sie die Mehrwertsteuer konfigurieren, um Fehler in Rechnungslegung und Preisen zu vermeiden. Die Konfiguration erfolgt in der Sektion « Rechnungen > Einstellungen ».</p>" invoicing_info_html: "<p>Sie können das Rechnungsmodul komplett deaktivieren.</p><p>Das ist nützlich, wenn Sie über Ihr eigenes Rechnungssystem verfügen und nicht wollen, dass Fab-Manager Rechnungen generiert und an Mitglieder sendet.</p><p><strong>Warnung:</strong> Auch wenn Sie das Rechnungsmodul deaktivieren, müssen Sie die Mehrwertsteuer konfigurieren, um Fehler in Rechnungslegung und Preisen zu vermeiden. Die Konfiguration erfolgt in der Sektion « Rechnungen > Einstellungen ».</p>"
enable_invoicing: "Rechnungsstellung aktivieren" enable_invoicing: "Rechnungsstellung aktivieren"
@ -1256,7 +1260,7 @@ de:
phone_is_required: "Telefonummer erforderlich" phone_is_required: "Telefonummer erforderlich"
phone_required_info: "Sie können festlegen, ob die Telefonnummer erforderlich sein soll, um einen neuen Benutzer auf Fab-Manager zu registrieren." phone_required_info: "Sie können festlegen, ob die Telefonnummer erforderlich sein soll, um einen neuen Benutzer auf Fab-Manager zu registrieren."
address: "Adresse" address: "Adresse"
address_required_info_html: "You can define if the address should be required to register a new user on Fab-manager.<br/><strong>Please note</strong> that, depending on your country, the regulations may requires addresses for the invoices to be valid." address_required_info_html: "Sie können festlegen, ob eine Adresse für die Neuregistrierung eines Benutzers erforderlich sein soll.<br/><strong>Bitte beachten Sie</strong> dass in Abhängigkeit von Landesvorschriften Adressen für die Gültigkeit der Rechnungen erforderlich sein können."
address_is_required: "Adresse ist erforderlich" address_is_required: "Adresse ist erforderlich"
captcha: "Captcha" captcha: "Captcha"
captcha_info_html: "Sie können einen Schutz gegen Roboter einrichten, um zu verhindern, dass diese Accounts erstellen. Dieser Schutz verwendet Google reCAPTCHA. Melden Sie sich für <a href='http://www.google.com/recaptcha/admin' target='_blank'>ein API-Schlüsselpaar</a> an, um reCaptcha zu verwenden." captcha_info_html: "Sie können einen Schutz gegen Roboter einrichten, um zu verhindern, dass diese Accounts erstellen. Dieser Schutz verwendet Google reCAPTCHA. Melden Sie sich für <a href='http://www.google.com/recaptcha/admin' target='_blank'>ein API-Schlüsselpaar</a> an, um reCaptcha zu verwenden."
@ -1278,24 +1282,24 @@ de:
confirmation_required_info: "Optional können Sie die Bestätigung der E-Mail-Adresse für Benutzer obligatorisch machen, bevor Sie Zugriff auf Fab-Manager bekommen." confirmation_required_info: "Optional können Sie die Bestätigung der E-Mail-Adresse für Benutzer obligatorisch machen, bevor Sie Zugriff auf Fab-Manager bekommen."
confirmation_is_required: "Bestätigung erforderlich" confirmation_is_required: "Bestätigung erforderlich"
wallet_module: "Guthabenkonto-Modul" wallet_module: "Guthabenkonto-Modul"
public_agenda_module: "public agenda module" public_agenda_module: "öffentliches Agenda-Modul"
statistics_module: "Statistik-Modul" statistics_module: "Statistik-Modul"
upcoming_events_shown: "Anzeigelimit für anstehende Termine" upcoming_events_shown: "Anzeigelimit für anstehende Termine"
display_invite_to_renew_pack: "Display the invite to renew prepaid-packs" display_invite_to_renew_pack: "Einladung zur Erneuerung der vorausbezahlten Pakete anzeigen"
packs_threshold_info_html: "You can define under how many hours the user will be invited to buy a new prepaid-pack, if his stock of prepaid hours is under this threshold.<br/>You can set a <strong>number of hours</strong> (<em>eg. 5</em>) or a <strong>percentage</strong> of his current pack pack (<em>eg. 0.05 means 5%</em>)." packs_threshold_info_html: "Sie können festlegen, ab wievielen Reststunden der Benutzer auf den Kauf eines neuen Pakets an vorausbezahlten Stunden hingewiesen wird.<br/>Sie können eine <strong>Anzahl von Stunden</strong> (<em>z. B. 5</em>) oder einen <strong>Prozentsatz</strong> seines aktuellen Pakets (<em>z. B. 0,05 bedeutet 5%</em>) angeben."
renew_pack_threshold: "threshold for packs renewal" renew_pack_threshold: "Schwellenwert für Paketverlängerung"
pack_only_for_subscription_info_html: "If this option is activated, the purchase and use of a prepaid pack is only possible for the user with a valid subscription." pack_only_for_subscription_info_html: "Wenn diese Option aktiviert ist, können nur Benutzer mit einem gültigen Abonnement vorausbezahlte Pakete kaufen und nutzen."
pack_only_for_subscription: "Subscription valid for purchase and use of a prepaid pack" pack_only_for_subscription: "Abonnement gültig für Kauf und Nutzung eines vorausbezahlten Pakets"
pack_only_for_subscription_info: "Make subscription mandatory for prepaid packs" pack_only_for_subscription_info: "Abonnement für vorausbezahlte Pakete obligatorisch machen"
extended_prices: "Extended prices" extended_prices: "Erweiterter Preis"
extended_prices_info_html: "Spaces can have different prices depending on the cumulated duration of the booking. You can choose if this apply to all bookings or only to those starting within the same day." extended_prices_info_html: "Räume können je nach Dauer der Buchung unterschiedliche Preise haben. Sie können wählen, ob dies für alle Buchungen oder nur für diejenigen gilt, die am selben Tag beginnen."
extended_prices_in_same_day: "Extended prices in the same day" extended_prices_in_same_day: "Erweiterte Preise am selben Tag"
public_registrations: "Public registrations" public_registrations: "Öffentliche Registrierungen"
overlapping_options: overlapping_options:
training_reservations: "Trainings" training_reservations: "Schulungen"
machine_reservations: "Machines" machine_reservations: "Maschinen"
space_reservations: "Spaces" space_reservations: "Räume"
events_reservations: "Events" events_reservations: "Veranstaltungen"
general: general:
general: "Allgemein" general: "Allgemein"
title: "Titel" title: "Titel"
@ -1317,9 +1321,9 @@ de:
name: "Name" name: "Name"
created_at: "Erstellungsdatum" created_at: "Erstellungsdatum"
updated_at: "Datum der letzten Aktualisierung" updated_at: "Datum der letzten Aktualisierung"
public_registrations: "Public registrations" public_registrations: "Öffentliche Registrierungen"
public_registrations_info: "Allow everyone to register a new account on the platform. If disabled, only administrators and managers can create new accounts." public_registrations_info: "Erlaube jedem, ein neues Konto auf der Plattform anzulegen. Wenn deaktiviert, können nur Administratoren und Manager neue Konten erstellen."
public_registrations_allowed: "Public registrations allowed" public_registrations_allowed: "Öffentliche Registrierungen erlaubt"
help: "Hilfe" help: "Hilfe"
feature_tour: "Feature-Tour" feature_tour: "Feature-Tour"
feature_tour_info_html: "<p>Wenn sich ein Administrator oder Manager anmeldet, wird beim jeweils ersten Besuch eines Abschnitts der Anwendung die Feature-Tour ausgelöst. Sie können dieses Verhalten auf einen der folgenden Werte ändern:</p><ul><li>« Einmal », um das Standardverhalten beizubehalten.</li><li>« Pro Sitzung », um die Tour jedes Mal anzuzeigen, wenn die Anwendung erneut geöffnet wird.</li><li>« Nur manuell », deaktiviert die automatische Anzeige der Touren. Es ist weiterhin möglich, sie durch Drücken der F1-Taste oder durch Klicken auf « Hilfe » im Benutzermenu zu starten.</li></ul>" feature_tour_info_html: "<p>Wenn sich ein Administrator oder Manager anmeldet, wird beim jeweils ersten Besuch eines Abschnitts der Anwendung die Feature-Tour ausgelöst. Sie können dieses Verhalten auf einen der folgenden Werte ändern:</p><ul><li>« Einmal », um das Standardverhalten beizubehalten.</li><li>« Pro Sitzung », um die Tour jedes Mal anzuzeigen, wenn die Anwendung erneut geöffnet wird.</li><li>« Nur manuell », deaktiviert die automatische Anzeige der Touren. Es ist weiterhin möglich, sie durch Drücken der F1-Taste oder durch Klicken auf « Hilfe » im Benutzermenu zu starten.</li></ul>"
@ -1335,9 +1339,9 @@ de:
wallet: "Guthabenkonto" wallet: "Guthabenkonto"
wallet_info_html: "<p>Mit dem Guthabenkonto können Sie Benutzern eine Geldsumme zuweisen. Diese können es nach Belieben im Fab-Manager ausgeben.</p><p>Mitglieder können ihr Guthabenkonto nicht selbst aufladen, das können nur Manager und Administratoren.</p>" wallet_info_html: "<p>Mit dem Guthabenkonto können Sie Benutzern eine Geldsumme zuweisen. Diese können es nach Belieben im Fab-Manager ausgeben.</p><p>Mitglieder können ihr Guthabenkonto nicht selbst aufladen, das können nur Manager und Administratoren.</p>"
enable_wallet: "Guthabenkonto aktivieren" enable_wallet: "Guthabenkonto aktivieren"
public_agenda: "Public agenda" public_agenda: "Öffentliche Agenda"
public_agenda_info_html: "<p>The public agenda offers to members and visitors a general overview of the Fablab's planning.</p><p>Please note that, even logged, users won't be able to book a reservation or modify anything from this agenda: this is a read-only page.</p>" public_agenda_info_html: "<p>Die öffentliche Agenda bietet Mitgliedern und Besuchern eine allgemeine Übersicht über die Planung des Fablabs.</p><p>Bitte beachten Sie, dass selbst eingeloggte Benutzer keine Reservierung buchen oder die Agenda ändern können: Dies ist eine schreibgeschützte Seite.</p>"
enable_public_agenda: "Enable public agenda" enable_public_agenda: "Öffentliche Agenda aktivieren"
statistics: "Statistiken" statistics: "Statistiken"
statistics_info_html: "<p>Aktivieren oder deaktivieren Sie das Statistik-Modul.</p><p>Wenn aktiviert, konsolidiert das Modul die Tagesdaten in der Datenbank einer leistungsstarken Analyse-Engine. Administratoren können im entsprechenden Abschnitt die erstellten Diagramme und Tabellen durchsuchen.</p>" statistics_info_html: "<p>Aktivieren oder deaktivieren Sie das Statistik-Modul.</p><p>Wenn aktiviert, konsolidiert das Modul die Tagesdaten in der Datenbank einer leistungsstarken Analyse-Engine. Administratoren können im entsprechenden Abschnitt die erstellten Diagramme und Tabellen durchsuchen.</p>"
enable_statistics: "Statistik-Modul aktivieren" enable_statistics: "Statistik-Modul aktivieren"
@ -1381,7 +1385,7 @@ de:
online_payment: "Ist das Online-Zahlungsmodul aktiv?" online_payment: "Ist das Online-Zahlungsmodul aktiv?"
invoices: "Ist das Rechnungsmodul aktiv?" invoices: "Ist das Rechnungsmodul aktiv?"
openlab: "Ist das Projektteilungsmodul (OpenLab) aktiv?" openlab: "Ist das Projektteilungsmodul (OpenLab) aktiv?"
tracking_id_info_html: "<p>Um die statistische Analyse der Besuche mithilfe von Google Analytics zu ermöglichen, tragen Sie hier Ihre Tracking-ID in der Form UA-000000-0 ein. Besuchen Sie <a href='https://analytics.google.com/analytics/web/' target='_blank'>die Google Analytics Website</a>, um eine Tracking-ID zu erstellen.<br/><strong>Warnung:</strong> wenn Sie dieses Feature aktivieren, muss in Ihrer Datenschutzrichtlinie darauf hingewiesen werden.</p><p> Um Google Analytics verwenden zu können, benötigen Sie auch den Hostnamen. Klicken Sie auf die angrenzende Schaltfläche. Dieser letzte Parameter wird auch an anderen Stellen verwendet, bitte verwenden Sie ihn vorsichtig.</p>" tracking_id_info_html: "Um die statistische Analyse der Besuche mithilfe von Google Analytics V4 zu ermöglichen, tragen Sie hier Ihre Tracking-ID in der Form G-XXXXXX ein. Besuchen Sie <a href='https://analytics.google.com/analytics/web/' target='_blank'>die Google Analytics Website</a>, um eine Tracking-ID zu erstellen.<br/><strong>Warnung:</strong> wenn Sie dieses Feature aktivieren, wird ein Cookie erstellt. Denken Sie daran, es oben in Ihrer Datenschutzrichtlinie darauf hingewiesen werden."
tracking_id: "Tracking-ID" tracking_id: "Tracking-ID"
open_api_clients: open_api_clients:
add_new_client: "Neuen API-Client erstellen" add_new_client: "Neuen API-Client erstellen"
@ -1395,7 +1399,7 @@ de:
client_name: "Kundenname" client_name: "Kundenname"
confirmation_required: "Bestätigung erforderlich" confirmation_required: "Bestätigung erforderlich"
do_you_really_want_to_delete_this_open_api_client: "Möchten Sie diesen OpenAPI-Client wirklich löschen?" do_you_really_want_to_delete_this_open_api_client: "Möchten Sie diesen OpenAPI-Client wirklich löschen?"
do_you_really_want_to_revoke_this_open_api_access: "Möchten Sie diesen Zugriff wirklich widerrufen ? Er wird das aktuelle Token löschen und ersetzen." do_you_really_want_to_revoke_this_open_api_access: "Möchten Sie diesen Zugriff wirklich widerrufen? Er wird das aktuelle Token löschen und ersetzen."
client_successfully_created: "Client erfolgreich erstellt." client_successfully_created: "Client erfolgreich erstellt."
client_successfully_updated: "Client erfolgreich aktualisiert." client_successfully_updated: "Client erfolgreich aktualisiert."
client_successfully_deleted: "Client erfolgreich gelöscht." client_successfully_deleted: "Client erfolgreich gelöscht."
@ -1422,50 +1426,50 @@ de:
report_removed: "Der Bericht wurde gelöscht" report_removed: "Der Bericht wurde gelöscht"
failed_to_remove: "Ein Fehler ist aufgetreten, der Bericht konnte nicht gelöscht werden" failed_to_remove: "Ein Fehler ist aufgetreten, der Bericht konnte nicht gelöscht werden"
plans_categories: plans_categories:
manage_plans_categories: "Manage plans' categories" manage_plans_categories: "Plan-Kategorien verwalten"
plan_categories_list: plan_categories_list:
categories_list: "List of the plan's categories" categories_list: "Liste der Kategorien des Plans"
no_categories: "Keine Kategorien" no_categories: "Keine Kategorien"
name: "Name" name: "Name"
significance: "Significance" significance: "Signifikanz"
create_plan_category: create_plan_category:
new_category: "New category" new_category: "Neue Kategorie"
name: "Name" name: "Name"
significance: "Significance" significance: "Signifikanz"
significance_info: "Categories will be shown ordered by signifiance. The higher you set the significance, the first the category will be shown." significance_info: "Kategorien werden nach Signifikanz sortiert. Je höher die Signifikanz, desto weiter oben wird die Kategorie angezeigt."
confirm_create: "Create the category" confirm_create: "Kategorie erstellen"
category_created: "The new category was successfully created" category_created: "Die neue Kategorie wurde erfolgreich erstellt"
unable_to_create: "Unable to create the category: " unable_to_create: "Die Kategorie konnte nicht erstellt werden: "
edit_plan_category: edit_plan_category:
edit_category: "Edit the category" edit_category: "Kategorie bearbeiten"
name: "Name" name: "Name"
significance: "Significance" significance: "Signifikanz"
confirm_edition: "Validate" confirm_edition: "Bestätigen"
category_updated: "The category was successfully updated" category_updated: "Die Kategorie wurde erfolgreich aktualisiert"
unable_to_update: "Unable to update the category: " unable_to_update: "Die Kategorie konnte nicht aktualisiert werden: "
significance_info: "Categories will be shown ordered by signifiance. The higher you set the significance, the first the category will be shown." significance_info: "Kategorien werden nach Signifikanz sortiert. Je höher die Signifikanz, desto weiter oben wird die Kategorie angezeigt."
delete_plan_category: delete_plan_category:
delete_category: "Delete a category" delete_category: "Kategorie löschen"
confirm_delete: "Delete" confirm_delete: "Löschen"
delete_confirmation: "Are you sure you want to delete this category? If you do, the plans associated with this category won't be sorted anymore." delete_confirmation: "Sind Sie sicher, dass Sie diese Kategorie löschen möchten? Wenn Sie dies tun, werden die mit dieser Kategorie verbundenen Pläne nicht mehr sortiert."
category_deleted: "The category was successfully deleted" category_deleted: "Die Kategorie wurde erfolgreich gelöscht"
unable_to_delete: "Unable to delete the category: " unable_to_delete: "Die Kategorie konnte nicht gelöscht werden: "
local_payment: local_payment:
validate_cart: "Validate my cart" validate_cart: "Bestätigen Sie den Warenkorb"
offline_payment: "Payment on site" offline_payment: "Zahlung vor Ort"
about_to_cash: "You're about to confirm the cashing by an external payment mean. Please do not click on the button below until you have fully cashed the requested payment." about_to_cash: "Sie bestätigen die Zahlung über ein externes Zahlungsmittel. Bitte klicken Sie nicht auf die Schaltfläche unten, bis Sie die angeforderte Zahlung vollständig eingelöst haben."
about_to_confirm: "You're about to confirm your {ITEM, select, subscription{subscription} other{reservation}}." about_to_confirm: "Sie bestätigen nun {ITEM, select, subscription{Ihr Abonnement} other{Ihre Reservierung}}"
payment_method: "Payment method" payment_method: "Zahlungsmethode"
method_card: "Online by card" method_card: "Online per Karte"
method_check: "By check" method_check: "Per Scheck"
method_transfer: "By bank transfer" method_transfer: "Per Banküberweisung"
card_collection_info: "By validating, you'll be prompted for the member's card number. This card will be automatically charged at the deadlines." card_collection_info: "Nach der Validierung werden Sie nach der Kartennummer des Mitglieds gefragt. Diese Karte wird automatisch zu den Fristen belastet."
check_collection_info: "By validating, you confirm that you have {DEADLINES} checks, allowing you to collect all the monthly payments." check_collection_info: "Durch die Validierung bestätigen Sie, dass Sie {DEADLINES} Schecks haben und so alle monatlichen Zahlungen abwickeln können."
transfer_collection_info: "<p>By validating, you confirm that you set up {DEADLINES} bank direct debits, allowing you to collect all the monthly payments.</p><p><strong>Please note:</strong> the bank transfers are not automatically handled by Fab-manager.</p>" transfer_collection_info: "<p>Durch die Validierung bestätigen Sie, dass Sie {DEADLINES} Bank-Lastschriften eingerichtet haben, so dass alle monatlichen Zahlungen eingezogen werden können.</p><p><strong>Bitte beachten Sie:</strong> Banküberweisungen werden nicht automatisch vom Fab-Manager bearbeitet.</p>"
online_payment_disabled: "Online payment is not available. You cannot collect this payment schedule by online card." online_payment_disabled: "Online-Zahlung ist nicht verfügbar. Sie können diesen Zahlungsplan nicht per Karte online abwickeln."
check_list_setting: check_list_setting:
save: 'Save' save: 'Speichern'
customization_of_SETTING_successfully_saved: "Customization of the {SETTING} successfully saved." customization_of_SETTING_successfully_saved: "Anpassung von {SETTING} erfolgreich gespeichert."
#feature tour #feature tour
tour: tour:
conclusion: conclusion:
@ -1554,8 +1558,8 @@ de:
title: "Gutschrift" title: "Gutschrift"
content: "Ermöglicht die Erstellung einer Gutschrift für die Rechnung in dieser Zeile oder für ihre Unterelemente. <strong>Warnung:</strong> Nur das Rechnungsdokument wird generiert, die tatsächliche Gutschrift für den Benutzer wird immer in Ihrer Verantwortung liegen." content: "Ermöglicht die Erstellung einer Gutschrift für die Rechnung in dieser Zeile oder für ihre Unterelemente. <strong>Warnung:</strong> Nur das Rechnungsdokument wird generiert, die tatsächliche Gutschrift für den Benutzer wird immer in Ihrer Verantwortung liegen."
payment-schedules: payment-schedules:
title: "Payment schedules" title: "Zahlungspläne"
content: "<p>Some subscription plans may be configured to allow the members to pay them with a monthly payment schedule.</p><p>Here you can view all existing payment schedules and manage their deadlines.</p><p>Click on [+] at the beginning of a row to display all deadlines associated with a payment schedule, and run some actions on them.</p>" content: "<p>Einige Abonnements können so konfiguriert werden, dass die Mitglieder sie mit einem monatlichen Zahlungsplan bezahlen können.</p><p>Hier können Sie alle bestehenden Zahlungspläne einsehen und deren Fristen verwalten.</p><p>Klicken Sie auf [+] am Anfang einer Reihe, um alle mit einem Zahlungsplan verbundenen Fristen anzuzeigen, und führen Sie Aktionen aus.</p>"
settings: settings:
title: "Einstellungen" title: "Einstellungen"
content: "<p>Hier können Sie die Parameter für die Rechnungserstellung ändern. Klicken Sie auf das Element, das Sie bearbeiten wollen.</p><p>Insbesondere legen Sie hier fest, ob Sie der Mehrwertsteuer unterliegen und zu welchem Satz.</p>" content: "<p>Hier können Sie die Parameter für die Rechnungserstellung ändern. Klicken Sie auf das Element, das Sie bearbeiten wollen.</p><p>Insbesondere legen Sie hier fest, ob Sie der Mehrwertsteuer unterliegen und zu welchem Satz.</p>"

View File

@ -15,7 +15,7 @@ en:
trainings: "Trainings" trainings: "Trainings"
machines: "Machines" machines: "Machines"
spaces: "Spaces" spaces: "Spaces"
events: "Eventos" events: "Events"
availabilities: "Availabilities" availabilities: "Availabilities"
availabilities_notice: "Export to an Excel workbook every slots available for reservation, and their occupancy rate." availabilities_notice: "Export to an Excel workbook every slots available for reservation, and their occupancy rate."
info: "Info" info: "Info"
@ -24,7 +24,7 @@ en:
ongoing_reservations: "Ongoing reservations" ongoing_reservations: "Ongoing reservations"
without_reservation: "Without reservation" without_reservation: "Without reservation"
confirmation_required: "Confirmation required" confirmation_required: "Confirmation required"
do_you_really_want_to_cancel_the_USER_s_reservation_the_DATE_at_TIME_concerning_RESERVATION: "Do you really {GENDER, select, other {want}} to cancel the {USER}'s reservation, the {DATE} at {TIME}, concerning {RESERVATION}?" do_you_really_want_to_cancel_the_USER_s_reservation_the_DATE_at_TIME_concerning_RESERVATION: "Do you really want to cancel {USER}'s reservation, the {DATE} at {TIME}, concerning {RESERVATION}?"
reservation_was_successfully_cancelled: "Reservation was successfully cancelled." reservation_was_successfully_cancelled: "Reservation was successfully cancelled."
reservation_cancellation_failed: "Reservation cancellation failed." reservation_cancellation_failed: "Reservation cancellation failed."
unable_to_remove_the_last_machine_of_the_slot_delete_the_slot_rather: "Unable to remove the last machine of the slot. Delete the slot rather." unable_to_remove_the_last_machine_of_the_slot_delete_the_slot_rather: "Unable to remove the last machine of the slot. Delete the slot rather."
@ -184,7 +184,7 @@ en:
NUMBER_reservation: "{NUMBER} {NUMBER, plural, one{reservation} other{reservations}}" NUMBER_reservation: "{NUMBER} {NUMBER, plural, one{reservation} other{reservations}}"
none: "None" none: "None"
training_validation: "Training validation" training_validation: "Training validation"
training_of_the_DATE_TIME_html : "Training of the <strong>{DATE} - {TIME}</strong>" training_of_the_DATE_TIME_html: "Training of the <strong>{DATE} - {TIME}</strong>"
you_can_validate_the_training_of_the_following_members: "You can validate the training of the following members:" you_can_validate_the_training_of_the_following_members: "You can validate the training of the following members:"
deleted_user: "Deleted user" deleted_user: "Deleted user"
no_reservation: "No reservation" no_reservation: "No reservation"
@ -271,7 +271,7 @@ en:
events_edit: events_edit:
edit_the_event: "Edit the event" edit_the_event: "Edit the event"
confirmation_required: "Confirmation required" confirmation_required: "Confirmation required"
edit_recurring_event: "You're about to update a periodic event. What do you want to update ?" edit_recurring_event: "You're about to update a periodic event. What do you want to update?"
edit_this_event: "Only this event" edit_this_event: "Only this event"
edit_this_and_next: "This event and the following" edit_this_and_next: "This event and the following"
edit_all: "All events" edit_all: "All events"
@ -322,10 +322,10 @@ en:
none: "None" #grammar concordance with training. none: "None" #grammar concordance with training.
an_error_occurred_while_saving_the_number_of_credits: "An error occurred while saving the number of credits." an_error_occurred_while_saving_the_number_of_credits: "An error occurred while saving the number of credits."
an_error_occurred_while_deleting_credit_with_the_TRAINING: "An error occurred while deleting credit with the {TRAINING}." an_error_occurred_while_deleting_credit_with_the_TRAINING: "An error occurred while deleting credit with the {TRAINING}."
an_error_occurred_unable_to_find_the_credit_to_revoke: "An error occurred : unable to find the credit to revoke." an_error_occurred_unable_to_find_the_credit_to_revoke: "An error occurred: unable to find the credit to revoke."
an_error_occurred_while_creating_credit_with_the_TRAINING: "An error occurred while creating credit with the {TRAINING}." an_error_occurred_while_creating_credit_with_the_TRAINING: "An error occurred while creating credit with the {TRAINING}."
not_set: "Not set" not_set: "Not set"
error_a_credit_linking_this_machine_with_that_subscription_already_exists: "Error : a credit linking this machine with that subscription already exists." error_a_credit_linking_this_machine_with_that_subscription_already_exists: "Error: a credit linking this machine with that subscription already exists."
changes_have_been_successfully_saved: "Changes have been successfully saved." changes_have_been_successfully_saved: "Changes have been successfully saved."
credit_was_successfully_saved: "Credit was successfully saved." credit_was_successfully_saved: "Credit was successfully saved."
error_creating_credit: "Unable to create credit, an error occurred" error_creating_credit: "Unable to create credit, an error occurred"
@ -365,7 +365,7 @@ en:
these_prices_match_space_hours_rates_html: "The prices below match one hour of space usage, <strong>without subscription</strong>." these_prices_match_space_hours_rates_html: "The prices below match one hour of space usage, <strong>without subscription</strong>."
add_a_space_credit: "Add a Space credit" add_a_space_credit: "Add a Space credit"
space: "Space" space: "Space"
error_a_credit_linking_this_space_with_that_subscription_already_exists: "Error : a credit linking this space with that subscription already exists." error_a_credit_linking_this_space_with_that_subscription_already_exists: "Error: a credit linking this space with that subscription already exists."
status_enabled: "Enabled" status_enabled: "Enabled"
status_disabled: "Disabled" status_disabled: "Disabled"
status_all: "All" status_all: "All"
@ -511,7 +511,7 @@ en:
no_invoices_for_now: "No invoices for now." no_invoices_for_now: "No invoices for now."
payment_schedules_list: "Payment schedules" payment_schedules_list: "Payment schedules"
invoicing_settings: "Invoicing settings" invoicing_settings: "Invoicing settings"
warning_invoices_disabled: "Warning : invoices are not enabled. No invoices will be generated by Fab-manager. Nevertheless, you must correctly fill the information below, especially VAT." warning_invoices_disabled: "Warning: invoices are not enabled. No invoices will be generated by Fab-manager. Nevertheless, you must correctly fill the information below, especially VAT."
change_logo: "Change logo" change_logo: "Change logo"
john_smith: "John Smith" john_smith: "John Smith"
john_smith_at_example_com: "jean.smith@example.com" john_smith_at_example_com: "jean.smith@example.com"
@ -702,6 +702,10 @@ en:
general_space_code: "Accounting code for all spaces" general_space_code: "Accounting code for all spaces"
accounting_Space_label: "Spaces label" accounting_Space_label: "Spaces label"
general_space_label: "Account label for all spaces" general_space_label: "Account label for all spaces"
accounting_Pack_code: "Prepaid-pack code"
general_pack_code: "Accounting code for prepaid-packs"
accounting_Pack_label: "Prepaid-pack label"
general_pack_label: "Account label for prepaid-packs"
accounting_Error_code: "Errors code" accounting_Error_code: "Errors code"
general_error_code: "Accounting code for erroneous invoices" general_error_code: "Accounting code for erroneous invoices"
accounting_Error_label: "Errors label" accounting_Error_label: "Errors label"
@ -1012,7 +1016,7 @@ en:
#add a new administrator to the platform #add a new administrator to the platform
admins_new: admins_new:
add_an_administrator: "Add an administrator" add_an_administrator: "Add an administrator"
administrator_successfully_created_he_will_receive_his_connection_directives_by_email: "Administrator successfully created. {GENDER, select, female{She} other{He}} receive {GENDER, select, female{her} other{his}} connection directives by e-mail." administrator_successfully_created_he_will_receive_his_connection_directives_by_email: "Successful creation. Connection directives were sent to the new administrator by e-mail."
failed_to_create_admin: "Unable to create the administrator:" failed_to_create_admin: "Unable to create the administrator:"
man: "Man" man: "Man"
woman: "Woman" woman: "Woman"
@ -1030,7 +1034,7 @@ en:
#add a new manager to the platform #add a new manager to the platform
manager_new: manager_new:
add_a_manager: "Add a manager" add_a_manager: "Add a manager"
manager_successfully_created: "Manager successfully created. {GENDER, select, female{She} other{He}} receive {GENDER, select, female{her} other{his}} connection directives by e-mail." manager_successfully_created: "Successful creation. Connection directives were sent to the new manager by e-mail."
failed_to_create_manager: "Unable to create the manager:" failed_to_create_manager: "Unable to create the manager:"
man: "Man" man: "Man"
woman: "Woman" woman: "Woman"
@ -1061,7 +1065,7 @@ en:
oauth2_provider_successfully_added: "OAuth 2.0 provider successfully added." oauth2_provider_successfully_added: "OAuth 2.0 provider successfully added."
#edit an authentication provider (SSO) #edit an authentication provider (SSO)
authentication_edit: authentication_edit:
provider: "Provider :" provider: "Provider:"
it_is_required_to_set_the_matching_between_User.uid_and_the_API_to_add_this_provider: "It is required to set the matching between User.uid and the API to add this provider." it_is_required_to_set_the_matching_between_User.uid_and_the_API_to_add_this_provider: "It is required to set the matching between User.uid and the API to add this provider."
provider_successfully_updated: "Provider successfully updated." provider_successfully_updated: "Provider successfully updated."
an_error_occurred_unable_to_update_the_provider: "An error occurred: unable to update the provider." an_error_occurred_unable_to_update_the_provider: "An error occurred: unable to update the provider."
@ -1351,7 +1355,7 @@ en:
public_registrations_allowed: "Public registrations allowed" public_registrations_allowed: "Public registrations allowed"
help: "Help" help: "Help"
feature_tour: "Feature tour" feature_tour: "Feature tour"
feature_tour_info_html: "<p>When an administrator or a manager in logged-in, a feature tour will be triggered the first time he/she visits each section of the application. You can change this behavior to one of the following values:</p><ul><li>« Once » to keep the default behavior.</li><li>« By session » to display the tours each time you reopen the application.</li><li>« Manual trigger » to prevent displaying the tours automatically. It'll still be possible to trigger them by pressing the F1 key or by clicking on « Help » in the user's menu.</li></ul>" feature_tour_info_html: "<p>When an administrator or a manager in logged-in, a feature tour will be triggered the first time he visits each section of the application. You can change this behavior to one of the following values:</p><ul><li>« Once » to keep the default behavior.</li><li>« By session » to display the tours each time you reopen the application.</li><li>« Manual trigger » to prevent displaying the tours automatically. It'll still be possible to trigger them by pressing the F1 key or by clicking on « Help » in the user's menu.</li></ul>"
feature_tour_display_mode: "Feature tour display mode" feature_tour_display_mode: "Feature tour display mode"
display_mode: display_mode:
once: "Once" once: "Once"
@ -1410,7 +1414,7 @@ en:
online_payment: "Is the online payment module active?" online_payment: "Is the online payment module active?"
invoices: "Is the invoicing module active?" invoices: "Is the invoicing module active?"
openlab: "Is the project sharing module (OpenLab) active?" openlab: "Is the project sharing module (OpenLab) active?"
tracking_id_info_html: "<p>To enable the statistical tracking of the visits using Google Analytics, set your tracking ID here. It is in the form UA-000000-2. Visit <a href='https://analytics.google.com/analytics/web/' target='_blank'>the Google Analytics website</a> to get one.<br/><strong>Warning:</strong> if you enable this feature, remember to write it in your privacy policy, above.</p><p>The host name is also required to use Google Analytics. You can get it by clicking on the adjacent button. This last parameter is used elsewhere, please set it carefully.</p>" tracking_id_info_html: "To enable the statistical tracking of the visits using Google Analytics V4, set your tracking ID here. It is in the form G-XXXXXX. Visit <a href='https://analytics.google.com/analytics/web/' target='_blank'>the Google Analytics website</a> to get one.<br/><strong>Warning:</strong> if you enable this feature, a cookie will be created. Remember to write it down in your privacy policy, above."
tracking_id: "Tracking ID" tracking_id: "Tracking ID"
open_api_clients: open_api_clients:
add_new_client: "Create new API client" add_new_client: "Create new API client"
@ -1424,7 +1428,7 @@ en:
client_name: "Client's name" client_name: "Client's name"
confirmation_required: "Confirmation required" confirmation_required: "Confirmation required"
do_you_really_want_to_delete_this_open_api_client: "Do you really want to delete this OpenAPI client?" do_you_really_want_to_delete_this_open_api_client: "Do you really want to delete this OpenAPI client?"
do_you_really_want_to_revoke_this_open_api_access: "Do you really want to revoke this access ? It will erase and replace the current token." do_you_really_want_to_revoke_this_open_api_access: "Do you really want to revoke this access? It will erase and replace the current token."
client_successfully_created: "Client successfully created." client_successfully_created: "Client successfully created."
client_successfully_updated: "Client successfully updated." client_successfully_updated: "Client successfully updated."
client_successfully_deleted: "Client successfully deleted." client_successfully_deleted: "Client successfully deleted."

View File

@ -24,7 +24,7 @@ es:
ongoing_reservations: "Reservas en curso" ongoing_reservations: "Reservas en curso"
without_reservation: "Sin reserva" without_reservation: "Sin reserva"
confirmation_required: "Confirmación requerida" confirmation_required: "Confirmación requerida"
do_you_really_want_to_cancel_the_USER_s_reservation_the_DATE_at_TIME_concerning_RESERVATION: "Realmente quieres cancelar la reserva del {USER}, en {DATE} a las {TIME}, respecto {RESERVATION}?" do_you_really_want_to_cancel_the_USER_s_reservation_the_DATE_at_TIME_concerning_RESERVATION: "¿Realmente quieres cancelar la reserva del {USER}, en {DATE} a las {TIME}, respecto {RESERVATION}?"
reservation_was_successfully_cancelled: "La reserva fué cancelada con éxito." reservation_was_successfully_cancelled: "La reserva fué cancelada con éxito."
reservation_cancellation_failed: "Fallo al cancelar la reserva." reservation_cancellation_failed: "Fallo al cancelar la reserva."
unable_to_remove_the_last_machine_of_the_slot_delete_the_slot_rather: "No se puede quitar la última máquina de la ranura. Eliminar la ranura en su lugar." unable_to_remove_the_last_machine_of_the_slot_delete_the_slot_rather: "No se puede quitar la última máquina de la ranura. Eliminar la ranura en su lugar."
@ -271,7 +271,7 @@ es:
events_edit: events_edit:
edit_the_event: "Editar el evento" edit_the_event: "Editar el evento"
confirmation_required: "Confirmation required" confirmation_required: "Confirmation required"
edit_recurring_event: "You're about to update a periodic event. What do you want to update ?" edit_recurring_event: "You're about to update a periodic event. What do you want to update?"
edit_this_event: "Only this event" edit_this_event: "Only this event"
edit_this_and_next: "This event and the following" edit_this_and_next: "This event and the following"
edit_all: "All events" edit_all: "All events"
@ -482,7 +482,7 @@ es:
no_invoices_for_now: "Sin facturas por ahora." no_invoices_for_now: "Sin facturas por ahora."
payment_schedules_list: "Payment schedules" payment_schedules_list: "Payment schedules"
invoicing_settings: "Configuración de facturación" invoicing_settings: "Configuración de facturación"
warning_invoices_disabled: "Warning : invoices are not enabled. No invoices will be generated by Fab-manager. Nevertheless, you must correctly fill the information below, especially VAT." warning_invoices_disabled: "Warning: invoices are not enabled. No invoices will be generated by Fab-manager. Nevertheless, you must correctly fill the information below, especially VAT."
change_logo: "Cambio de logotipo" change_logo: "Cambio de logotipo"
john_smith: "John Smith" john_smith: "John Smith"
john_smith_at_example_com: "jean.smith@example.com" john_smith_at_example_com: "jean.smith@example.com"
@ -673,6 +673,10 @@ es:
general_space_code: "Accounting code for all spaces" general_space_code: "Accounting code for all spaces"
accounting_Space_label: "Spaces label" accounting_Space_label: "Spaces label"
general_space_label: "Account label for all spaces" general_space_label: "Account label for all spaces"
accounting_Pack_code: "Prepaid-pack code"
general_pack_code: "Accounting code for prepaid-packs"
accounting_Pack_label: "Prepaid-pack label"
general_pack_label: "Account label for prepaid-packs"
accounting_Error_code: "Errors code" accounting_Error_code: "Errors code"
general_error_code: "Accounting code for erroneous invoices" general_error_code: "Accounting code for erroneous invoices"
accounting_Error_label: "Errors label" accounting_Error_label: "Errors label"
@ -838,7 +842,7 @@ es:
active: "Activo" active: "Activo"
pending: "Pendiente" pending: "Pendiente"
previous_provider: "Proveedor anteriorr" previous_provider: "Proveedor anteriorr"
confirmation_required: "Delete the provider?" confirmation_required: "¿Eliminar el proveedor?"
do_you_really_want_to_delete_the_TYPE_authentication_provider_NAME: "¿Realmente desea eliminar la {TYPE} proveedor de autenticación: {NAME}?" do_you_really_want_to_delete_the_TYPE_authentication_provider_NAME: "¿Realmente desea eliminar la {TYPE} proveedor de autenticación: {NAME}?"
authentication_provider_successfully_deleted: "El proveedor de autenticación se eliminó correctamente." authentication_provider_successfully_deleted: "El proveedor de autenticación se eliminó correctamente."
an_error_occurred_unable_to_delete_the_specified_provider: "Se ha producido un error: no se puede eliminar el proveedor especificado." an_error_occurred_unable_to_delete_the_specified_provider: "Se ha producido un error: no se puede eliminar el proveedor especificado."
@ -983,7 +987,7 @@ es:
#add a new administrator to the platform #add a new administrator to the platform
admins_new: admins_new:
add_an_administrator: "Agregar un administrador" add_an_administrator: "Agregar un administrador"
administrator_successfully_created_he_will_receive_his_connection_directives_by_email: "administrador creado correctamente. {GENDER, select, female{She} other{He}} receive {GENDER, select, female{her} other{his}} directivas de conexión por e-mail." administrator_successfully_created_he_will_receive_his_connection_directives_by_email: "Successful creation. Connection directives were sent to the new administrator by e-mail."
failed_to_create_admin: "No se puede crear el administrador :" failed_to_create_admin: "No se puede crear el administrador :"
man: "Man" man: "Man"
woman: "Woman" woman: "Woman"
@ -1001,7 +1005,7 @@ es:
#add a new manager to the platform #add a new manager to the platform
manager_new: manager_new:
add_a_manager: "Add a manager" add_a_manager: "Add a manager"
manager_successfully_created: "Manager successfully created. {GENDER, select, female{She} other{He}} receive {GENDER, select, female{her} other{his}} connection directives by e-mail." manager_successfully_created: "Successful creation. Connection directives were sent to the new manager by e-mail."
failed_to_create_manager: "Unable to create the manager:" failed_to_create_manager: "Unable to create the manager:"
man: "Man" man: "Man"
woman: "Woman" woman: "Woman"
@ -1032,7 +1036,7 @@ es:
oauth2_provider_successfully_added: "OAuth 2.0 proveedor agregado correctamente." oauth2_provider_successfully_added: "OAuth 2.0 proveedor agregado correctamente."
#edit an authentication provider (SSO) #edit an authentication provider (SSO)
authentication_edit: authentication_edit:
provider: "Proveedor :" 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." 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." 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." an_error_occurred_unable_to_update_the_provider: "Se ha producido un error: no se puede actualizar el proveedor."
@ -1322,7 +1326,7 @@ es:
public_registrations_allowed: "Public registrations allowed" public_registrations_allowed: "Public registrations allowed"
help: "Help" help: "Help"
feature_tour: "Feature tour" feature_tour: "Feature tour"
feature_tour_info_html: "<p>When an administrator or a manager in logged-in, a feature tour will be triggered the first time he/she visits each section of the application. You can change this behavior to one of the following values:</p><ul><li>« Once » to keep the default behavior.</li><li>« By session » to display the tours each time you reopen the application.</li><li>« Manual trigger » to prevent displaying the tours automatically. It'll still be possible to trigger them by pressing the F1 key or by clicking on « Help » in the user's menu.</li></ul>" feature_tour_info_html: "<p>When an administrator or a manager in logged-in, a feature tour will be triggered the first time he visits each section of the application. You can change this behavior to one of the following values:</p><ul><li>« Once » to keep the default behavior.</li><li>« By session » to display the tours each time you reopen the application.</li><li>« Manual trigger » to prevent displaying the tours automatically. It'll still be possible to trigger them by pressing the F1 key or by clicking on « Help » in the user's menu.</li></ul>"
feature_tour_display_mode: "Feature tour display mode" feature_tour_display_mode: "Feature tour display mode"
display_mode: display_mode:
once: "Once" once: "Once"
@ -1381,7 +1385,7 @@ es:
online_payment: "Is the online payment module active?" online_payment: "Is the online payment module active?"
invoices: "Is the invoicing module active?" invoices: "Is the invoicing module active?"
openlab: "Is the project sharing module (OpenLab) active?" openlab: "Is the project sharing module (OpenLab) active?"
tracking_id_info_html: "<p>To enable the statistical tracking of the visits using Google Analytics, set your tracking ID here. It is in the form UA-000000-2. Visit <a href='https://analytics.google.com/analytics/web/' target='_blank'>the Google Analytics website</a> to get one.<br/><strong>Warning:</strong> if you enable this feature, remember to write it in your privacy policy, above.</p><p>The host name is also required to use Google Analytics. You can get it by clicking on the adjacent button. This last parameter is used elsewhere, please set it carefully.</p>" tracking_id_info_html: "To enable the statistical tracking of the visits using Google Analytics V4, set your tracking ID here. It is in the form G-XXXXXX. Visit <a href='https://analytics.google.com/analytics/web/' target='_blank'>the Google Analytics website</a> to get one.<br/><strong>Warning:</strong> if you enable this feature, a cookie will be created. Remember to write it down in your privacy policy, above."
tracking_id: "Tracking ID" tracking_id: "Tracking ID"
open_api_clients: open_api_clients:
add_new_client: "Crear un nuevo cliente de API" add_new_client: "Crear un nuevo cliente de API"
@ -1395,7 +1399,7 @@ es:
client_name: "Nombre del cliente" client_name: "Nombre del cliente"
confirmation_required: "Confirmation required" confirmation_required: "Confirmation required"
do_you_really_want_to_delete_this_open_api_client: "¿Desea realmente eliminar este cliente OpenAPI?" do_you_really_want_to_delete_this_open_api_client: "¿Desea realmente eliminar este cliente OpenAPI?"
do_you_really_want_to_revoke_this_open_api_access: "¿Realmente desea revocar este acceso? Se borrará y reemplazará el token actual." do_you_really_want_to_revoke_this_open_api_access: "Do you really want to revoke this access? It will erase and replace the current token."
client_successfully_created: "Cliente creado correctamente." client_successfully_created: "Cliente creado correctamente."
client_successfully_updated: "Cliente actualizado correctamente." client_successfully_updated: "Cliente actualizado correctamente."
client_successfully_deleted: "Cliente borrado correctamente." client_successfully_deleted: "Cliente borrado correctamente."

View File

@ -24,7 +24,7 @@ fr:
ongoing_reservations: "Réservations en cours" ongoing_reservations: "Réservations en cours"
without_reservation: "Sans réservation" without_reservation: "Sans réservation"
confirmation_required: "Confirmation requise" confirmation_required: "Confirmation requise"
do_you_really_want_to_cancel_the_USER_s_reservation_the_DATE_at_TIME_concerning_RESERVATION: "Êtes-vous {GENDER, select, female{sûre} other{sûr}} de vouloir annuler la réservation de {USER}, le {DATE} à {TIME}, concernant {RESERVATION} ?" do_you_really_want_to_cancel_the_USER_s_reservation_the_DATE_at_TIME_concerning_RESERVATION: "Voulez-vous vraiment annuler la réservation de {USER}, le {DATE} à {TIME}, concernant {RESERVATION} ?"
reservation_was_successfully_cancelled: "La réservation a bien été annulée." reservation_was_successfully_cancelled: "La réservation a bien été annulée."
reservation_cancellation_failed: "L'annulation de la réservation a échouée." reservation_cancellation_failed: "L'annulation de la réservation a échouée."
unable_to_remove_the_last_machine_of_the_slot_delete_the_slot_rather: "Impossible de supprimer la dernière machine du créneau. Supprimez plutôt le créneau." unable_to_remove_the_last_machine_of_the_slot_delete_the_slot_rather: "Impossible de supprimer la dernière machine du créneau. Supprimez plutôt le créneau."
@ -271,7 +271,7 @@ fr:
events_edit: events_edit:
edit_the_event: "Éditer lévénement" edit_the_event: "Éditer lévénement"
confirmation_required: "Confirmation requise" confirmation_required: "Confirmation requise"
edit_recurring_event: "Vous êtes sur le point de modifier un événement périodique. Que voulez-vous modifier ?" edit_recurring_event: "Vous êtes sur le point de mettre à jour un événement périodique. Que voulez-vous mettre à jour ?"
edit_this_event: "Uniquement cet événement" edit_this_event: "Uniquement cet événement"
edit_this_and_next: "Cet événement et tous les suivants" edit_this_and_next: "Cet événement et tous les suivants"
edit_all: "Tous les événements" edit_all: "Tous les événements"
@ -673,6 +673,10 @@ fr:
general_space_code: "Code comptable pour tous les espaces" general_space_code: "Code comptable pour tous les espaces"
accounting_Space_label: "Libellé espaces" accounting_Space_label: "Libellé espaces"
general_space_label: "Libellé du compte pour tous les espaces" general_space_label: "Libellé du compte pour tous les espaces"
accounting_Pack_code: "Code pack prépayé"
general_pack_code: "Code comptable pour tous les packs prépayés"
accounting_Pack_label: "Libellé pack prépayé"
general_pack_label: "Libellé du compte pour tous les packs prépayés"
accounting_Error_code: "Code erreurs" accounting_Error_code: "Code erreurs"
general_error_code: "Code comptable pour les factures en erreur" general_error_code: "Code comptable pour les factures en erreur"
accounting_Error_label: "Libellé erreurs" accounting_Error_label: "Libellé erreurs"
@ -983,7 +987,7 @@ fr:
#add a new administrator to the platform #add a new administrator to the platform
admins_new: admins_new:
add_an_administrator: "Ajouter un administrateur" add_an_administrator: "Ajouter un administrateur"
administrator_successfully_created_he_will_receive_his_connection_directives_by_email: "L'administrateur a bien été créé. {GENDER, select, female{Elle} other{Il}} recevra ses instructions de connexion par email." administrator_successfully_created_he_will_receive_his_connection_directives_by_email: "Création réussie. Les directives de connexion ont été envoyées à l'administrateur par e-mail."
failed_to_create_admin: "Impossible de créer l'administrateur :" failed_to_create_admin: "Impossible de créer l'administrateur :"
man: "Homme" man: "Homme"
woman: "Femme" woman: "Femme"
@ -1001,7 +1005,7 @@ fr:
#add a new manager to the platform #add a new manager to the platform
manager_new: manager_new:
add_a_manager: "Ajouter un gestionnaire" add_a_manager: "Ajouter un gestionnaire"
manager_successfully_created: "Le gestionnaire a bien été créé. {GENDER, select, female{Elle} other{Il}} recevra ses instructions de connexion par courriel." manager_successfully_created: "Création réussie. Les directives de connexion ont été envoyées au nouveau gestionnaire par e-mail."
failed_to_create_manager: "Impossible de créer le gestionnaire :" failed_to_create_manager: "Impossible de créer le gestionnaire :"
man: "Homme" man: "Homme"
woman: "Femme" woman: "Femme"
@ -1381,7 +1385,7 @@ fr:
online_payment: "Le module de paiement par carte bancaire est-il actif ?" online_payment: "Le module de paiement par carte bancaire est-il actif ?"
invoices: "Le module est facturation est-il actif ?" invoices: "Le module est facturation est-il actif ?"
openlab: "Le module de partage de projets (OpenLab) est-il actif ?" openlab: "Le module de partage de projets (OpenLab) est-il actif ?"
tracking_id_info_html: "<p>Pour activer les suivi statistique des visites utilisant Google Analytics, définissez ici votre ID de suivi. Il se présente sous la forme UA-000000-2. Visitez <a href='https://analytics.google.com/analytics/web/' target='_blank'>le site web de Google Analytics</a> pour en obtenir un.<br/><strong>Attention :</strong> si vous activez cette fonctionnalité, pensez à l'indiquer dans votre politique de confidentialité, ci-dessus.</p><p>Le nom d'hôte est également requis pour pouvoir utiliser Google Analytics. Vous pouvez l'obtenir en cliquant sur le bouton adjacent. Ce dernier paramètre est utilisé ailleurs, veuillez le définir avec soin.</p>" tracking_id_info_html: "Pour activer les suivi statistique des visites utilisant Google Analytics V4, définissez ici votre ID de suivi. Il se présente sous la forme G-XXXXXX. Visitez <a href='https://analytics.google.com/analytics/web/' target='_blank'>le site web de Google Analytics</a> pour en obtenir un.<br/><strong>Attention :</strong> si vous activez cette fonctionnalité, une cookie sera créé. Pensez à l'indiquer dans votre politique de confidentialité, ci-dessus."
tracking_id: "ID de suivi" tracking_id: "ID de suivi"
open_api_clients: open_api_clients:
add_new_client: "Créer un compte client" add_new_client: "Créer un compte client"

View File

@ -24,7 +24,7 @@
ongoing_reservations: "Pågående reservasjoner" ongoing_reservations: "Pågående reservasjoner"
without_reservation: "Ikke reservert" without_reservation: "Ikke reservert"
confirmation_required: "Bekreftelse nødvendig" confirmation_required: "Bekreftelse nødvendig"
do_you_really_want_to_cancel_the_USER_s_reservation_the_DATE_at_TIME_concerning_RESERVATION: "{GENDER, select, other {Ønsker du å}} kansellere {USER} sin reservasjon {DATE}, {TIME} for {RESERVATION}?" do_you_really_want_to_cancel_the_USER_s_reservation_the_DATE_at_TIME_concerning_RESERVATION: "Ønsker du å kansellere {USER} sin reservasjon {DATE}, {TIME} for {RESERVATION}?"
reservation_was_successfully_cancelled: "Kansellering av reservasjon er gjennomført." reservation_was_successfully_cancelled: "Kansellering av reservasjon er gjennomført."
reservation_cancellation_failed: "Det gikk ikke an å kansellere reservasjonen." reservation_cancellation_failed: "Det gikk ikke an å kansellere reservasjonen."
unable_to_remove_the_last_machine_of_the_slot_delete_the_slot_rather: "Kan ikke fjerne siste maskinen fra reservasjonen. Slett reservasjonen." unable_to_remove_the_last_machine_of_the_slot_delete_the_slot_rather: "Kan ikke fjerne siste maskinen fra reservasjonen. Slett reservasjonen."
@ -325,7 +325,7 @@
an_error_occurred_unable_to_find_the_credit_to_revoke: "En feil oppstod: kunne ikke finne kreditten som skal tilbakekalles." an_error_occurred_unable_to_find_the_credit_to_revoke: "En feil oppstod: kunne ikke finne kreditten som skal tilbakekalles."
an_error_occurred_while_creating_credit_with_the_TRAINING: "Det oppstod en feil under oppretting av kreditt med {TRAINING}." an_error_occurred_while_creating_credit_with_the_TRAINING: "Det oppstod en feil under oppretting av kreditt med {TRAINING}."
not_set: "Ikke angitt" not_set: "Ikke angitt"
error_a_credit_linking_this_machine_with_that_subscription_already_exists: "Feil : en kreditnota på denne maskinen med dette abonnementet finnes allerede." error_a_credit_linking_this_machine_with_that_subscription_already_exists: "Feil: en kreditnota på denne maskinen med dette abonnementet finnes allerede."
changes_have_been_successfully_saved: "Endringene er lagret." changes_have_been_successfully_saved: "Endringene er lagret."
credit_was_successfully_saved: "Kreditten ble lagret." credit_was_successfully_saved: "Kreditten ble lagret."
error_creating_credit: "Kan ikke opprette kreditt, feil oppstod" error_creating_credit: "Kan ikke opprette kreditt, feil oppstod"
@ -365,7 +365,7 @@
these_prices_match_space_hours_rates_html: "Prisene under samsvarer med en time maskinbruk <strong>uten abonnement</strong>." these_prices_match_space_hours_rates_html: "Prisene under samsvarer med en time maskinbruk <strong>uten abonnement</strong>."
add_a_space_credit: "Legg til en plass/romkreditt" add_a_space_credit: "Legg til en plass/romkreditt"
space: "Plass/rom" space: "Plass/rom"
error_a_credit_linking_this_space_with_that_subscription_already_exists: "Feil : en kreditnota på denne maskinen med dette abonnementet finnes allerede." error_a_credit_linking_this_space_with_that_subscription_already_exists: "Feil: en kreditnota på denne maskinen med dette abonnementet finnes allerede."
status_enabled: "Aktivert" status_enabled: "Aktivert"
status_disabled: "Deaktivert" status_disabled: "Deaktivert"
status_all: "Alle" status_all: "Alle"
@ -673,6 +673,10 @@
general_space_code: "Regnskapskode for plasser/rom" general_space_code: "Regnskapskode for plasser/rom"
accounting_Space_label: "Etikett, plasser/rom" accounting_Space_label: "Etikett, plasser/rom"
general_space_label: "Regnskapskode for alle plasser/rom" general_space_label: "Regnskapskode for alle plasser/rom"
accounting_Pack_code: "Prepaid-pack code"
general_pack_code: "Accounting code for prepaid-packs"
accounting_Pack_label: "Prepaid-pack label"
general_pack_label: "Account label for prepaid-packs"
accounting_Error_code: "Kode for feil" accounting_Error_code: "Kode for feil"
general_error_code: "Regnskapskode for fakturafeil" general_error_code: "Regnskapskode for fakturafeil"
accounting_Error_label: "Etikett for feil" accounting_Error_label: "Etikett for feil"
@ -1295,7 +1299,7 @@
training_reservations: "Trainings" training_reservations: "Trainings"
machine_reservations: "Machines" machine_reservations: "Machines"
space_reservations: "Spaces" space_reservations: "Spaces"
events_reservations: "Events" events_reservations: "Arrangementer"
general: general:
general: "Generelt" general: "Generelt"
title: "Tittel" title: "Tittel"
@ -1322,7 +1326,7 @@
public_registrations_allowed: "Public registrations allowed" public_registrations_allowed: "Public registrations allowed"
help: "Hjelp" help: "Hjelp"
feature_tour: "Funksjonsgjennomgang" feature_tour: "Funksjonsgjennomgang"
feature_tour_info_html: "<p>When an administrator or a manager in logged-in, a feature tour will be triggered the first time he/she visits each section of the application. You can change this behavior to one of the following values:</p><ul><li>« Once » to keep the default behavior.</li><li>« By session » to display the tours each time you reopen the application.</li><li>« Manual trigger » to prevent displaying the tours automatically. It'll still be possible to trigger them by pressing the F1 key or by clicking on « Help » in the user's menu.</li></ul>" feature_tour_info_html: "<p>Når en administrator eller en leder er innlogget En fremvisning utløses første gang han besøker hver del av applikasjonen. Du kan endre denne adferden til en av følgende verdier:</p><ul><li>« Once » for å beholde standardvirkemåten.</li><li>« By session » to display the tours each time you reopen the application.</li><li>« Manual trigger » for å forhindre at turene vises automatisk. Det vil fortsatt være mulig å utløse dem ved å trykke F1-tasten eller ved å klikke på « Hjelp » i brukermenyen.</li></ul>"
feature_tour_display_mode: "Modus for funksjonsgjennomgang" feature_tour_display_mode: "Modus for funksjonsgjennomgang"
display_mode: display_mode:
once: "Én gang" once: "Én gang"
@ -1381,7 +1385,7 @@
online_payment: "Is the online payment module active?" online_payment: "Is the online payment module active?"
invoices: "Is the invoicing module active?" invoices: "Is the invoicing module active?"
openlab: "Is the project sharing module (OpenLab) active?" openlab: "Is the project sharing module (OpenLab) active?"
tracking_id_info_html: "<p>To enable the statistical tracking of the visits using Google Analytics, set your tracking ID here. It is in the form UA-000000-2. Visit <a href='https://analytics.google.com/analytics/web/' target='_blank'>the Google Analytics website</a> to get one.<br/><strong>Warning:</strong> if you enable this feature, remember to write it in your privacy policy, above.</p><p>The host name is also required to use Google Analytics. You can get it by clicking on the adjacent button. This last parameter is used elsewhere, please set it carefully.</p>" tracking_id_info_html: "To enable the statistical tracking of the visits using Google Analytics V4, set your tracking ID here. It is in the form G-XXXXXX. Visit <a href='https://analytics.google.com/analytics/web/' target='_blank'>the Google Analytics website</a> to get one.<br/><strong>Warning:</strong> if you enable this feature, a cookie will be created. Remember to write it down in your privacy policy, above."
tracking_id: "Tracking ID" tracking_id: "Tracking ID"
open_api_clients: open_api_clients:
add_new_client: "Lage ny API-klient" add_new_client: "Lage ny API-klient"
@ -1395,7 +1399,7 @@
client_name: "Klientens navn" client_name: "Klientens navn"
confirmation_required: "Confirmation required" confirmation_required: "Confirmation required"
do_you_really_want_to_delete_this_open_api_client: "Do you really want to delete this OpenAPI client?" do_you_really_want_to_delete_this_open_api_client: "Do you really want to delete this OpenAPI client?"
do_you_really_want_to_revoke_this_open_api_access: "Do you really want to revoke this access ? It will erase and replace the current token." do_you_really_want_to_revoke_this_open_api_access: "Do you really want to revoke this access? It will erase and replace the current token."
client_successfully_created: "Client successfully created." client_successfully_created: "Client successfully created."
client_successfully_updated: "Client successfully updated." client_successfully_updated: "Client successfully updated."
client_successfully_deleted: "Client successfully deleted." client_successfully_deleted: "Client successfully deleted."
@ -1595,7 +1599,7 @@
content: "Create and manage promotional coupons allowing to offer punctual discounts to their holders." content: "Create and manage promotional coupons allowing to offer punctual discounts to their holders."
events: events:
welcome: welcome:
title: "Events" title: "Arrangementer"
content: "Create events, track their reservations and organize them from this page." content: "Create events, track their reservations and organize them from this page."
list: list:
title: "The events" title: "The events"

View File

@ -15,7 +15,7 @@ pt:
trainings: "Treinamentos" trainings: "Treinamentos"
machines: "Máquinas" machines: "Máquinas"
spaces: "Espaços" spaces: "Espaços"
events: "Eventos" events: "Events"
availabilities: "Disponíveis" availabilities: "Disponíveis"
availabilities_notice: "Exportar para Excel livro com todos os slots disponíveis para reserva, e suas ocupações." availabilities_notice: "Exportar para Excel livro com todos os slots disponíveis para reserva, e suas ocupações."
info: "Informações" info: "Informações"
@ -24,7 +24,7 @@ pt:
ongoing_reservations: "Reservas em curso" ongoing_reservations: "Reservas em curso"
without_reservation: "Sem reservas" without_reservation: "Sem reservas"
confirmation_required: "Confirmação Obrigatória" confirmation_required: "Confirmação Obrigatória"
do_you_really_want_to_cancel_the_USER_s_reservation_the_DATE_at_TIME_concerning_RESERVATION: "Você realmente deseja cancelar a reserva do usuário {USER}, em {DATE} ás {TIME}, sobre {RESERVATION}?" do_you_really_want_to_cancel_the_USER_s_reservation_the_DATE_at_TIME_concerning_RESERVATION: "Realmente deseja cancelar a reserva do usuário {USER}, em {DATE} ás {TIME}, sobre {RESERVATION}?"
reservation_was_successfully_cancelled: "A reserva foi cancelada com sucesso" reservation_was_successfully_cancelled: "A reserva foi cancelada com sucesso"
reservation_cancellation_failed: "Cancelamento da reserva falhou." reservation_cancellation_failed: "Cancelamento da reserva falhou."
unable_to_remove_the_last_machine_of_the_slot_delete_the_slot_rather: "Não é possível remover a última máquina do slot. Delete o slot primeiramente." unable_to_remove_the_last_machine_of_the_slot_delete_the_slot_rather: "Não é possível remover a última máquina do slot. Delete o slot primeiramente."
@ -271,7 +271,7 @@ pt:
events_edit: events_edit:
edit_the_event: "Editar evento" edit_the_event: "Editar evento"
confirmation_required: "Confirmação obrigatória" confirmation_required: "Confirmação obrigatória"
edit_recurring_event: "Você está prestes a atualizar um evento periódico. O que você quer atualizar ?" edit_recurring_event: "Você está prestes a atualizar um evento periódico. O que você quer atualizar?"
edit_this_event: "Apenas este evento" edit_this_event: "Apenas este evento"
edit_this_and_next: "Este evento e os seguintes" edit_this_and_next: "Este evento e os seguintes"
edit_all: "Todos eventos" edit_all: "Todos eventos"
@ -322,10 +322,10 @@ pt:
none: "Vazio" #grammar concordance with training. none: "Vazio" #grammar concordance with training.
an_error_occurred_while_saving_the_number_of_credits: "Um erro ocorreu enquanto era salvo o número de créditos." an_error_occurred_while_saving_the_number_of_credits: "Um erro ocorreu enquanto era salvo o número de créditos."
an_error_occurred_while_deleting_credit_with_the_TRAINING: "Um erro ocorreu enquanto o crédito era deletado do {TRAINING}." an_error_occurred_while_deleting_credit_with_the_TRAINING: "Um erro ocorreu enquanto o crédito era deletado do {TRAINING}."
an_error_occurred_unable_to_find_the_credit_to_revoke: "Um erro ocorreu : incapaz de encontrar o crédito para revogar." an_error_occurred_unable_to_find_the_credit_to_revoke: "An error occurred: unable to find the credit to revoke."
an_error_occurred_while_creating_credit_with_the_TRAINING: "Ocorreu um erro ao criar o crédito com o {TRAINING}." an_error_occurred_while_creating_credit_with_the_TRAINING: "Ocorreu um erro ao criar o crédito com o {TRAINING}."
not_set: "Não definido" not_set: "Não definido"
error_a_credit_linking_this_machine_with_that_subscription_already_exists: "Erro : um link de crédito entre esta máquina e esta assinatura já existe." error_a_credit_linking_this_machine_with_that_subscription_already_exists: "Erro: uma conexão de crédito entre esta máquina e esta assinatura já existe."
changes_have_been_successfully_saved: "As modificações foram salvas com sucesso." changes_have_been_successfully_saved: "As modificações foram salvas com sucesso."
credit_was_successfully_saved: "Crédito salvo com sucesso." credit_was_successfully_saved: "Crédito salvo com sucesso."
error_creating_credit: "Não foi possível criar crédito, um erro ocorreu" error_creating_credit: "Não foi possível criar crédito, um erro ocorreu"
@ -673,6 +673,10 @@ pt:
general_space_code: "Código de contabilidade para todos os espaços" general_space_code: "Código de contabilidade para todos os espaços"
accounting_Space_label: "Rótulo de espaços" accounting_Space_label: "Rótulo de espaços"
general_space_label: "Rótulo de conta para todos os espaços" general_space_label: "Rótulo de conta para todos os espaços"
accounting_Pack_code: "Prepaid-pack code"
general_pack_code: "Accounting code for prepaid-packs"
accounting_Pack_label: "Prepaid-pack label"
general_pack_label: "Account label for prepaid-packs"
accounting_Error_code: "Código do erro" accounting_Error_code: "Código do erro"
general_error_code: "Código de contabilidade para faturas erradas" general_error_code: "Código de contabilidade para faturas erradas"
accounting_Error_label: "Rótulo dos erros" accounting_Error_label: "Rótulo dos erros"
@ -983,7 +987,7 @@ pt:
#add a new administrator to the platform #add a new administrator to the platform
admins_new: admins_new:
add_an_administrator: "Adicionar administrador" add_an_administrator: "Adicionar administrador"
administrator_successfully_created_he_will_receive_his_connection_directives_by_email: "Administrator criado com sucesso. {GENDER, select, female{Ela} other{Ele}} receberá {GENDER, select, female{sua} other{seu}} diretivas de conexão por e-mail." administrator_successfully_created_he_will_receive_his_connection_directives_by_email: "Successful creation. Connection directives were sent to the new administrator by e-mail."
failed_to_create_admin: "Não é possível criar administrador:" failed_to_create_admin: "Não é possível criar administrador:"
man: "Homem" man: "Homem"
woman: "Mulher" woman: "Mulher"
@ -1001,7 +1005,7 @@ pt:
#add a new manager to the platform #add a new manager to the platform
manager_new: manager_new:
add_a_manager: "Adicionar Gestor" add_a_manager: "Adicionar Gestor"
manager_successfully_created: "Gerente criado com sucesso. {GENDER, select, female{Ela} other{Ele}} receberá {GENDER, select, female{Suas diretrizes de conexão por e-mail} other{Suas diretrizes de conexão por e-mail}}" manager_successfully_created: "Successful creation. Connection directives were sent to the new manager by e-mail."
failed_to_create_manager: "Não foi possível criar o gerente:" failed_to_create_manager: "Não foi possível criar o gerente:"
man: "Homem" man: "Homem"
woman: "Mulher" woman: "Mulher"
@ -1032,7 +1036,7 @@ pt:
oauth2_provider_successfully_added: "Provedor OAuth 2.0 adicionado com sucesso." oauth2_provider_successfully_added: "Provedor OAuth 2.0 adicionado com sucesso."
#edit an authentication provider (SSO) #edit an authentication provider (SSO)
authentication_edit: authentication_edit:
provider: "Provedor :" provider: "Provedor:"
it_is_required_to_set_the_matching_between_User.uid_and_the_API_to_add_this_provider: "É necessário definir a correspondência entre User.uid ea API para adicionar este fornecedor." it_is_required_to_set_the_matching_between_User.uid_and_the_API_to_add_this_provider: "É necessário definir a correspondência entre User.uid ea API para adicionar este fornecedor."
provider_successfully_updated: "Provedor modificado com sucesso." provider_successfully_updated: "Provedor modificado com sucesso."
an_error_occurred_unable_to_update_the_provider: "Um erro ocorreu: não é possível atualizar provedor." an_error_occurred_unable_to_update_the_provider: "Um erro ocorreu: não é possível atualizar provedor."
@ -1322,7 +1326,7 @@ pt:
public_registrations_allowed: "Public registrations allowed" public_registrations_allowed: "Public registrations allowed"
help: "Ajuda" help: "Ajuda"
feature_tour: "Tour de recursos" feature_tour: "Tour de recursos"
feature_tour_info_html: "<p>Quando um administrador ou um gerente está logado, um tour de recurso será acionado na primeira vez que ele/ela visita cada seção do aplicativo. Você pode mudar esse comportamento para um dos seguintes valores:</p><ul><li>« Uma vez » para manter o comportamento padrão.</li><li>« Por sessão » para exibir os tours cada vez que você reabrir o aplicativo.</li><li>« Ativação manual » para evitar a exibição automática dos tours. Ainda será possível ativá-los pressionando a tecla F1 ou clicando em « Ajuda » no menu do usuário.</li></ul>" feature_tour_info_html: "<p>Quando um administrador ou um gerente está logado, um tour de recurso será acionado na primeira vez que ele visita cada seção do aplicativo. Você pode mudar esse comportamento para um dos seguintes valores:</p><ul><li>« Uma vez » para manter o comportamento padrão.</li><li>« Por sessão » para exibir os tours cada vez que você reabrir o aplicativo.</li><li>« Ativação manual » para evitar a exibição automática dos tours. Ainda será possível ativá-los pressionando a tecla F1 ou clicando em « Ajuda » no menu do usuário.</li></ul>"
feature_tour_display_mode: "Modo de exibição de recursos do tour" feature_tour_display_mode: "Modo de exibição de recursos do tour"
display_mode: display_mode:
once: "Uma vez" once: "Uma vez"
@ -1381,7 +1385,7 @@ pt:
online_payment: "O módulo de pagamento online está ativo?" online_payment: "O módulo de pagamento online está ativo?"
invoices: "O módulo de faturação está ativo?" invoices: "O módulo de faturação está ativo?"
openlab: "O módulo de compartilhamento de projetos (OpenLab) está ativo?" openlab: "O módulo de compartilhamento de projetos (OpenLab) está ativo?"
tracking_id_info_html: "<p>Para ativar o rastreamento estatístico das visitas usando o Google Analytics, defina seu ID de rastreamento aqui. Está na forma de UA-000000-2. Visite <a href='https://analytics.google.com/analytics/web/' target='_blank'>o site do Google Analytics</a> para obter um.<br/><strong>Aviso:</strong> se você ativar este recurso, lembre-se de escrevê-lo na sua política de privacidade.</p><p>O nome do host também é necessário para usar o Google Analytics. Você pode obtê-lo clicando no botão adjacente. Este último parâmetro é usado em outro lugar, por favor, defina-o com cuidado.</p>" tracking_id_info_html: "Para ativar o rastreamento estatístico das visitas usando o Google Analytics, defina seu ID de rastreamento aqui. Está na forma de G-XXXXXX. Visite <a href='https://analytics.google.com/analytics/web/' target='_blank'>o site do Google Analytics</a> para obter um.<br/><strong>Aviso:</strong> se você ativar este recurso, um cookie será criado. Lembre-se de escrevê-lo na sua política de privacidade."
tracking_id: "ID de rastreamento" tracking_id: "ID de rastreamento"
open_api_clients: open_api_clients:
add_new_client: "Criar novo cliente de API" add_new_client: "Criar novo cliente de API"

View File

@ -15,7 +15,7 @@ zu:
trainings: "crwdns6709:0crwdne6709:0" trainings: "crwdns6709:0crwdne6709:0"
machines: "crwdns6711:0crwdne6711:0" machines: "crwdns6711:0crwdne6711:0"
spaces: "crwdns6713:0crwdne6713:0" spaces: "crwdns6713:0crwdne6713:0"
events: "crwdns6715:0crwdne6715:0" events: "crwdns22406:0crwdne22406:0"
availabilities: "crwdns6717:0crwdne6717:0" availabilities: "crwdns6717:0crwdne6717:0"
availabilities_notice: "crwdns6719:0crwdne6719:0" availabilities_notice: "crwdns6719:0crwdne6719:0"
info: "crwdns20468:0crwdne20468:0" info: "crwdns20468:0crwdne20468:0"
@ -24,7 +24,7 @@ zu:
ongoing_reservations: "crwdns6721:0crwdne6721:0" ongoing_reservations: "crwdns6721:0crwdne6721:0"
without_reservation: "crwdns20326:0crwdne20326:0" without_reservation: "crwdns20326:0crwdne20326:0"
confirmation_required: "crwdns6725:0crwdne6725:0" confirmation_required: "crwdns6725:0crwdne6725:0"
do_you_really_want_to_cancel_the_USER_s_reservation_the_DATE_at_TIME_concerning_RESERVATION: "crwdns20296:0GENDER={GENDER}crwdnd20296:0USER={USER}crwdnd20296:0DATE={DATE}crwdnd20296:0TIME={TIME}crwdnd20296:0RESERVATION={RESERVATION}crwdne20296:0" do_you_really_want_to_cancel_the_USER_s_reservation_the_DATE_at_TIME_concerning_RESERVATION: "crwdns22408:0{USER}crwdnd22408:0{DATE}crwdnd22408:0{TIME}crwdnd22408:0{RESERVATION}crwdne22408:0"
reservation_was_successfully_cancelled: "crwdns6729:0crwdne6729:0" reservation_was_successfully_cancelled: "crwdns6729:0crwdne6729:0"
reservation_cancellation_failed: "crwdns6731:0crwdne6731:0" reservation_cancellation_failed: "crwdns6731:0crwdne6731:0"
unable_to_remove_the_last_machine_of_the_slot_delete_the_slot_rather: "crwdns6733:0crwdne6733:0" unable_to_remove_the_last_machine_of_the_slot_delete_the_slot_rather: "crwdns6733:0crwdne6733:0"
@ -271,7 +271,7 @@ zu:
events_edit: events_edit:
edit_the_event: "crwdns7095:0crwdne7095:0" edit_the_event: "crwdns7095:0crwdne7095:0"
confirmation_required: "crwdns19784:0crwdne19784:0" confirmation_required: "crwdns19784:0crwdne19784:0"
edit_recurring_event: "crwdns19786:0crwdne19786:0" edit_recurring_event: "crwdns22410:0crwdne22410:0"
edit_this_event: "crwdns19788:0crwdne19788:0" edit_this_event: "crwdns19788:0crwdne19788:0"
edit_this_and_next: "crwdns19790:0crwdne19790:0" edit_this_and_next: "crwdns19790:0crwdne19790:0"
edit_all: "crwdns19792:0crwdne19792:0" edit_all: "crwdns19792:0crwdne19792:0"
@ -322,10 +322,10 @@ zu:
none: "crwdns19808:0crwdne19808:0" #grammar concordance with training. none: "crwdns19808:0crwdne19808:0" #grammar concordance with training.
an_error_occurred_while_saving_the_number_of_credits: "crwdns7173:0crwdne7173:0" an_error_occurred_while_saving_the_number_of_credits: "crwdns7173:0crwdne7173:0"
an_error_occurred_while_deleting_credit_with_the_TRAINING: "crwdns7175:0{TRAINING}crwdne7175:0" an_error_occurred_while_deleting_credit_with_the_TRAINING: "crwdns7175:0{TRAINING}crwdne7175:0"
an_error_occurred_unable_to_find_the_credit_to_revoke: "crwdns7177:0crwdne7177:0" an_error_occurred_unable_to_find_the_credit_to_revoke: "crwdns22412:0crwdne22412:0"
an_error_occurred_while_creating_credit_with_the_TRAINING: "crwdns7179:0{TRAINING}crwdne7179:0" an_error_occurred_while_creating_credit_with_the_TRAINING: "crwdns7179:0{TRAINING}crwdne7179:0"
not_set: "crwdns7181:0crwdne7181:0" not_set: "crwdns7181:0crwdne7181:0"
error_a_credit_linking_this_machine_with_that_subscription_already_exists: "crwdns7183:0crwdne7183:0" error_a_credit_linking_this_machine_with_that_subscription_already_exists: "crwdns22414:0crwdne22414:0"
changes_have_been_successfully_saved: "crwdns7185:0crwdne7185:0" changes_have_been_successfully_saved: "crwdns7185:0crwdne7185:0"
credit_was_successfully_saved: "crwdns7187:0crwdne7187:0" credit_was_successfully_saved: "crwdns7187:0crwdne7187:0"
error_creating_credit: "crwdns7189:0crwdne7189:0" error_creating_credit: "crwdns7189:0crwdne7189:0"
@ -365,7 +365,7 @@ zu:
these_prices_match_space_hours_rates_html: "crwdns20480:0crwdne20480:0" these_prices_match_space_hours_rates_html: "crwdns20480:0crwdne20480:0"
add_a_space_credit: "crwdns7259:0crwdne7259:0" add_a_space_credit: "crwdns7259:0crwdne7259:0"
space: "crwdns7261:0crwdne7261:0" space: "crwdns7261:0crwdne7261:0"
error_a_credit_linking_this_space_with_that_subscription_already_exists: "crwdns7263:0crwdne7263:0" error_a_credit_linking_this_space_with_that_subscription_already_exists: "crwdns22416:0crwdne22416:0"
status_enabled: "crwdns7265:0crwdne7265:0" status_enabled: "crwdns7265:0crwdne7265:0"
status_disabled: "crwdns7267:0crwdne7267:0" status_disabled: "crwdns7267:0crwdne7267:0"
status_all: "crwdns7269:0crwdne7269:0" status_all: "crwdns7269:0crwdne7269:0"
@ -482,7 +482,7 @@ zu:
no_invoices_for_now: "crwdns7337:0crwdne7337:0" no_invoices_for_now: "crwdns7337:0crwdne7337:0"
payment_schedules_list: "crwdns21058:0crwdne21058:0" payment_schedules_list: "crwdns21058:0crwdne21058:0"
invoicing_settings: "crwdns7339:0crwdne7339:0" invoicing_settings: "crwdns7339:0crwdne7339:0"
warning_invoices_disabled: "crwdns7341:0crwdne7341:0" warning_invoices_disabled: "crwdns22418:0crwdne22418:0"
change_logo: "crwdns7343:0crwdne7343:0" change_logo: "crwdns7343:0crwdne7343:0"
john_smith: "crwdns7345:0crwdne7345:0" john_smith: "crwdns7345:0crwdne7345:0"
john_smith_at_example_com: "crwdns7347:0crwdne7347:0" john_smith_at_example_com: "crwdns7347:0crwdne7347:0"
@ -673,6 +673,10 @@ zu:
general_space_code: "crwdns7677:0crwdne7677:0" general_space_code: "crwdns7677:0crwdne7677:0"
accounting_Space_label: "crwdns7679:0crwdne7679:0" accounting_Space_label: "crwdns7679:0crwdne7679:0"
general_space_label: "crwdns7681:0crwdne7681:0" general_space_label: "crwdns7681:0crwdne7681:0"
accounting_Pack_code: "crwdns22446:0crwdne22446:0"
general_pack_code: "crwdns22448:0crwdne22448:0"
accounting_Pack_label: "crwdns22450:0crwdne22450:0"
general_pack_label: "crwdns22452:0crwdne22452:0"
accounting_Error_code: "crwdns21470:0crwdne21470:0" accounting_Error_code: "crwdns21470:0crwdne21470:0"
general_error_code: "crwdns21472:0crwdne21472:0" general_error_code: "crwdns21472:0crwdne21472:0"
accounting_Error_label: "crwdns21474:0crwdne21474:0" accounting_Error_label: "crwdns21474:0crwdne21474:0"
@ -983,7 +987,7 @@ zu:
#add a new administrator to the platform #add a new administrator to the platform
admins_new: admins_new:
add_an_administrator: "crwdns8027:0crwdne8027:0" add_an_administrator: "crwdns8027:0crwdne8027:0"
administrator_successfully_created_he_will_receive_his_connection_directives_by_email: "crwdns8029:0GENDER={GENDER}crwdnd8029:0GENDER={GENDER}crwdne8029:0" administrator_successfully_created_he_will_receive_his_connection_directives_by_email: "crwdns22420:0crwdne22420:0"
failed_to_create_admin: "crwdns8031:0crwdne8031:0" failed_to_create_admin: "crwdns8031:0crwdne8031:0"
man: "crwdns8033:0crwdne8033:0" man: "crwdns8033:0crwdne8033:0"
woman: "crwdns8035:0crwdne8035:0" woman: "crwdns8035:0crwdne8035:0"
@ -1001,7 +1005,7 @@ zu:
#add a new manager to the platform #add a new manager to the platform
manager_new: manager_new:
add_a_manager: "crwdns20348:0crwdne20348:0" add_a_manager: "crwdns20348:0crwdne20348:0"
manager_successfully_created: "crwdns20350:0GENDER={GENDER}crwdnd20350:0GENDER={GENDER}crwdne20350:0" manager_successfully_created: "crwdns22422:0crwdne22422:0"
failed_to_create_manager: "crwdns20352:0crwdne20352:0" failed_to_create_manager: "crwdns20352:0crwdne20352:0"
man: "crwdns20354:0crwdne20354:0" man: "crwdns20354:0crwdne20354:0"
woman: "crwdns20356:0crwdne20356:0" woman: "crwdns20356:0crwdne20356:0"
@ -1032,7 +1036,7 @@ zu:
oauth2_provider_successfully_added: "crwdns8081:0crwdne8081:0" oauth2_provider_successfully_added: "crwdns8081:0crwdne8081:0"
#edit an authentication provider (SSO) #edit an authentication provider (SSO)
authentication_edit: authentication_edit:
provider: "crwdns8083:0crwdne8083:0" provider: "crwdns22424:0crwdne22424:0"
it_is_required_to_set_the_matching_between_User.uid_and_the_API_to_add_this_provider: "crwdns20208:0crwdne20208:0" it_is_required_to_set_the_matching_between_User.uid_and_the_API_to_add_this_provider: "crwdns20208:0crwdne20208:0"
provider_successfully_updated: "crwdns20210:0crwdne20210:0" provider_successfully_updated: "crwdns20210:0crwdne20210:0"
an_error_occurred_unable_to_update_the_provider: "crwdns8089:0crwdne8089:0" an_error_occurred_unable_to_update_the_provider: "crwdns8089:0crwdne8089:0"
@ -1322,7 +1326,7 @@ zu:
public_registrations_allowed: "crwdns22283:0crwdne22283:0" public_registrations_allowed: "crwdns22283:0crwdne22283:0"
help: "crwdns20764:0crwdne20764:0" help: "crwdns20764:0crwdne20764:0"
feature_tour: "crwdns20766:0crwdne20766:0" feature_tour: "crwdns20766:0crwdne20766:0"
feature_tour_info_html: "crwdns20768:0crwdne20768:0" feature_tour_info_html: "crwdns22426:0crwdne22426:0"
feature_tour_display_mode: "crwdns20770:0crwdne20770:0" feature_tour_display_mode: "crwdns20770:0crwdne20770:0"
display_mode: display_mode:
once: "crwdns20772:0crwdne20772:0" once: "crwdns20772:0crwdne20772:0"
@ -1381,7 +1385,7 @@ zu:
online_payment: "crwdns19892:0crwdne19892:0" online_payment: "crwdns19892:0crwdne19892:0"
invoices: "crwdns19894:0crwdne19894:0" invoices: "crwdns19894:0crwdne19894:0"
openlab: "crwdns19896:0crwdne19896:0" openlab: "crwdns19896:0crwdne19896:0"
tracking_id_info_html: "crwdns20812:0crwdne20812:0" tracking_id_info_html: "crwdns22442:0crwdne22442:0"
tracking_id: "crwdns20814:0crwdne20814:0" tracking_id: "crwdns20814:0crwdne20814:0"
open_api_clients: open_api_clients:
add_new_client: "crwdns8443:0crwdne8443:0" add_new_client: "crwdns8443:0crwdne8443:0"
@ -1395,7 +1399,7 @@ zu:
client_name: "crwdns8459:0crwdne8459:0" client_name: "crwdns8459:0crwdne8459:0"
confirmation_required: "crwdns8461:0crwdne8461:0" confirmation_required: "crwdns8461:0crwdne8461:0"
do_you_really_want_to_delete_this_open_api_client: "crwdns8463:0crwdne8463:0" do_you_really_want_to_delete_this_open_api_client: "crwdns8463:0crwdne8463:0"
do_you_really_want_to_revoke_this_open_api_access: "crwdns8465:0crwdne8465:0" do_you_really_want_to_revoke_this_open_api_access: "crwdns22428:0crwdne22428:0"
client_successfully_created: "crwdns8467:0crwdne8467:0" client_successfully_created: "crwdns8467:0crwdne8467:0"
client_successfully_updated: "crwdns8469:0crwdne8469:0" client_successfully_updated: "crwdns8469:0crwdne8469:0"
client_successfully_deleted: "crwdns8471:0crwdne8471:0" client_successfully_deleted: "crwdns8471:0crwdne8471:0"

View File

@ -109,10 +109,10 @@ de:
your_previous_trainings: "Ihre vorigen Schulungen" your_previous_trainings: "Ihre vorigen Schulungen"
your_approved_trainings: "Ihre bestätigten Trainings" your_approved_trainings: "Ihre bestätigten Trainings"
no_trainings: "Keine Schulungen" no_trainings: "Keine Schulungen"
your_training_credits: "Your training credits" your_training_credits: "Dein Trainingsguthaben"
subscribe_for_credits: "Subscribe to benefit from free trainings" subscribe_for_credits: "Abonnement abschließen, um kostenlose Schulungen zu erhalten"
register_for_free: "Register for free to the following trainings:" register_for_free: "Melden Sie sich kostenlos für folgende Schulungen an:"
book_here: "Book here" book_here: "Hier buchen"
#dashboard: my events #dashboard: my events
events: events:
your_next_events: "Ihre nächsten Termine" your_next_events: "Ihre nächsten Termine"
@ -132,7 +132,7 @@ de:
payment_schedules: payment_schedules:
no_payment_schedules: "Keine Zahlungspläne zum Anzeigen" no_payment_schedules: "Keine Zahlungspläne zum Anzeigen"
load_more: "Mehr laden" load_more: "Mehr laden"
card_updated_success: "Your card was successfully updated" card_updated_success: "Ihre Karte wurde erfolgreich aktualisiert"
#public profil of a member #public profil of a member
members_show: members_show:
members_list: "Mitgliederliste" members_list: "Mitgliederliste"
@ -173,30 +173,30 @@ de:
DATE_TIME: "{DATE} {TIME}" DATE_TIME: "{DATE} {TIME}"
#modal telling users that they need to pass a training before booking a machine #modal telling users that they need to pass a training before booking a machine
required_training_modal: required_training_modal:
to_book_MACHINE_requires_TRAINING_html: "To book the \"{MACHINE}\" you must have completed the training <strong>{TRAINING}</strong>." to_book_MACHINE_requires_TRAINING_html: "Um \"{MACHINE}\" zu buchen, müssen Sie <strong>{TRAINING}</strong> abgeschlossen haben."
training_or_training_html: "</strong> or the training <strong>" training_or_training_html: "</strong> oder die Schulung <strong>"
enroll_now: "Zur Schulung anmelden" enroll_now: "Zur Schulung anmelden"
no_enroll_for_now: "Ich möchte mich jetzt nicht anmelden" no_enroll_for_now: "Ich möchte mich jetzt nicht anmelden"
close: "Schließen" close: "Schließen"
propose_packs_modal: propose_packs_modal:
available_packs: "Prepaid packs available" available_packs: "Prepaid-Pakete verfügbar"
packs_proposed: "You can buy a prepaid pack of hours for this machine. These packs allows you to benefit from volume discounts." packs_proposed: "Sie können ein Paket vorausbezahlter Stunden für diese Maschine kaufen. Über diese Pakete können Sie einen Mengenrabatt erhalten."
no_thanks: "Nein, danke" no_thanks: "Nein, danke"
pack_DURATION: "{DURATION} hours" pack_DURATION: "{DURATION} Stunden"
buy_this_pack: "Buy this pack" buy_this_pack: "Dieses Paket kaufen"
pack_bought_success: "You have successfully bought this pack of prepaid-hours. Your invoice will ba available soon from your dashboard." pack_bought_success: "Sie haben erfolgreich dieses Paket vorbezahlter Stunden gekauft. Ihre Rechnung wird bald in Ihrem Dashboard verfügbar sein."
validity: "Usable for {COUNT} {PERIODS}" validity: "Verwendbar für {COUNT} {PERIODS}"
period: period:
day: "{COUNT, plural, one{day} other{days}}" day: "{COUNT, plural, one {Tag} other {Tage}}"
week: "{COUNT, plural, one{week} other{weeks}}" week: "{COUNT, plural, one{Woche} other{Wochen}}"
month: "{COUNT, plural, one{month} other{months}}" month: "{COUNT, plural, one{Monat} other{Monate}}"
year: "{COUNT, plural, one{year} other{years}}" year: "{COUNT, plural, one {Jahr} other {Jahre}}"
packs_summary: packs_summary:
prepaid_hours: "Prepaid hours" prepaid_hours: "Vorausbezahlte Stunden"
remaining_HOURS: "You have {HOURS} prepaid hours remaining for this {ITEM, select, Machine{machine} Space{space} other{}}." remaining_HOURS: "Sie haben {HOURS} vorausbezahlte Stunden für {ITEM, select, Machine{diese Maschine} Space{diesen Raum} other{}} übrig."
no_hours: "You don't have any prepaid hours for this {ITEM, select, Machine{machine} Space{space} other{}}." no_hours: "Sie haben keine vorausbezahlte Nutzungsdauer für {ITEM, select, Machine{diese Maschine} Space{diesen Raum} other{}}."
buy_a_new_pack: "Buy a new pack" buy_a_new_pack: "Ein neues Paket kaufen"
unable_to_use_pack_for_subsription_is_expired: "You must have a valid subscription to use your remaining hours." unable_to_use_pack_for_subsription_is_expired: "Sie benötigen für die verbleibenden Stunden ein gültiges Abonnement."
#book a training #book a training
trainings_reserve: trainings_reserve:
trainings_planning: "Schulungsplanung" trainings_planning: "Schulungsplanung"

View File

@ -7,7 +7,7 @@ es:
you_ve_just_created_a_new_account_on_the_fablab_by_logging_from: "Acaba de crear una nueva cuenta en {GENDER, select, male{el} female{la} neutral{} other{las}} {NAME}, al iniciar sesión desde" you_ve_just_created_a_new_account_on_the_fablab_by_logging_from: "Acaba de crear una nueva cuenta en {GENDER, select, male{el} female{la} neutral{} other{las}} {NAME}, al iniciar sesión desde"
we_need_some_more_details: "Para finalizar la configuración de la plataforma, necesitamos algunos detalles más." we_need_some_more_details: "Para finalizar la configuración de la plataforma, necesitamos algunos detalles más."
your_email_is_already_used_by_another_account_on_the_platform: "Parece que su dirección de correo electrónico ya está siendo utilizada por otro usuario. Compruebe su dirección de correo electrónico e ingrese debajo del código que le hemos enviado." your_email_is_already_used_by_another_account_on_the_platform: "Parece que su dirección de correo electrónico ya está siendo utilizada por otro usuario. Compruebe su dirección de correo electrónico e ingrese debajo del código que le hemos enviado."
or: "or" or: "o"
please_fill_the_following_form: "rellene el siguiente formulario, por favor" please_fill_the_following_form: "rellene el siguiente formulario, por favor"
some_data_may_have_already_been_provided_by_provider_and_cannot_be_modified: "Algunos datos pueden haber sido proporcionados ya por {NAME} y no pueden modificarse" some_data_may_have_already_been_provided_by_provider_and_cannot_be_modified: "Algunos datos pueden haber sido proporcionados ya por {NAME} y no pueden modificarse"
then_click_on_: "haz click en" then_click_on_: "haz click en"
@ -25,20 +25,20 @@ es:
an_unexpected_error_occurred_check_your_authentication_code: "Ha ocurrido un error inesperado, por favor, revise su código de autentificación." an_unexpected_error_occurred_check_your_authentication_code: "Ha ocurrido un error inesperado, por favor, revise su código de autentificación."
send_code_again: "Enviar el código de nuevo" send_code_again: "Enviar el código de nuevo"
email_address_associated_with_your_account: "Email asociado con su cuenta" email_address_associated_with_your_account: "Email asociado con su cuenta"
email_is_required: "Email address is required" email_is_required: "Se requiere una dirección de email"
email_format_is_incorrect: "El formato de email incorrecto" email_format_is_incorrect: "El formato de email incorrecto"
code_successfully_sent_again: "El mail ha sido enviado otra vez con éxito" code_successfully_sent_again: "El mail ha sido enviado otra vez con éxito"
used_for_statistics: "This data will be used for statistical purposes" used_for_statistics: "Estos datos se utilizarán para fines estadísticos"
your_user_s_profile: "Your user's profile" your_user_s_profile: "Perfil de tu usuario"
user_s_profile_is_required: "User's profile is required." user_s_profile_is_required: "Se requiere perfil de usuario."
i_ve_read_and_i_accept_: "I've read and I accept" i_ve_read_and_i_accept_: "He leído y acepto"
_the_fablab_policy: "the FabLab policy" _the_fablab_policy: "la política de FabLab"
change_my_data: "Change my data" change_my_data: "Cambiar mis datos"
sync_my_profile: "Sync my profile" sync_my_profile: "Sincronizar mi perfil"
once_your_data_are_up_to_date_: "Once your data are up to date," once_your_data_are_up_to_date_: "Una vez sus datos hayan sido actualizados,"
_click_on_the_synchronization_button_opposite_: "click on the synchronization button opposite" _click_on_the_synchronization_button_opposite_: "haga clic en el botón de sincronización"
_disconnect_then_reconnect_: "disconnect then reconnect" _disconnect_then_reconnect_: "desconectar y volver a conectar"
_for_your_changes_to_take_effect: "for your changes to take effect." _for_your_changes_to_take_effect: "para que los cambios surtan efecto."
dashboard: dashboard:
#dashboard: public profile #dashboard: public profile
profile: profile:
@ -65,20 +65,20 @@ es:
edit_my_profile: "Editar mi perfil" edit_my_profile: "Editar mi perfil"
your_group_has_been_successfully_changed: "Su grupo ha sido cambiado con exito." your_group_has_been_successfully_changed: "Su grupo ha sido cambiado con exito."
an_unexpected_error_prevented_your_group_from_being_changed: "Un error inesperado impidió que su grupo fuese cambiado." an_unexpected_error_prevented_your_group_from_being_changed: "Un error inesperado impidió que su grupo fuese cambiado."
confirmation_required: "Confirmation required" confirmation_required: "Confirmación requerida"
confirm_delete_your_account: "¿Está seguro de querer eliminar su cuenta?" confirm_delete_your_account: "¿Está seguro de querer eliminar su cuenta?"
all_data_will_be_lost: "All your data will be destroyed and won't be recoverable." all_data_will_be_lost: "Todos tus datos serán destruidos y no serán recuperables."
invoicing_data_kept: "According to regulation, all data related to your invoices will be kept separately for 10 years." invoicing_data_kept: "Según la regulación, todos los datos relacionados con sus facturas se mantendrán por separado durante 10 años."
statistic_data_anonymized: "Some data (sex, date of birth, group) will be anonymized and kept for statistical purposes." statistic_data_anonymized: "Algunos datos (sexo, fecha de nacimiento, grupo) serán anonimizados y conservados con fines estadísticos."
no_further_access_to_projects: "Your published projects will be anonymized and you won't get any further ability to edit them." no_further_access_to_projects: "Tus proyectos publicados serán anónimos y no tendrás más capacidad para editarlos."
your_user_account_has_been_successfully_deleted_goodbye: "Su cuenta ha sido eliminada con éxito. Adiós" your_user_account_has_been_successfully_deleted_goodbye: "Su cuenta ha sido eliminada con éxito. Adiós"
an_error_occured_preventing_your_account_from_being_deleted: "Un error inesperado impidió que su cuenta fuese eliminada." an_error_occured_preventing_your_account_from_being_deleted: "Un error inesperado impidió que su cuenta fuese eliminada."
used_for_statistics: "This data will be used for statistical purposes" used_for_statistics: "Estos datos se utilizarán para fines estadísticos"
used_for_invoicing: "This data will be used for billing purposes" used_for_invoicing: "Estos datos se utilizarán para fines de facturación"
used_for_reservation: "This data will be used in case of change on one of your bookings" used_for_reservation: "Estos datos se utilizarán en caso de cambio en una de sus reservas"
used_for_profile: "This data will only be displayed on your profile" used_for_profile: "Estos datos sólo se mostrarán en tu perfil"
used_for_pricing_stats: "This data will be used to determine the prices to which you are entitled, and for statistical purposes" used_for_pricing_stats: "Estos datos se utilizarán para determinar los precios a los que tiene derecho, y con fines estadísticos"
public_profile: "You will have a public profile and other users will be able to associate you in their projects" public_profile: "Tendrás un perfil público y otros usuarios podrán asociarte en sus proyectos"
trainings: "Cursos" trainings: "Cursos"
no_trainings: "Sin cursos" no_trainings: "Sin cursos"
subscription: "Suscripción" subscription: "Suscripción"
@ -94,32 +94,32 @@ es:
#dashboard: my projects #dashboard: my projects
projects: projects:
you_dont_have_any_projects: "Aún no tiene proyectos." you_dont_have_any_projects: "Aún no tiene proyectos."
add_a_project: "Add a project" add_a_project: "Añadir un proyecto"
author: "Autor" author: "Autor"
collaborator: "Colaborador" collaborator: "Colaborador"
rough_draft: "Draft" rough_draft: "Borrador"
description: "Description" description: "Descripción"
machines_and_materials: "Machines and materials" machines_and_materials: "Máquinas y materiales"
machines: "Machines" machines: "Máquinas"
materials: "Materials" materials: "Materiales"
collaborators: "Collaborators" collaborators: "Colaboradores"
#dashboard: my trainings #dashboard: my trainings
trainings: trainings:
your_next_trainings: "Sus próximos cursos" your_next_trainings: "Sus próximos cursos"
your_previous_trainings: "Sus cursos anteriores" your_previous_trainings: "Sus cursos anteriores"
your_approved_trainings: "Sus cursos aprobados" your_approved_trainings: "Sus cursos aprobados"
no_trainings: "No trainings" no_trainings: "Sin cursos"
your_training_credits: "Your training credits" your_training_credits: "Tus créditos de entrenamiento"
subscribe_for_credits: "Subscribe to benefit from free trainings" subscribe_for_credits: "Suscríbete para beneficiarte de entrenamientos gratuitos"
register_for_free: "Register for free to the following trainings:" register_for_free: "Regístrate gratis en los siguientes entrenamientos:"
book_here: "Book here" book_here: "Reservar aquí"
#dashboard: my events #dashboard: my events
events: events:
your_next_events: "Sus próximos eventos" your_next_events: "Sus próximos eventos"
no_events_to_come: "No hay próximos eventos" no_events_to_come: "No hay próximos eventos"
your_previous_events: "Sus eventos anteriores" your_previous_events: "Sus eventos anteriores"
no_passed_events: "No passed events" no_passed_events: "Sin eventos anteriores"
NUMBER_normal_places_reserved: "{NUMBER} {NUMBER, plural, =0{} =1{normal place reserved} other{normal places reserved}}" NUMBER_normal_places_reserved: "¡{NUMBER} {NUMBER, plural, one {} =0{} =1{lugar normal reservado} other{lugares normales reservados}}"
NUMBER_of_NAME_places_reserved: "{NUMBER} {NUMBER, plural, =0{} =1{of {NAME} place reserved} other{of {NAME} places reserved}}" NUMBER_of_NAME_places_reserved: "{NUMBER} {NUMBER, plural, =0{} =1{of {NAME} place reserved} other{of {NAME} places reserved}}"
#dashboard: my invoices #dashboard: my invoices
invoices: invoices:
@ -215,7 +215,7 @@ es:
notifications: notifications:
notifications_center: "Centro de notificaciones" notifications_center: "Centro de notificaciones"
mark_all_as_read: "Marcar como leido" mark_all_as_read: "Marcar como leido"
date: "Date" date: "Fecha"
notif_title: "Titulo" notif_title: "Titulo"
no_new_notifications: "No hay notificaciones nuevas." no_new_notifications: "No hay notificaciones nuevas."
archives: "Archivos" archives: "Archivos"

View File

@ -19,7 +19,7 @@ de:
my_trainings: "Meine Trainings" my_trainings: "Meine Trainings"
my_events: "Meine Veranstaltungen" my_events: "Meine Veranstaltungen"
my_invoices: "Meine Rechnungen" my_invoices: "Meine Rechnungen"
my_payment_schedules: "My payment schedules" my_payment_schedules: "Meine Zahlungspläne"
my_wallet: "Mein Guthaben" my_wallet: "Mein Guthaben"
#contextual help #contextual help
help: "Hilfe" help: "Hilfe"
@ -84,8 +84,8 @@ de:
birth_date_is_required: "Geburtsdatum ist erforderlich." birth_date_is_required: "Geburtsdatum ist erforderlich."
phone_number: "Telefonnummer" phone_number: "Telefonnummer"
phone_number_is_required: "Die Angabe der Telefonnummer ist erforderlich." phone_number_is_required: "Die Angabe der Telefonnummer ist erforderlich."
address: "Address" address: "Adresse"
address_is_required: "Address is required" address_is_required: "Adresse ist erforderlich"
i_authorize_Fablab_users_registered_on_the_site_to_contact_me: "Angemeldete Benutzer dürfen mich kontaktieren" i_authorize_Fablab_users_registered_on_the_site_to_contact_me: "Angemeldete Benutzer dürfen mich kontaktieren"
i_accept_to_receive_information_from_the_fablab: "Das Fablab darf mir Informationen schicken" i_accept_to_receive_information_from_the_fablab: "Das Fablab darf mir Informationen schicken"
i_ve_read_and_i_accept_: "Ich habe gelesen und akzeptiere" i_ve_read_and_i_accept_: "Ich habe gelesen und akzeptiere"
@ -165,6 +165,7 @@ de:
openlab_search_not_available_at_the_moment: "Suche über das gesamte Netzwerk ist derzeit nicht verfügbar. Sie können nach Projekten auf dieser Plattform suchen." openlab_search_not_available_at_the_moment: "Suche über das gesamte Netzwerk ist derzeit nicht verfügbar. Sie können nach Projekten auf dieser Plattform suchen."
project_search_result_is_empty: "Leider haben wir keine Ergebnisse gefunden, die Ihren Suchkriterien entsprechen." project_search_result_is_empty: "Leider haben wir keine Ergebnisse gefunden, die Ihren Suchkriterien entsprechen."
reset_all_filters: "Alle Filter zurücksetzen" reset_all_filters: "Alle Filter zurücksetzen"
keywords: "Schlüsselwörter"
search: "Suche" search: "Suche"
all_projects: "Alle Projekte" all_projects: "Alle Projekte"
my_projects: "Meine Projekte" my_projects: "Meine Projekte"
@ -211,7 +212,7 @@ de:
book: "Buchen" book: "Buchen"
_or_the_: " oder die " _or_the_: " oder die "
machines_filters: machines_filters:
show_machines: "Show machines" show_machines: "Maschinen anzeigen"
status_enabled: "Aktiviert" status_enabled: "Aktiviert"
status_disabled: "Deaktiviert" status_disabled: "Deaktiviert"
status_all: "Alle" status_all: "Alle"
@ -251,9 +252,9 @@ de:
no_plans: "Für Ihre Gruppe sind keine Pläne verfügbar" no_plans: "Für Ihre Gruppe sind keine Pläne verfügbar"
AMOUNT_per_month: "{AMOUNT} / monate" AMOUNT_per_month: "{AMOUNT} / monate"
my_group: "Meine Gruppe" my_group: "Meine Gruppe"
his_group: "{GENDER, select, male{Seine} female{Ihre} other{Seine}} Gruppe" his_group: "User's group"
he_wants_to_change_group: "{ROLE, select, member{Ich möchte} other{Der Benutzer möchte}} die Gruppe wechseln" he_wants_to_change_group: "Change group"
change_my_group: "Ändere {ROLE, select, member{meine} other{{GENDER, select, male{seine} female{ihre} other{seine}}}} Gruppe" change_my_group: "Validate group change"
summary: "Zusammenfassung" summary: "Zusammenfassung"
your_subscription_has_expired_on_the_DATE: "Ihr Abonnement ist am {DATE} abgelaufen" your_subscription_has_expired_on_the_DATE: "Ihr Abonnement ist am {DATE} abgelaufen"
subscription_price: "Abonnementspreis" subscription_price: "Abonnementspreis"
@ -266,10 +267,10 @@ de:
an_error_prevented_to_change_the_user_s_group: "Fehler beim Ändern der Benutzergruppe." an_error_prevented_to_change_the_user_s_group: "Fehler beim Ändern der Benutzergruppe."
plans_filter: plans_filter:
i_am: "Ich bin" i_am: "Ich bin"
select_group: "select a group" select_group: "Wählen Sie eine Gruppe aus"
i_want_duration: "I want to subscribe for" i_want_duration: "Ich möchte mich anmelden für"
all_durations: "All durations" all_durations: "Alle Laufzeiten"
select_duration: "select a duration" select_duration: "Wählen Sie eine Laufzeit"
#Fablab's events list #Fablab's events list
events_list: events_list:
the_fablab_s_events: "Veranstaltungen des Fablabs" the_fablab_s_events: "Veranstaltungen des Fablabs"

Some files were not shown because too many files have changed in this diff Show More