mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2024-11-29 10:24:20 +01:00
Merge branch 'settings' into dev
This commit is contained in:
commit
68a99718c8
@ -7,7 +7,8 @@
|
|||||||
"Application": true,
|
"Application": true,
|
||||||
"angular": true,
|
"angular": true,
|
||||||
"Fablab": true,
|
"Fablab": true,
|
||||||
"moment": true,
|
"moment": true
|
||||||
}
|
},
|
||||||
|
"plugins": ["lint-erb"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
12
CHANGELOG.md
12
CHANGELOG.md
@ -1,5 +1,17 @@
|
|||||||
# Changelog Fab-manager
|
# Changelog Fab-manager
|
||||||
|
|
||||||
|
- Ability to configure most of the settings from the admin's UI
|
||||||
|
- Ability to lock some settings from the environment
|
||||||
|
- Improved display of the icons alerting about an outdated version
|
||||||
|
- Improved mime-type checking (back & front)
|
||||||
|
- Updated CarrierWave to 2.1.0
|
||||||
|
- Updated redis to v6, with alpine image
|
||||||
|
- Updated Sidekiq to 6.0.7
|
||||||
|
- Fix a bug: managers do not see the name of the user who reserved a slot
|
||||||
|
- Fix a bug: OpenAPI documentation is not available
|
||||||
|
- [TODO DEPLOY] `rails fablab:setup:env_to_db`
|
||||||
|
- [TODO DEPLOY] `\curl -sSL https://raw.githubusercontent.com/sleede/fab-manager/master/scripts/redis-upgrade.sh | bash`
|
||||||
|
|
||||||
## v4.4.6 2020 June 01
|
## v4.4.6 2020 June 01
|
||||||
|
|
||||||
- Fix a security issue: updated kaminari from 1.2.0 to 1.2.1 to fix [CVE-2020-11082](https://nvd.nist.gov/vuln/detail/CVE-2020-11082)
|
- Fix a security issue: updated kaminari from 1.2.0 to 1.2.1 to fix [CVE-2020-11082](https://nvd.nist.gov/vuln/detail/CVE-2020-11082)
|
||||||
|
5
Gemfile
5
Gemfile
@ -96,11 +96,10 @@ gem 'friendly_id', '~> 5.1.0'
|
|||||||
gem 'aasm'
|
gem 'aasm'
|
||||||
|
|
||||||
# Background job processing
|
# Background job processing
|
||||||
gem 'redis-namespace'
|
gem 'sidekiq', '>= 6.0.7'
|
||||||
gem 'sidekiq', '>= 3.4.2'
|
|
||||||
gem 'sinatra', require: false
|
|
||||||
# Recurring jobs for Sidekiq
|
# Recurring jobs for Sidekiq
|
||||||
gem 'sidekiq-cron'
|
gem 'sidekiq-cron'
|
||||||
|
gem 'sidekiq-unique-jobs', '~> 6.0.22'
|
||||||
|
|
||||||
gem 'stripe', '5.1.1'
|
gem 'stripe', '5.1.1'
|
||||||
|
|
||||||
|
54
Gemfile.lock
54
Gemfile.lock
@ -91,11 +91,13 @@ GEM
|
|||||||
sassc (>= 2.0.0)
|
sassc (>= 2.0.0)
|
||||||
builder (3.2.4)
|
builder (3.2.4)
|
||||||
camertron-eprun (1.1.1)
|
camertron-eprun (1.1.1)
|
||||||
carrierwave (0.10.0)
|
carrierwave (2.1.0)
|
||||||
activemodel (>= 3.2.0)
|
activemodel (>= 5.0.0)
|
||||||
activesupport (>= 3.2.0)
|
activesupport (>= 5.0.0)
|
||||||
json (>= 1.7)
|
addressable (~> 2.6)
|
||||||
mime-types (>= 1.16)
|
image_processing (~> 1.1)
|
||||||
|
mimemagic (>= 0.3.0)
|
||||||
|
mini_mime (>= 0.1.3)
|
||||||
caxlsx (3.0.1)
|
caxlsx (3.0.1)
|
||||||
htmlentities (~> 4.3, >= 4.3.4)
|
htmlentities (~> 4.3, >= 4.3.4)
|
||||||
mimemagic (~> 0.3)
|
mimemagic (~> 0.3)
|
||||||
@ -114,7 +116,7 @@ GEM
|
|||||||
sass-rails (< 5.1)
|
sass-rails (< 5.1)
|
||||||
sprockets (< 4.0)
|
sprockets (< 4.0)
|
||||||
concurrent-ruby (1.1.6)
|
concurrent-ruby (1.1.6)
|
||||||
connection_pool (2.2.2)
|
connection_pool (2.2.3)
|
||||||
coveralls (0.8.23)
|
coveralls (0.8.23)
|
||||||
json (>= 1.8, < 3)
|
json (>= 1.8, < 3)
|
||||||
simplecov (~> 0.16.1)
|
simplecov (~> 0.16.1)
|
||||||
@ -192,6 +194,9 @@ GEM
|
|||||||
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.11.0)
|
||||||
|
mini_magick (>= 4.9.5, < 5)
|
||||||
|
ruby-vips (>= 2.0.17, < 3)
|
||||||
jaro_winkler (1.5.4)
|
jaro_winkler (1.5.4)
|
||||||
jbuilder (2.10.0)
|
jbuilder (2.10.0)
|
||||||
activesupport (>= 5.0.0)
|
activesupport (>= 5.0.0)
|
||||||
@ -230,7 +235,7 @@ GEM
|
|||||||
method_source (1.0.0)
|
method_source (1.0.0)
|
||||||
mime-types (3.3.1)
|
mime-types (3.3.1)
|
||||||
mime-types-data (~> 3.2015)
|
mime-types-data (~> 3.2015)
|
||||||
mime-types-data (3.2019.1009)
|
mime-types-data (3.2020.0512)
|
||||||
mimemagic (0.3.5)
|
mimemagic (0.3.5)
|
||||||
mini_magick (4.10.1)
|
mini_magick (4.10.1)
|
||||||
mini_mime (1.0.2)
|
mini_mime (1.0.2)
|
||||||
@ -245,8 +250,6 @@ GEM
|
|||||||
multi_json (1.14.1)
|
multi_json (1.14.1)
|
||||||
multi_xml (0.6.0)
|
multi_xml (0.6.0)
|
||||||
multipart-post (2.1.1)
|
multipart-post (2.1.1)
|
||||||
mustermann (1.1.1)
|
|
||||||
ruby2_keywords (~> 0.0.1)
|
|
||||||
nio4r (2.5.2)
|
nio4r (2.5.2)
|
||||||
nokogiri (1.10.9)
|
nokogiri (1.10.9)
|
||||||
mini_portile2 (~> 2.4.0)
|
mini_portile2 (~> 2.4.0)
|
||||||
@ -342,9 +345,7 @@ GEM
|
|||||||
recurrence (1.3.0)
|
recurrence (1.3.0)
|
||||||
activesupport
|
activesupport
|
||||||
i18n
|
i18n
|
||||||
redis (4.1.3)
|
redis (4.1.4)
|
||||||
redis-namespace (1.6.0)
|
|
||||||
redis (>= 3.0.4)
|
|
||||||
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)
|
||||||
@ -360,7 +361,8 @@ 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)
|
||||||
ruby2_keywords (0.0.2)
|
ruby-vips (2.0.17)
|
||||||
|
ffi (~> 1.9)
|
||||||
rubyzip (1.3.0)
|
rubyzip (1.3.0)
|
||||||
safe_yaml (1.0.5)
|
safe_yaml (1.0.5)
|
||||||
sass (3.4.25)
|
sass (3.4.25)
|
||||||
@ -379,24 +381,23 @@ GEM
|
|||||||
activerecord (>= 4)
|
activerecord (>= 4)
|
||||||
activesupport (>= 4)
|
activesupport (>= 4)
|
||||||
sha3 (1.0.1)
|
sha3 (1.0.1)
|
||||||
sidekiq (5.2.7)
|
sidekiq (6.0.7)
|
||||||
connection_pool (~> 2.2, >= 2.2.2)
|
connection_pool (>= 2.2.2)
|
||||||
rack (>= 1.5.0)
|
rack (~> 2.0)
|
||||||
rack-protection (>= 1.5.0)
|
rack-protection (>= 2.0.0)
|
||||||
redis (>= 3.3.5, < 5)
|
redis (>= 4.1.0)
|
||||||
sidekiq-cron (1.1.0)
|
sidekiq-cron (1.1.0)
|
||||||
fugit (~> 1.1)
|
fugit (~> 1.1)
|
||||||
sidekiq (>= 4.2.1)
|
sidekiq (>= 4.2.1)
|
||||||
|
sidekiq-unique-jobs (6.0.22)
|
||||||
|
concurrent-ruby (~> 1.0, >= 1.0.5)
|
||||||
|
sidekiq (>= 4.0, < 7.0)
|
||||||
|
thor (~> 0)
|
||||||
simplecov (0.16.1)
|
simplecov (0.16.1)
|
||||||
docile (~> 1.1)
|
docile (~> 1.1)
|
||||||
json (>= 1.8, < 3)
|
json (>= 1.8, < 3)
|
||||||
simplecov-html (~> 0.10.0)
|
simplecov-html (~> 0.10.0)
|
||||||
simplecov-html (0.10.2)
|
simplecov-html (0.10.2)
|
||||||
sinatra (2.0.8.1)
|
|
||||||
mustermann (~> 1.0)
|
|
||||||
rack (~> 2.0)
|
|
||||||
rack-protection (= 2.0.8.1)
|
|
||||||
tilt (~> 2.0)
|
|
||||||
spring (2.0.2)
|
spring (2.0.2)
|
||||||
activesupport (>= 4.2)
|
activesupport (>= 4.2)
|
||||||
spring-watcher-listen (2.0.1)
|
spring-watcher-listen (2.0.1)
|
||||||
@ -415,7 +416,7 @@ GEM
|
|||||||
ffi
|
ffi
|
||||||
term-ansicolor (1.7.1)
|
term-ansicolor (1.7.1)
|
||||||
tins (~> 1.0)
|
tins (~> 1.0)
|
||||||
thor (1.0.1)
|
thor (0.20.3)
|
||||||
thread_safe (0.3.6)
|
thread_safe (0.3.6)
|
||||||
tilt (2.0.10)
|
tilt (2.0.10)
|
||||||
tins (1.24.1)
|
tins (1.24.1)
|
||||||
@ -509,7 +510,6 @@ DEPENDENCIES
|
|||||||
rails_12factor
|
rails_12factor
|
||||||
rb-readline
|
rb-readline
|
||||||
recurrence
|
recurrence
|
||||||
redis-namespace
|
|
||||||
repost
|
repost
|
||||||
responders (~> 2.0)
|
responders (~> 2.0)
|
||||||
rolify
|
rolify
|
||||||
@ -519,9 +519,9 @@ DEPENDENCIES
|
|||||||
sdoc (~> 0.4.0)
|
sdoc (~> 0.4.0)
|
||||||
seed_dump
|
seed_dump
|
||||||
sha3
|
sha3
|
||||||
sidekiq (>= 3.4.2)
|
sidekiq (>= 6.0.7)
|
||||||
sidekiq-cron
|
sidekiq-cron
|
||||||
sinatra
|
sidekiq-unique-jobs (~> 6.0.22)
|
||||||
spring
|
spring
|
||||||
spring-watcher-listen (~> 2.0.0)
|
spring-watcher-listen (~> 2.0.0)
|
||||||
stripe (= 5.1.1)
|
stripe (= 5.1.1)
|
||||||
|
15
README.md
15
README.md
@ -27,9 +27,9 @@ Fab-manager is the Fab Lab management solution. It provides a comprehensive, web
|
|||||||
Fab-manager is a Ruby on Rails / AngularJS web application that runs on the following software:
|
Fab-manager is a Ruby on Rails / AngularJS web application that runs on the following software:
|
||||||
|
|
||||||
- Ubuntu LTS 14.04+ / Debian 8+
|
- Ubuntu LTS 14.04+ / Debian 8+
|
||||||
- Ruby 2.3
|
- Ruby 2.6
|
||||||
- Redis 2.8.4+
|
- Redis 6
|
||||||
- Sidekiq 3.3.4+
|
- Sidekiq 6
|
||||||
- Elasticsearch 5.6
|
- Elasticsearch 5.6
|
||||||
- PostgreSQL 9.6
|
- PostgreSQL 9.6
|
||||||
|
|
||||||
@ -71,9 +71,8 @@ The deal is fair, you share your projects and as reward you benefits from projec
|
|||||||
If you want to try it, you can visit [this Fab-manager](https://fablab.lacasemate.fr/#!/projects) and see projects from different Fab-managers.
|
If you want to try it, you can visit [this Fab-manager](https://fablab.lacasemate.fr/#!/projects) and see projects from different Fab-managers.
|
||||||
|
|
||||||
To start using this awesome feature, there are a few steps:
|
To start using this awesome feature, there are a few steps:
|
||||||
- send a mail to **contact@fab-manager.com** asking for your Open Projects client's credentials and giving them the name of your Fab-manager, they will give you an `OPENLAB_APP_ID` and an `OPENLAB_APP_SECRET`
|
- send a mail to **contact@fab-manager.com** asking for your Open Projects client's credentials and giving them the name and the URL of your Fab-manager, they will give you an `App ID` and a `secret`
|
||||||
- fill in the value of the keys in your environment file
|
- fill in the value of the keys in Admin > Projects > Settings > Projects sharing
|
||||||
- start your Fab-manager app
|
|
||||||
- export your projects to open-projects (if you already have projects created on your Fab-manager, unless you can skip that part) executing this command: `bundle exec rake fablab:openlab:bulk_export`
|
- export your projects to open-projects (if you already have projects created on your Fab-manager, unless you can skip that part) executing this command: `bundle exec rake fablab:openlab:bulk_export`
|
||||||
|
|
||||||
**IMPORTANT: please run your server in production mode.**
|
**IMPORTANT: please run your server in production mode.**
|
||||||
@ -99,9 +98,9 @@ You can see an example on the [repo of navinum gamification plugin](https://gith
|
|||||||
## Single Sign-On
|
## Single Sign-On
|
||||||
|
|
||||||
Fab-manager can be connected to a [Single Sign-On](https://en.wikipedia.org/wiki/Single_sign-on) server which will provide its own authentication for the platform's users.
|
Fab-manager can be connected to a [Single Sign-On](https://en.wikipedia.org/wiki/Single_sign-on) server which will provide its own authentication for the platform's users.
|
||||||
Currently OAuth 2 is the only supported protocol for SSO authentication.
|
Currently, OAuth 2 is the only supported protocol for SSO authentication.
|
||||||
|
|
||||||
For an example of how to use configure a SSO in Fab-manager, please read [sso_with_github.md](doc/sso_with_github.md).
|
For an example of how to use configure an SSO in Fab-manager, please read [sso_with_github.md](doc/sso_with_github.md).
|
||||||
|
|
||||||
<a name="known-issues"></a>
|
<a name="known-issues"></a>
|
||||||
## Known issues
|
## Known issues
|
||||||
|
@ -17,7 +17,7 @@ Application.Directives = angular.module('application.directives', []);
|
|||||||
angular.module('application', ['ngCookies', 'ngResource', 'ngSanitize', 'ui.router', 'ui.bootstrap',
|
angular.module('application', ['ngCookies', 'ngResource', 'ngSanitize', 'ui.router', 'ui.bootstrap',
|
||||||
'ngUpload', 'duScroll', 'application.filters', 'application.services', 'application.directives',
|
'ngUpload', 'duScroll', 'application.filters', 'application.services', 'application.directives',
|
||||||
'frapontillo.bootstrap-switch', 'application.constants', 'application.controllers', 'application.router',
|
'frapontillo.bootstrap-switch', 'application.constants', 'application.controllers', 'application.router',
|
||||||
'ui.select', 'ui.calendar', 'angularMoment', 'Devise', 'DeviseModal', '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', 'angular-google-analytics',
|
||||||
'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',
|
||||||
@ -28,10 +28,10 @@ angular.module('application', ['ngCookies', 'ngResource', 'ngSanitize', 'ui.rout
|
|||||||
// 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.gaId);
|
AnalyticsProvider.setAccount(Fablab.trackingId);
|
||||||
// track all routes (or not)
|
// track all routes (or not)
|
||||||
AnalyticsProvider.trackPages(true);
|
AnalyticsProvider.trackPages(true);
|
||||||
AnalyticsProvider.setDomainName(Fablab.defaultHost);
|
AnalyticsProvider.setDomainName(Fablab.baseHostUrl);
|
||||||
AnalyticsProvider.useAnalytics(true);
|
AnalyticsProvider.useAnalytics(true);
|
||||||
AnalyticsProvider.setPageEvent('$stateChangeSuccess');
|
AnalyticsProvider.setPageEvent('$stateChangeSuccess');
|
||||||
} else {
|
} else {
|
||||||
@ -81,25 +81,6 @@ angular.module('application', ['ngCookies', 'ngResource', 'ngSanitize', 'ui.rout
|
|||||||
$state.prevParams = fromParams;
|
$state.prevParams = fromParams;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Global config: if true, the whole 'Plans & Subscriptions' feature will be disabled in the application
|
|
||||||
$rootScope.fablabWithoutPlans = Fablab.withoutPlans;
|
|
||||||
// Global config: it true, the whole 'Spaces' features will be disabled in the application
|
|
||||||
$rootScope.fablabWithoutSpaces = Fablab.withoutSpaces;
|
|
||||||
// Global config: if true, all payments will be disabled in the application for the members (only admins will be able to proceed reservations)
|
|
||||||
$rootScope.fablabWithoutOnlinePayment = Fablab.withoutOnlinePayment;
|
|
||||||
// Global config: if true, no invoices will be generated
|
|
||||||
$rootScope.fablabWithoutInvoices = Fablab.withoutInvoices;
|
|
||||||
// Global config: if true, the phone number is required to create an account
|
|
||||||
$rootScope.phoneRequired = Fablab.phoneRequired;
|
|
||||||
// Global config: if true, the events are shown in the admin calendar
|
|
||||||
$rootScope.eventsInCalendar = Fablab.eventsInCalendar;
|
|
||||||
// Global config: machine/space slot duration
|
|
||||||
$rootScope.slotDuration = Fablab.slotDuration;
|
|
||||||
// Global config: if true, user must confirm his email to sign in
|
|
||||||
$rootScope.userConfirmationNeededToSignIn = Fablab.userConfirmationNeededToSignIn;
|
|
||||||
// Global config: if true, wallet will be disable
|
|
||||||
$rootScope.fablabWithoutWallet = Fablab.fablabWithoutWallet;
|
|
||||||
|
|
||||||
// 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).
|
||||||
// If no previous $state were recorded, navigate to the home page
|
// If no previous $state were recorded, navigate to the home page
|
||||||
$rootScope.backPrevLocation = function (event) {
|
$rootScope.backPrevLocation = function (event) {
|
||||||
|
@ -18,8 +18,8 @@
|
|||||||
* Controller used in the calendar management page
|
* Controller used in the calendar management page
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Application.Controllers.controller('AdminCalendarController', ['$scope', '$state', '$uibModal', 'moment', 'AuthService', 'Availability', 'Slot', 'Setting', 'Export', 'growl', 'dialogs', 'bookingWindowStart', 'bookingWindowEnd', 'machinesPromise', 'plansPromise', 'groupsPromise', '_t', 'uiCalendarConfig', 'CalendarConfig', 'Member', 'uiTourService',
|
Application.Controllers.controller('AdminCalendarController', ['$scope', '$state', '$uibModal', 'moment', 'AuthService', 'Availability', 'Slot', 'Setting', 'Export', 'growl', 'dialogs', 'bookingWindowStart', 'bookingWindowEnd', 'machinesPromise', 'plansPromise', 'groupsPromise', 'settingsPromise', '_t', 'uiCalendarConfig', 'CalendarConfig', 'Member', 'uiTourService',
|
||||||
function ($scope, $state, $uibModal, moment, AuthService, Availability, Slot, Setting, Export, growl, dialogs, bookingWindowStart, bookingWindowEnd, machinesPromise, plansPromise, groupsPromise, _t, uiCalendarConfig, CalendarConfig, Member, uiTourService) {
|
function ($scope, $state, $uibModal, moment, AuthService, Availability, Slot, Setting, Export, growl, dialogs, bookingWindowStart, bookingWindowEnd, machinesPromise, plansPromise, groupsPromise, settingsPromise, _t, uiCalendarConfig, CalendarConfig, Member, uiTourService) {
|
||||||
/* PRIVATE STATIC CONSTANTS */
|
/* PRIVATE STATIC CONSTANTS */
|
||||||
|
|
||||||
// The calendar is divided in slots of 30 minutes
|
// The calendar is divided in slots of 30 minutes
|
||||||
@ -29,7 +29,7 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
|||||||
const BOOKING_SNAP = '00:30:00';
|
const BOOKING_SNAP = '00:30:00';
|
||||||
|
|
||||||
// We do not allow the creation of slots that are not a multiple of 60 minutes
|
// We do not allow the creation of slots that are not a multiple of 60 minutes
|
||||||
const SLOT_MULTIPLE = Fablab.slotDuration;
|
const SLOT_MULTIPLE = parseInt(settingsPromise.slot_duration, 10);
|
||||||
|
|
||||||
/* PUBLIC SCOPE */
|
/* PUBLIC SCOPE */
|
||||||
|
|
||||||
@ -42,6 +42,9 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
|||||||
// corresponding fullCalendar item in the DOM
|
// corresponding fullCalendar item in the DOM
|
||||||
$scope.availabilityDom = null;
|
$scope.availabilityDom = null;
|
||||||
|
|
||||||
|
// Should we show the scheduled events in the calendar?
|
||||||
|
$scope.eventsInCalendar = (settingsPromise.events_in_calendar === 'true');
|
||||||
|
|
||||||
// bind the availabilities slots with full-Calendar events
|
// bind the availabilities slots with full-Calendar events
|
||||||
$scope.eventSources = [];
|
$scope.eventSources = [];
|
||||||
$scope.eventSources.push({
|
$scope.eventSources.push({
|
||||||
@ -349,7 +352,7 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
// if the user has never seen the tour, show him now
|
// if the user has never seen the tour, show him now
|
||||||
if (Fablab.featureTourDisplay !== 'manual' && $scope.currentUser.profile.tours.indexOf('calendar') < 0) {
|
if (settingsPromise.feature_tour_display !== 'manual' && $scope.currentUser.profile.tours.indexOf('calendar') < 0) {
|
||||||
uitour.start();
|
uitour.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -429,7 +432,8 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
|||||||
spacesPromise: ['Space', function (Space) { return Space.query().$promise; }],
|
spacesPromise: ['Space', function (Space) { return Space.query().$promise; }],
|
||||||
tagsPromise: ['Tag', function (Tag) { return Tag.query().$promise; }],
|
tagsPromise: ['Tag', function (Tag) { return Tag.query().$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; }],
|
||||||
|
slotDurationPromise: ['Setting', function (Setting) { return Setting.get({ name: 'slot_duration' }).$promise; }]
|
||||||
} });
|
} });
|
||||||
// when the modal is closed, we send the slot to the server for saving
|
// when the modal is closed, we send the slot to the server for saving
|
||||||
modalInstance.result.then(
|
modalInstance.result.then(
|
||||||
@ -531,8 +535,8 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
|||||||
/**
|
/**
|
||||||
* Controller used in the slot creation modal window
|
* Controller used in the slot creation modal window
|
||||||
*/
|
*/
|
||||||
Application.Controllers.controller('CreateEventModalController', ['$scope', '$uibModalInstance', '$sce', 'moment', 'start', 'end', 'slots', 'machinesPromise', 'Availability', 'trainingsPromise', 'spacesPromise', 'tagsPromise', 'plansPromise', 'groupsPromise', 'growl', '_t',
|
Application.Controllers.controller('CreateEventModalController', ['$scope', '$uibModalInstance', '$sce', 'moment', 'start', 'end', 'slots', 'machinesPromise', 'Availability', 'trainingsPromise', 'spacesPromise', 'tagsPromise', 'plansPromise', 'groupsPromise', 'slotDurationPromise', 'growl', '_t',
|
||||||
function ($scope, $uibModalInstance, $sce, moment, start, end, slots, machinesPromise, Availability, trainingsPromise, spacesPromise, tagsPromise, plansPromise, groupsPromise, growl, _t) {
|
function ($scope, $uibModalInstance, $sce, moment, start, end, slots, machinesPromise, Availability, trainingsPromise, spacesPromise, tagsPromise, plansPromise, groupsPromise, slotDurationPromise, growl, _t) {
|
||||||
// $uibModal parameter
|
// $uibModal parameter
|
||||||
$scope.start = start;
|
$scope.start = start;
|
||||||
|
|
||||||
@ -595,7 +599,7 @@ Application.Controllers.controller('CreateEventModalController', ['$scope', '$ui
|
|||||||
period: 'week',
|
period: 'week',
|
||||||
nb_periods: 1,
|
nb_periods: 1,
|
||||||
end_date: undefined, // recurrence end
|
end_date: undefined, // recurrence end
|
||||||
slot_duration: Fablab.slotDuration
|
slot_duration: parseInt(slotDurationPromise.setting.value, 10)
|
||||||
};
|
};
|
||||||
|
|
||||||
// recurrent slots
|
// recurrent slots
|
||||||
|
@ -153,8 +153,8 @@ class EventsController {
|
|||||||
/**
|
/**
|
||||||
* Controller used in the events listing page (admin view)
|
* Controller used in the events listing page (admin view)
|
||||||
*/
|
*/
|
||||||
Application.Controllers.controller('AdminEventsController', ['$scope', '$state', 'dialogs', '$uibModal', 'growl', 'AuthService', 'Event', 'Category', 'EventTheme', 'AgeRange', 'PriceCategory', 'eventsPromise', 'categoriesPromise', 'themesPromise', 'ageRangesPromise', 'priceCategoriesPromise', '_t', 'Member', 'uiTourService',
|
Application.Controllers.controller('AdminEventsController', ['$scope', '$state', 'dialogs', '$uibModal', 'growl', 'AuthService', 'Event', 'Category', 'EventTheme', 'AgeRange', 'PriceCategory', 'eventsPromise', 'categoriesPromise', 'themesPromise', 'ageRangesPromise', 'priceCategoriesPromise', '_t', 'Member', 'uiTourService', 'settingsPromise',
|
||||||
function ($scope, $state, dialogs, $uibModal, growl, AuthService, Event, Category, EventTheme, AgeRange, PriceCategory, eventsPromise, categoriesPromise, themesPromise, ageRangesPromise, priceCategoriesPromise, _t, Member, uiTourService) {
|
function ($scope, $state, dialogs, $uibModal, growl, AuthService, Event, Category, EventTheme, AgeRange, PriceCategory, eventsPromise, categoriesPromise, themesPromise, ageRangesPromise, priceCategoriesPromise, _t, Member, uiTourService, settingsPromise) {
|
||||||
/* PUBLIC SCOPE */
|
/* PUBLIC SCOPE */
|
||||||
|
|
||||||
// By default, the pagination mode is activated to limit the page size
|
// By default, the pagination mode is activated to limit the page size
|
||||||
@ -465,7 +465,7 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
// if the user has never seen the tour, show him now
|
// if the user has never seen the tour, show him now
|
||||||
if (Fablab.featureTourDisplay !== 'manual' && $scope.currentUser.profile.tours.indexOf('events') < 0) {
|
if (settingsPromise.feature_tour_display !== 'manual' && $scope.currentUser.profile.tours.indexOf('events') < 0) {
|
||||||
uitour.start();
|
uitour.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,18 +17,21 @@
|
|||||||
/**
|
/**
|
||||||
* Controller used in the admin invoices listing page
|
* Controller used in the admin invoices listing page
|
||||||
*/
|
*/
|
||||||
Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'Invoice', 'AccountingPeriod', 'AuthService', 'invoices', 'closedPeriods', '$uibModal', 'growl', '$filter', 'Setting', 'settings', '_t', 'Member', 'uiTourService',
|
Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'Invoice', 'AccountingPeriod', 'AuthService', 'invoices', 'closedPeriods', '$uibModal', 'growl', '$filter', 'Setting', 'settings', 'stripeSecretKey', '_t', 'Member', 'uiTourService', 'Payment', 'onlinePaymentStatus',
|
||||||
function ($scope, $state, Invoice, AccountingPeriod, AuthService, invoices, closedPeriods, $uibModal, growl, $filter, Setting, settings, _t, Member, uiTourService) {
|
function ($scope, $state, Invoice, AccountingPeriod, AuthService, invoices, closedPeriods, $uibModal, growl, $filter, Setting, settings, stripeSecretKey, _t, Member, uiTourService, Payment, onlinePaymentStatus) {
|
||||||
/* PRIVATE STATIC CONSTANTS */
|
/* PRIVATE STATIC CONSTANTS */
|
||||||
|
|
||||||
// number of invoices loaded each time we click on 'load more...'
|
// number of invoices loaded each time we click on 'load more...'
|
||||||
const INVOICES_PER_PAGE = 20;
|
const INVOICES_PER_PAGE = 20;
|
||||||
|
|
||||||
|
// fake stripe secret key
|
||||||
|
const STRIPE_SK_HIDDEN = 'sk_test_hidden-hidden-hidden-hid';
|
||||||
|
|
||||||
/* PUBLIC SCOPE */
|
/* PUBLIC SCOPE */
|
||||||
|
|
||||||
// default active tab
|
// default active tab
|
||||||
$scope.tabs = {
|
$scope.tabs = {
|
||||||
active: Fablab.withoutInvoices ? 1 : 0
|
active: settings.invoicing_module === 'true' ? 0 : 1
|
||||||
};
|
};
|
||||||
|
|
||||||
// List of all invoices
|
// List of all invoices
|
||||||
@ -50,6 +53,14 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
|||||||
// Default invoices ordering/sorting
|
// Default invoices ordering/sorting
|
||||||
$scope.orderInvoice = '-reference';
|
$scope.orderInvoice = '-reference';
|
||||||
|
|
||||||
|
// Invoice PDF filename settings (and example)
|
||||||
|
$scope.file = {
|
||||||
|
prefix: settings.invoice_prefix,
|
||||||
|
nextId: 40,
|
||||||
|
date: moment().format('DDMMYYYY'),
|
||||||
|
templateUrl: 'editPrefix.html'
|
||||||
|
}
|
||||||
|
|
||||||
// Invoices parameters
|
// Invoices parameters
|
||||||
$scope.invoice = {
|
$scope.invoice = {
|
||||||
logo: null,
|
logo: null,
|
||||||
@ -169,6 +180,15 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// all settings
|
||||||
|
$scope.allSettings = settings;
|
||||||
|
|
||||||
|
// is the stripe private set?
|
||||||
|
$scope.stripeSecretKey = (stripeSecretKey.isPresent ? STRIPE_SK_HIDDEN : '');
|
||||||
|
|
||||||
|
// has any online payment been already made?
|
||||||
|
$scope.onlinePaymentStatus = onlinePaymentStatus.status;
|
||||||
|
|
||||||
// Placeholding date for the invoice creation
|
// Placeholding date for the invoice creation
|
||||||
$scope.today = moment();
|
$scope.today = moment();
|
||||||
|
|
||||||
@ -465,6 +485,38 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a modal dialog allowing the user to edit the prefix of the invoice file name
|
||||||
|
*/
|
||||||
|
$scope.openEditPrefix = function () {
|
||||||
|
const modalInstance = $uibModal.open({
|
||||||
|
animation: true,
|
||||||
|
templateUrl: $scope.file.templateUrl,
|
||||||
|
size: 'lg',
|
||||||
|
resolve: {
|
||||||
|
model () { return $scope.file.prefix;}
|
||||||
|
},
|
||||||
|
controller: ['$scope', '$uibModalInstance', 'model', function ($scope, $uibModalInstance, model) {
|
||||||
|
$scope.model = model;
|
||||||
|
$scope.ok = function () { $uibModalInstance.close($scope.model); };
|
||||||
|
$scope.cancel = function () { $uibModalInstance.dismiss('cancel'); };
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
return modalInstance.result.then(function (model) {
|
||||||
|
Setting.update({ name: 'invoice_prefix' }, { value: model }, function (data) {
|
||||||
|
$scope.file.prefix = model;
|
||||||
|
return growl.success(_t('app.admin.invoices.prefix_successfully_saved'));
|
||||||
|
}
|
||||||
|
, function (error) {
|
||||||
|
if (error.status === 304) return;
|
||||||
|
|
||||||
|
growl.error(_t('app.admin.invoices.an_error_occurred_while_saving_the_prefix'));
|
||||||
|
console.error(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback to save the value of the text zone when editing is done
|
* Callback to save the value of the text zone when editing is done
|
||||||
*/
|
*/
|
||||||
@ -569,7 +621,7 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
|||||||
{ settings: Object.values($scope.settings) },
|
{ settings: Object.values($scope.settings) },
|
||||||
function () { growl.success(_t('app.admin.invoices.codes_customization_success')); },
|
function () { growl.success(_t('app.admin.invoices.codes_customization_success')); },
|
||||||
function (error) {
|
function (error) {
|
||||||
growl.error('unexpected_error_occurred');
|
growl.error('app.admin.invoices.unexpected_error_occurred');
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -584,6 +636,42 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
|||||||
return `${invoice.operator.first_name} ${invoice.operator.last_name}`;
|
return `${invoice.operator.first_name} ${invoice.operator.last_name}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a modal dialog which ask for the stripe keys
|
||||||
|
* @param onlinePaymentModule {{name: String, value: String}} setting that defines the next status of the online payment module
|
||||||
|
* @return {boolean} false if the keys were not provided
|
||||||
|
*/
|
||||||
|
$scope.requireStripeKeys = function(onlinePaymentModule) {
|
||||||
|
// if the online payment is about to be disabled, accept the change without any further question
|
||||||
|
if (onlinePaymentModule.value === false) return true;
|
||||||
|
|
||||||
|
// otherwise, open a modal to ask for the stripe keys
|
||||||
|
const modalInstance = $uibModal.open({
|
||||||
|
templateUrl: 'stripeKeys.html',
|
||||||
|
controller: 'StripeKeysModalController',
|
||||||
|
resolve: {
|
||||||
|
stripeKeys: ['Setting', function (Setting) { return Setting.query({ names: "['stripe_public_key', 'stripe_secret_key']" }).$promise; }]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
modalInstance.result.then(function (success) {
|
||||||
|
if (success) {
|
||||||
|
Setting.get({ name: 'stripe_public_key' }, function (res) {
|
||||||
|
$scope.allSettings.stripe_public_key = res.setting.value;
|
||||||
|
})
|
||||||
|
Setting.isPresent({ name: 'stripe_secret_key' }, function (res) {
|
||||||
|
$scope.stripeSecretKey = (res.isPresent ? STRIPE_SK_HIDDEN : '');
|
||||||
|
})
|
||||||
|
Payment.onlinePaymentStatus(function (res) {
|
||||||
|
$scope.onlinePaymentStatus = res.status;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// return the promise
|
||||||
|
return modalInstance.result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup the feature-tour for the admin/invoices page.
|
* Setup the feature-tour for the admin/invoices page.
|
||||||
* This is intended as a contextual help (when pressing F1)
|
* This is intended as a contextual help (when pressing F1)
|
||||||
@ -612,7 +700,7 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
|||||||
orphan: true
|
orphan: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!Fablab.withoutInvoices && $scope.invoices.length > 0) {
|
if (settings.invoicing_module === 'true' && $scope.invoices.length > 0) {
|
||||||
uitour.createStep({
|
uitour.createStep({
|
||||||
selector: '.invoices-management .invoices-list',
|
selector: '.invoices-management .invoices-list',
|
||||||
stepId: 'list',
|
stepId: 'list',
|
||||||
@ -671,10 +759,19 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
|||||||
content: _t('app.admin.tour.invoices.export.content'),
|
content: _t('app.admin.tour.invoices.export.content'),
|
||||||
placement: 'bottom'
|
placement: 'bottom'
|
||||||
});
|
});
|
||||||
|
uitour.createStep({
|
||||||
|
selector: '.invoices-management .payment-settings',
|
||||||
|
stepId: 'payment',
|
||||||
|
order: 8,
|
||||||
|
title: _t('app.admin.tour.invoices.payment.title'),
|
||||||
|
content: _t('app.admin.tour.invoices.payment.content'),
|
||||||
|
placement: 'bottom',
|
||||||
|
popupClass: 'shift-left-50'
|
||||||
|
});
|
||||||
uitour.createStep({
|
uitour.createStep({
|
||||||
selector: '.heading .close-accounting-periods-button',
|
selector: '.heading .close-accounting-periods-button',
|
||||||
stepId: 'periods',
|
stepId: 'periods',
|
||||||
order: 8,
|
order: 9,
|
||||||
title: _t('app.admin.tour.invoices.periods.title'),
|
title: _t('app.admin.tour.invoices.periods.title'),
|
||||||
content: _t('app.admin.tour.invoices.periods.content'),
|
content: _t('app.admin.tour.invoices.periods.content'),
|
||||||
placement: 'bottom',
|
placement: 'bottom',
|
||||||
@ -684,7 +781,7 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
|||||||
uitour.createStep({
|
uitour.createStep({
|
||||||
selector: 'body',
|
selector: 'body',
|
||||||
stepId: 'conclusion',
|
stepId: 'conclusion',
|
||||||
order: 9,
|
order: 10,
|
||||||
title: _t('app.admin.tour.conclusion.title'),
|
title: _t('app.admin.tour.conclusion.title'),
|
||||||
content: _t('app.admin.tour.conclusion.content'),
|
content: _t('app.admin.tour.conclusion.content'),
|
||||||
placement: 'bottom',
|
placement: 'bottom',
|
||||||
@ -701,6 +798,9 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
|||||||
if (nextStep.stepId === 'codes' || nextStep.stepId === 'export') {
|
if (nextStep.stepId === 'codes' || nextStep.stepId === 'export') {
|
||||||
$scope.tabs.active = 2;
|
$scope.tabs.active = 2;
|
||||||
}
|
}
|
||||||
|
if (nextStep.stepId === 'payment') {
|
||||||
|
$scope.tabs.active = 3;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
// on tour end, save the status in database
|
// on tour end, save the status in database
|
||||||
uitour.on('ended', function () {
|
uitour.on('ended', function () {
|
||||||
@ -711,7 +811,7 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
// if the user has never seen the tour, show him now
|
// if the user has never seen the tour, show him now
|
||||||
if (Fablab.featureTourDisplay !== 'manual' && $scope.currentUser.profile.tours.indexOf('invoices') < 0) {
|
if (settings.feature_tour_display !== 'manual' && $scope.currentUser.profile.tours.indexOf('invoices') < 0) {
|
||||||
uitour.start();
|
uitour.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1209,3 +1309,131 @@ Application.Controllers.controller('AccountingExportModalController', ['$scope',
|
|||||||
// !!! MUST BE CALLED AT THE END of the controller
|
// !!! MUST BE CALLED AT THE END of the controller
|
||||||
return initialize();
|
return initialize();
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controller used in the modal window allowing an admin to close an accounting period
|
||||||
|
*/
|
||||||
|
Application.Controllers.controller('StripeKeysModalController', ['$scope', '$uibModalInstance', '$http', '$httpParamSerializerJQLike', 'stripeKeys', 'Setting', 'growl', '_t',
|
||||||
|
function ($scope, $uibModalInstance, $http, $httpParamSerializerJQLike, stripeKeys, Setting, growl, _t) {
|
||||||
|
/* PUBLIC SCOPE */
|
||||||
|
|
||||||
|
// public key
|
||||||
|
$scope.publicKey = stripeKeys.stripe_public_key;
|
||||||
|
|
||||||
|
// test status of the public key
|
||||||
|
$scope.publicKeyStatus = undefined;
|
||||||
|
|
||||||
|
// secret key
|
||||||
|
$scope.secretKey = stripeKeys.stripe_secret_key;
|
||||||
|
|
||||||
|
// test status of the secret key
|
||||||
|
$scope.secretKeyStatus = undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trigger the test of the secret key and set the result in $scope.secretKeyStatus
|
||||||
|
*/
|
||||||
|
$scope.testSecretKey = function () {
|
||||||
|
if (!$scope.secretKey.match(/^sk_/)) {
|
||||||
|
$scope.secretKeyStatus = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$http({
|
||||||
|
method: 'GET',
|
||||||
|
url: 'https://api.stripe.com/v1/charges',
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${$scope.secretKey}`,
|
||||||
|
}
|
||||||
|
}).then(function () {
|
||||||
|
$scope.secretKeyStatus = true;
|
||||||
|
}, function (err) {
|
||||||
|
if (err.status === 401) $scope.secretKeyStatus = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trigger the test of the secret key and set the result in $scope.secretKeyStatus
|
||||||
|
*/
|
||||||
|
$scope.testPublicKey = function () {
|
||||||
|
if (!$scope.publicKey.match(/^pk_/)) {
|
||||||
|
$scope.publicKeyStatus = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const today = new Date();
|
||||||
|
$http({
|
||||||
|
method: 'POST',
|
||||||
|
url: 'https://api.stripe.com/v1/tokens',
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${$scope.publicKey}`,
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded'
|
||||||
|
},
|
||||||
|
data: $httpParamSerializerJQLike({
|
||||||
|
'card[number]': 4242424242424242,
|
||||||
|
'card[cvc]': 123,
|
||||||
|
'card[exp_month]': 12,
|
||||||
|
'card[exp_year]': today.getFullYear().toString().substring(2),
|
||||||
|
})
|
||||||
|
}).then(function () {
|
||||||
|
$scope.publicKeyStatus = true;
|
||||||
|
}, function (err) {
|
||||||
|
if (err.status === 401) $scope.publicKeyStatus = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate the keys
|
||||||
|
*/
|
||||||
|
$scope.ok = function () {
|
||||||
|
if ($scope.secretKeyStatus && $scope.publicKeyStatus) {
|
||||||
|
Setting.bulkUpdate(
|
||||||
|
{ settings: [
|
||||||
|
{
|
||||||
|
name: 'stripe_public_key',
|
||||||
|
value: $scope.publicKey
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'stripe_secret_key',
|
||||||
|
value: $scope.secretKey
|
||||||
|
}
|
||||||
|
] },
|
||||||
|
function () {
|
||||||
|
growl.success(_t('app.admin.invoices.payment.stripe_keys_saved'));
|
||||||
|
$uibModalInstance.close(true);
|
||||||
|
},
|
||||||
|
function (error) {
|
||||||
|
growl.error('app.admin.invoices.payment.error_saving_stripe_keys');
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
growl.error(_t('app.admin.invoices.payment.error_check_keys'))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Just dismiss the modal window
|
||||||
|
*/
|
||||||
|
$scope.cancel = function () {
|
||||||
|
$uibModalInstance.dismiss('cancel');
|
||||||
|
};
|
||||||
|
|
||||||
|
/* PRIVATE SCOPE */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||||
|
*/
|
||||||
|
const initialize = function () {
|
||||||
|
if (stripeKeys.stripe_public_key) {
|
||||||
|
$scope.testPublicKey();
|
||||||
|
}
|
||||||
|
if (stripeKeys.stripe_secret_key) {
|
||||||
|
$scope.testSecretKey();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// !!! MUST BE CALLED AT THE END of the controller!
|
||||||
|
return initialize();
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
@ -126,8 +126,8 @@ class MembersController {
|
|||||||
/**
|
/**
|
||||||
* Controller used in the members/groups management page
|
* Controller used in the members/groups management page
|
||||||
*/
|
*/
|
||||||
Application.Controllers.controller('AdminMembersController', ['$scope', '$sce', '$uibModal', 'membersPromise', 'adminsPromise', 'partnersPromise', 'managersPromise', 'growl', 'Admin', 'AuthService', 'dialogs', '_t', 'Member', 'Export', 'User', 'uiTourService',
|
Application.Controllers.controller('AdminMembersController', ['$scope', '$sce', '$uibModal', 'membersPromise', 'adminsPromise', 'partnersPromise', 'managersPromise', 'growl', 'Admin', 'AuthService', 'dialogs', '_t', 'Member', 'Export', 'User', 'uiTourService', 'settingsPromise',
|
||||||
function ($scope, $sce, $uibModal, membersPromise, adminsPromise, partnersPromise, managersPromise, growl, Admin, AuthService, dialogs, _t, Member, Export, User, uiTourService) {
|
function ($scope, $sce, $uibModal, membersPromise, adminsPromise, partnersPromise, managersPromise, growl, Admin, AuthService, dialogs, _t, Member, Export, User, uiTourService, settingsPromise) {
|
||||||
/* PRIVATE STATIC CONSTANTS */
|
/* PRIVATE STATIC CONSTANTS */
|
||||||
|
|
||||||
// number of users loaded each time we click on 'load more...'
|
// number of users loaded each time we click on 'load more...'
|
||||||
@ -567,7 +567,7 @@ Application.Controllers.controller('AdminMembersController', ['$scope', '$sce',
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
// if the user has never seen the tour, show him now
|
// if the user has never seen the tour, show him now
|
||||||
if (Fablab.featureTourDisplay !== 'manual' && $scope.currentUser.profile.tours.indexOf('members') < 0) {
|
if (settingsPromise.feature_tour_display !== 'manual' && $scope.currentUser.profile.tours.indexOf('members') < 0) {
|
||||||
uitour.start();
|
uitour.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -641,8 +641,8 @@ 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',
|
Application.Controllers.controller('EditMemberController', ['$scope', '$state', '$stateParams', 'Member', 'Training', 'dialogs', 'growl', 'Group', 'Subscription', 'CSRF', 'memberPromise', 'tagsPromise', '$uibModal', 'Plan', '$filter', '_t', 'walletPromise', 'transactionsPromise', 'activeProviderPromise', 'Wallet', 'phoneRequiredPromise',
|
||||||
function ($scope, $state, $stateParams, Member, Training, dialogs, growl, Group, Subscription, CSRF, memberPromise, tagsPromise, $uibModal, Plan, $filter, _t, walletPromise, transactionsPromise, activeProviderPromise, Wallet) {
|
function ($scope, $state, $stateParams, Member, Training, dialogs, growl, Group, Subscription, CSRF, memberPromise, tagsPromise, $uibModal, Plan, $filter, _t, walletPromise, transactionsPromise, activeProviderPromise, Wallet, phoneRequiredPromise) {
|
||||||
/* PUBLIC SCOPE */
|
/* PUBLIC SCOPE */
|
||||||
|
|
||||||
// API URL where the form will be posted
|
// API URL where the form will be posted
|
||||||
@ -660,6 +660,9 @@ Application.Controllers.controller('EditMemberController', ['$scope', '$state',
|
|||||||
// Should the password be modified?
|
// Should the password be modified?
|
||||||
$scope.password = { change: false };
|
$scope.password = { change: false };
|
||||||
|
|
||||||
|
// is the phone number required in _member_form?
|
||||||
|
$scope.phoneRequired = (phoneRequiredPromise.setting.value === 'true');
|
||||||
|
|
||||||
// the user subscription
|
// the user subscription
|
||||||
if (($scope.user.subscribed_plan != null) && ($scope.user.subscription != null)) {
|
if (($scope.user.subscribed_plan != null) && ($scope.user.subscription != null)) {
|
||||||
$scope.subscription = $scope.user.subscription;
|
$scope.subscription = $scope.user.subscription;
|
||||||
@ -948,8 +951,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',
|
Application.Controllers.controller('NewMemberController', ['$scope', '$state', '$stateParams', 'Member', 'Training', 'Group', 'CSRF', 'phoneRequiredPromise',
|
||||||
function ($scope, $state, $stateParams, Member, Training, Group, CSRF) {
|
function ($scope, $state, $stateParams, Member, Training, Group, CSRF, phoneRequiredPromise) {
|
||||||
CSRF.setMetaTags();
|
CSRF.setMetaTags();
|
||||||
|
|
||||||
/* PUBLIC SCOPE */
|
/* PUBLIC SCOPE */
|
||||||
@ -963,6 +966,9 @@ Application.Controllers.controller('NewMemberController', ['$scope', '$state', '
|
|||||||
// Should the password be set manually or generated?
|
// Should the password be set manually or generated?
|
||||||
$scope.password = { change: false };
|
$scope.password = { change: false };
|
||||||
|
|
||||||
|
// is the phone number required in _member_form?
|
||||||
|
$scope.phoneRequired = (phoneRequiredPromise.setting.value === 'true');
|
||||||
|
|
||||||
// Default member's profile parameters
|
// Default member's profile parameters
|
||||||
$scope.user = {
|
$scope.user = {
|
||||||
plan_interval: '',
|
plan_interval: '',
|
||||||
|
@ -10,8 +10,8 @@
|
|||||||
* DS207: Consider shorter variations of null checks
|
* DS207: Consider shorter variations of null checks
|
||||||
* 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('OpenAPIClientsController', ['$scope', 'clientsPromise', 'growl', 'OpenAPIClient', 'dialogs', '_t', 'Member', 'uiTourService',
|
Application.Controllers.controller('OpenAPIClientsController', ['$scope', 'clientsPromise', 'settingsPromise', 'growl', 'OpenAPIClient', 'dialogs', '_t', 'Member', 'uiTourService',
|
||||||
function ($scope, clientsPromise, growl, OpenAPIClient, dialogs, _t, Member, uiTourService) {
|
function ($scope, clientsPromise, settingsPromise, growl, OpenAPIClient, dialogs, _t, Member, uiTourService) {
|
||||||
/* PUBLIC SCOPE */
|
/* PUBLIC SCOPE */
|
||||||
|
|
||||||
// clients list
|
// clients list
|
||||||
@ -149,7 +149,7 @@ Application.Controllers.controller('OpenAPIClientsController', ['$scope', 'clien
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
// if the user has never seen the tour, and if the display behavior is not configured to manual triggering only, show the tour now
|
// if the user has never seen the tour, and if the display behavior is not configured to manual triggering only, show the tour now
|
||||||
if (Fablab.featureTourDisplay !== 'manual' && $scope.currentUser.profile.tours.indexOf('open-api') < 0) {
|
if (settingsPromise.feature_tour_display !== 'manual' && $scope.currentUser.profile.tours.indexOf('open-api') < 0) {
|
||||||
uitour.start();
|
uitour.start();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -18,8 +18,8 @@
|
|||||||
/**
|
/**
|
||||||
* Controller used in the prices edition page
|
* Controller used in the prices edition page
|
||||||
*/
|
*/
|
||||||
Application.Controllers.controller('EditPricingController', ['$scope', '$state', '$uibModal', '$filter', 'TrainingsPricing', 'Credit', 'Pricing', 'Plan', 'Coupon', 'plans', 'groups', 'growl', 'machinesPricesPromise', 'Price', 'dialogs', 'trainingsPricingsPromise', 'trainingsPromise', 'machineCreditsPromise', 'machinesPromise', 'trainingCreditsPromise', 'couponsPromise', 'spacesPromise', 'spacesPricesPromise', 'spacesCreditsPromise', '_t', 'Member', 'uiTourService',
|
Application.Controllers.controller('EditPricingController', ['$scope', '$state', '$uibModal', '$filter', 'TrainingsPricing', 'Credit', 'Pricing', 'Plan', 'Coupon', 'plans', 'groups', 'growl', 'machinesPricesPromise', 'Price', 'dialogs', 'trainingsPricingsPromise', 'trainingsPromise', 'machineCreditsPromise', 'machinesPromise', 'trainingCreditsPromise', 'couponsPromise', 'spacesPromise', 'spacesPricesPromise', 'spacesCreditsPromise', 'settingsPromise', '_t', 'Member', 'uiTourService',
|
||||||
function ($scope, $state, $uibModal, $filter, TrainingsPricing, Credit, Pricing, Plan, Coupon, plans, groups, growl, machinesPricesPromise, Price, dialogs, trainingsPricingsPromise, trainingsPromise, machineCreditsPromise, machinesPromise, trainingCreditsPromise, couponsPromise, spacesPromise, spacesPricesPromise, spacesCreditsPromise, _t, Member, uiTourService) {
|
function ($scope, $state, $uibModal, $filter, TrainingsPricing, Credit, Pricing, Plan, Coupon, plans, groups, growl, machinesPricesPromise, Price, dialogs, trainingsPricingsPromise, trainingsPromise, machineCreditsPromise, machinesPromise, trainingCreditsPromise, couponsPromise, spacesPromise, spacesPricesPromise, spacesCreditsPromise, settingsPromise, _t, Member, uiTourService) {
|
||||||
/* PUBLIC SCOPE */
|
/* PUBLIC SCOPE */
|
||||||
|
|
||||||
// List of machines prices (not considering any plan)
|
// List of machines prices (not considering any plan)
|
||||||
@ -76,6 +76,9 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
|||||||
// Default: we show only enabled plans
|
// Default: we show only enabled plans
|
||||||
$scope.planFiltering = 'enabled';
|
$scope.planFiltering = 'enabled';
|
||||||
|
|
||||||
|
// Default duration for the slots
|
||||||
|
$scope.slotDuration = parseInt(settingsPromise.slot_duration, 10);
|
||||||
|
|
||||||
// Available options for filtering plans by status
|
// Available options for filtering plans by status
|
||||||
$scope.filterDisabled = [
|
$scope.filterDisabled = [
|
||||||
'enabled',
|
'enabled',
|
||||||
@ -620,7 +623,7 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
|||||||
/**
|
/**
|
||||||
* Return the exemple price based on the configuration of the default slot duration.
|
* Return the exemple price based on the configuration of the default slot duration.
|
||||||
* @param type {string} 'hourly_rate' | *
|
* @param type {string} 'hourly_rate' | *
|
||||||
* @returns {number} price for Fablab.slotDuration minutes.
|
* @returns {number} price for "SLOT_DURATION" minutes.
|
||||||
*/
|
*/
|
||||||
$scope.examplePrice = function(type) {
|
$scope.examplePrice = function(type) {
|
||||||
const hourlyRate = 10;
|
const hourlyRate = 10;
|
||||||
@ -629,7 +632,7 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
|||||||
return $filter('currency')(hourlyRate);
|
return $filter('currency')(hourlyRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
const price = (hourlyRate / 60) * Fablab.slotDuration;
|
const price = (hourlyRate / 60) * $scope.slotDuration;
|
||||||
return $filter('currency')(price);
|
return $filter('currency')(price);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -673,7 +676,7 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
|||||||
content: _t('app.admin.tour.pricing.machines.content'),
|
content: _t('app.admin.tour.pricing.machines.content'),
|
||||||
placement: 'bottom'
|
placement: 'bottom'
|
||||||
});
|
});
|
||||||
if (!Fablab.withoutSpaces) {
|
if ($scope.modules.spaces) {
|
||||||
uitour.createStep({
|
uitour.createStep({
|
||||||
selector: '.plans-pricing .spaces-tab',
|
selector: '.plans-pricing .spaces-tab',
|
||||||
stepId: 'spaces',
|
stepId: 'spaces',
|
||||||
@ -727,7 +730,7 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
// if the user has never seen the tour, show him now
|
// if the user has never seen the tour, show him now
|
||||||
if (Fablab.featureTourDisplay !== 'manual' && $scope.currentUser.profile.tours.indexOf('pricing') < 0) {
|
if (settingsPromise.feature_tour_display !== 'manual' && $scope.currentUser.profile.tours.indexOf('pricing') < 0) {
|
||||||
uitour.start();
|
uitour.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,8 @@
|
|||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
Application.Controllers.controller('ProjectElementsController', ['$scope', '$state', 'Component', 'Licence', 'Theme', 'componentsPromise', 'licencesPromise', 'themesPromise', '_t', 'Member', 'uiTourService',
|
Application.Controllers.controller('AdminProjectsController', ['$scope', '$state', 'Component', 'Licence', 'Theme', 'componentsPromise', 'licencesPromise', 'themesPromise', '_t', 'Member', 'uiTourService', 'settingsPromise', 'growl',
|
||||||
function ($scope, $state, Component, Licence, Theme, componentsPromise, licencesPromise, themesPromise, _t, Member, uiTourService) {
|
function ($scope, $state, Component, Licence, Theme, componentsPromise, licencesPromise, themesPromise, _t, Member, uiTourService, settingsPromise, growl) {
|
||||||
// Materials list (plastic, wood ...)
|
// Materials list (plastic, wood ...)
|
||||||
$scope.components = componentsPromise;
|
$scope.components = componentsPromise;
|
||||||
|
|
||||||
@ -23,6 +23,12 @@ Application.Controllers.controller('ProjectElementsController', ['$scope', '$sta
|
|||||||
// Themes list (cooking, sport ...)
|
// Themes list (cooking, sport ...)
|
||||||
$scope.themes = themesPromise;
|
$scope.themes = themesPromise;
|
||||||
|
|
||||||
|
// Application settings
|
||||||
|
$scope.allSettings = settingsPromise;
|
||||||
|
|
||||||
|
// default tab: materials
|
||||||
|
$scope.tabs = { active: 0 };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves a new component / Update an existing material to the server (form validation callback)
|
* Saves a new component / Update an existing material to the server (form validation callback)
|
||||||
* @param data {Object} component name
|
* @param data {Object} component name
|
||||||
@ -156,18 +162,61 @@ Application.Controllers.controller('ProjectElementsController', ['$scope', '$sta
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup the feature-tour for the admin/project_elements page.
|
* When a file is sent to the server to test it against its MIME type,
|
||||||
|
* handle the result of the test.
|
||||||
|
*/
|
||||||
|
$scope.onTestFileComplete = function (res) {
|
||||||
|
if (res) {
|
||||||
|
growl.success(_t('app.admin.projects.settings.file_is_TYPE', { TYPE: res.type }));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For use with 'ng-class', returns the CSS class name for the uploads previews.
|
||||||
|
* The preview may show a placeholder or the content of the file depending on the upload state.
|
||||||
|
* @param v {*} any attribute, will be tested for truthiness (see JS evaluation rules)
|
||||||
|
*/
|
||||||
|
$scope.fileinputClass = function (v) {
|
||||||
|
if (v) {
|
||||||
|
return 'fileinput-exists';
|
||||||
|
} else {
|
||||||
|
return 'fileinput-new';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the initial dot from the given extension, if any
|
||||||
|
* @param extension {String}
|
||||||
|
* @returns {String}
|
||||||
|
*/
|
||||||
|
$scope.removeInitialDot = function (extension) {
|
||||||
|
if (extension.substr(0, 1) === '.') return $scope.lower(extension.substr(1));
|
||||||
|
|
||||||
|
return $scope.lower(extension);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the lowercase version of the provided string
|
||||||
|
* @param text {String}
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
$scope.lower = function (text) {
|
||||||
|
return text.toLowerCase();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup the feature-tour for the admin/projects page.
|
||||||
* This is intended as a contextual help (when pressing F1)
|
* This is intended as a contextual help (when pressing F1)
|
||||||
*/
|
*/
|
||||||
$scope.setupProjectElementsTour = function () {
|
$scope.setupProjectElementsTour = function () {
|
||||||
// get the tour defined by the ui-tour directive
|
// get the tour defined by the ui-tour directive
|
||||||
const uitour = uiTourService.getTourByName('project-elements');
|
const uitour = uiTourService.getTourByName('projects');
|
||||||
uitour.createStep({
|
uitour.createStep({
|
||||||
selector: 'body',
|
selector: 'body',
|
||||||
stepId: 'welcome',
|
stepId: 'welcome',
|
||||||
order: 0,
|
order: 0,
|
||||||
title: _t('app.admin.tour.project_elements.welcome.title'),
|
title: _t('app.admin.tour.projects.welcome.title'),
|
||||||
content: _t('app.admin.tour.project_elements.welcome.content'),
|
content: _t('app.admin.tour.projects.welcome.content'),
|
||||||
placement: 'bottom',
|
placement: 'bottom',
|
||||||
orphan: true
|
orphan: true
|
||||||
});
|
});
|
||||||
@ -175,30 +224,43 @@ Application.Controllers.controller('ProjectElementsController', ['$scope', '$sta
|
|||||||
selector: '.heading .abuses-button',
|
selector: '.heading .abuses-button',
|
||||||
stepId: 'abuses',
|
stepId: 'abuses',
|
||||||
order: 1,
|
order: 1,
|
||||||
title: _t('app.admin.tour.project_elements.abuses.title'),
|
title: _t('app.admin.tour.projects.abuses.title'),
|
||||||
content: _t('app.admin.tour.project_elements.abuses.content'),
|
content: _t('app.admin.tour.projects.abuses.content'),
|
||||||
placement: 'bottom',
|
placement: 'bottom',
|
||||||
popupClass: 'shift-left-40'
|
popupClass: 'shift-left-40'
|
||||||
});
|
});
|
||||||
|
uitour.createStep({
|
||||||
|
selector: '.projects .settings-tab',
|
||||||
|
stepId: 'settings',
|
||||||
|
order: 2,
|
||||||
|
title: _t('app.admin.tour.projects.settings.title'),
|
||||||
|
content: _t('app.admin.tour.projects.settings.content'),
|
||||||
|
placement: 'bottom',
|
||||||
|
popupClass: 'shift-left-50'
|
||||||
|
});
|
||||||
uitour.createStep({
|
uitour.createStep({
|
||||||
selector: 'body',
|
selector: 'body',
|
||||||
stepId: 'conclusion',
|
stepId: 'conclusion',
|
||||||
order: 2,
|
order: 3,
|
||||||
title: _t('app.admin.tour.conclusion.title'),
|
title: _t('app.admin.tour.conclusion.title'),
|
||||||
content: _t('app.admin.tour.conclusion.content'),
|
content: _t('app.admin.tour.conclusion.content'),
|
||||||
placement: 'bottom',
|
placement: 'bottom',
|
||||||
orphan: true
|
orphan: true
|
||||||
});
|
});
|
||||||
|
// on step change, change the active tab if needed
|
||||||
|
uitour.on('stepChanged', function (nextStep) {
|
||||||
|
if (nextStep.stepId === 'settings') { $scope.tabs.active = 3; }
|
||||||
|
});
|
||||||
// on tour end, save the status in database
|
// on tour end, save the status in database
|
||||||
uitour.on('ended', function () {
|
uitour.on('ended', function () {
|
||||||
if (uitour.getStatus() === uitour.Status.ON && $scope.currentUser.profile.tours.indexOf('project-elements') < 0) {
|
if (uitour.getStatus() === uitour.Status.ON && $scope.currentUser.profile.tours.indexOf('projects') < 0) {
|
||||||
Member.completeTour({ id: $scope.currentUser.id }, { tour: 'project-elements' }, function (res) {
|
Member.completeTour({ id: $scope.currentUser.id }, { tour: 'projects' }, function (res) {
|
||||||
$scope.currentUser.profile.tours = res.tours;
|
$scope.currentUser.profile.tours = res.tours;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// if the user has never seen the tour, show him now
|
// if the user has never seen the tour, show him now
|
||||||
if (Fablab.featureTourDisplay !== 'manual' && $scope.currentUser.profile.tours.indexOf('project-elements') < 0) {
|
if (settingsPromise.feature_tour_display !== 'manual' && $scope.currentUser.profile.tours.indexOf('projects') < 0) {
|
||||||
uitour.start();
|
uitour.start();
|
||||||
}
|
}
|
||||||
};
|
};
|
@ -54,9 +54,10 @@ Application.Controllers.controller('SettingsController', ['$scope', '$rootScope'
|
|||||||
// full history of privacy policy drafts
|
// full history of privacy policy drafts
|
||||||
$scope.privacyDraftsHistory = [];
|
$scope.privacyDraftsHistory = [];
|
||||||
|
|
||||||
|
// all settings as retrieved from database
|
||||||
|
$scope.allSettings = settingsPromise;
|
||||||
|
|
||||||
// various configurable settings
|
// various configurable settings
|
||||||
$scope.twitterSetting = { name: 'twitter_name', value: settingsPromise.twitter_name };
|
|
||||||
$scope.linkName = { name: 'link_name', value: settingsPromise.link_name };
|
|
||||||
$scope.aboutTitleSetting = { name: 'about_title', value: settingsPromise.about_title };
|
$scope.aboutTitleSetting = { name: 'about_title', value: settingsPromise.about_title };
|
||||||
$scope.aboutBodySetting = { name: 'about_body', value: settingsPromise.about_body };
|
$scope.aboutBodySetting = { name: 'about_body', value: settingsPromise.about_body };
|
||||||
$scope.privacyDpoSetting = { name: 'privacy_dpo', value: settingsPromise.privacy_dpo };
|
$scope.privacyDpoSetting = { name: 'privacy_dpo', value: settingsPromise.privacy_dpo };
|
||||||
@ -74,9 +75,7 @@ Application.Controllers.controller('SettingsController', ['$scope', '$rootScope'
|
|||||||
$scope.windowEnd = { name: 'booking_window_end', value: settingsPromise.booking_window_end };
|
$scope.windowEnd = { name: 'booking_window_end', value: settingsPromise.booking_window_end };
|
||||||
$scope.mainColorSetting = { name: 'main_color', value: settingsPromise.main_color };
|
$scope.mainColorSetting = { name: 'main_color', value: settingsPromise.main_color };
|
||||||
$scope.secondColorSetting = { name: 'secondary_color', value: settingsPromise.secondary_color };
|
$scope.secondColorSetting = { name: 'secondary_color', value: settingsPromise.secondary_color };
|
||||||
$scope.fablabName = { name: 'fablab_name', value: settingsPromise.fablab_name };
|
|
||||||
$scope.nameGenre = { name: 'name_genre', value: settingsPromise.name_genre };
|
$scope.nameGenre = { name: 'name_genre', value: settingsPromise.name_genre };
|
||||||
$scope.machinesSortBy = { name: 'machines_sort_by', value: settingsPromise.machines_sort_by };
|
|
||||||
$scope.cguFile = cguFile.custom_asset;
|
$scope.cguFile = cguFile.custom_asset;
|
||||||
$scope.cgvFile = cgvFile.custom_asset;
|
$scope.cgvFile = cgvFile.custom_asset;
|
||||||
$scope.customLogo = logoFile.custom_asset;
|
$scope.customLogo = logoFile.custom_asset;
|
||||||
@ -84,56 +83,6 @@ Application.Controllers.controller('SettingsController', ['$scope', '$rootScope'
|
|||||||
$scope.customFavicon = faviconFile.custom_asset;
|
$scope.customFavicon = faviconFile.custom_asset;
|
||||||
$scope.profileImage = profileImageFile.custom_asset;
|
$scope.profileImage = profileImageFile.custom_asset;
|
||||||
|
|
||||||
$scope.enableMove = {
|
|
||||||
name: 'booking_move_enable',
|
|
||||||
value: (settingsPromise.booking_move_enable === 'true')
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.moveDelay = {
|
|
||||||
name: 'booking_move_delay',
|
|
||||||
value: parseInt(settingsPromise.booking_move_delay, 10)
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.enableCancel = {
|
|
||||||
name: 'booking_cancel_enable',
|
|
||||||
value: (settingsPromise.booking_cancel_enable === 'true')
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.cancelDelay = {
|
|
||||||
name: 'booking_cancel_delay',
|
|
||||||
value: parseInt(settingsPromise.booking_cancel_delay, 10)
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.enableReminder = {
|
|
||||||
name: 'reminder_enable',
|
|
||||||
value: (settingsPromise.reminder_enable === 'true')
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.reminderDelay = {
|
|
||||||
name: 'reminder_delay',
|
|
||||||
value: parseInt(settingsPromise.reminder_delay, 10)
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.visibilityYearly = {
|
|
||||||
name: 'visibility_yearly',
|
|
||||||
value: parseInt(settingsPromise.visibility_yearly, 10)
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.visibilityOthers = {
|
|
||||||
name: 'visibility_others',
|
|
||||||
value: parseInt(settingsPromise.visibility_others, 10)
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.displayNameEnable = {
|
|
||||||
name: 'display_name_enable',
|
|
||||||
value: (settingsPromise.display_name_enable === 'true')
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.fabAnalytics = {
|
|
||||||
name: 'fab_analytics',
|
|
||||||
value: (settingsPromise.fab_analytics === 'true')
|
|
||||||
};
|
|
||||||
|
|
||||||
// By default, we display the currently published privacy policy
|
// By default, we display the currently published privacy policy
|
||||||
$scope.privacyPolicy = {
|
$scope.privacyPolicy = {
|
||||||
version: null,
|
version: null,
|
||||||
@ -381,10 +330,18 @@ Application.Controllers.controller('SettingsController', ['$scope', '$rootScope'
|
|||||||
placement: 'bottom',
|
placement: 'bottom',
|
||||||
orphan: true
|
orphan: true
|
||||||
});
|
});
|
||||||
|
uitour.createStep({
|
||||||
|
selector: '.admin-settings .general-page-tab',
|
||||||
|
stepId: 'general',
|
||||||
|
order: 1,
|
||||||
|
title: _t('app.admin.tour.settings.general.title'),
|
||||||
|
content: _t('app.admin.tour.settings.general.content'),
|
||||||
|
placement: 'bottom',
|
||||||
|
});
|
||||||
uitour.createStep({
|
uitour.createStep({
|
||||||
selector: '.admin-settings .home-page-content h4',
|
selector: '.admin-settings .home-page-content h4',
|
||||||
stepId: 'home',
|
stepId: 'home',
|
||||||
order: 1,
|
order: 2,
|
||||||
title: _t('app.admin.tour.settings.home.title'),
|
title: _t('app.admin.tour.settings.home.title'),
|
||||||
content: _t('app.admin.tour.settings.home.content'),
|
content: _t('app.admin.tour.settings.home.content'),
|
||||||
placement: 'bottom'
|
placement: 'bottom'
|
||||||
@ -392,7 +349,7 @@ Application.Controllers.controller('SettingsController', ['$scope', '$rootScope'
|
|||||||
uitour.createStep({
|
uitour.createStep({
|
||||||
selector: '.admin-settings .home-page-content .note-toolbar .note-insert div',
|
selector: '.admin-settings .home-page-content .note-toolbar .note-insert div',
|
||||||
stepId: 'components',
|
stepId: 'components',
|
||||||
order: 2,
|
order: 3,
|
||||||
title: _t('app.admin.tour.settings.components.title'),
|
title: _t('app.admin.tour.settings.components.title'),
|
||||||
content: _t('app.admin.tour.settings.components.content'),
|
content: _t('app.admin.tour.settings.components.content'),
|
||||||
placement: 'bottom'
|
placement: 'bottom'
|
||||||
@ -400,7 +357,7 @@ Application.Controllers.controller('SettingsController', ['$scope', '$rootScope'
|
|||||||
uitour.createStep({
|
uitour.createStep({
|
||||||
selector: '.admin-settings .home-page-content .note-toolbar .btn-codeview',
|
selector: '.admin-settings .home-page-content .note-toolbar .btn-codeview',
|
||||||
stepId: 'codeview',
|
stepId: 'codeview',
|
||||||
order: 3,
|
order: 4,
|
||||||
title: _t('app.admin.tour.settings.codeview.title'),
|
title: _t('app.admin.tour.settings.codeview.title'),
|
||||||
content: _t('app.admin.tour.settings.codeview.content'),
|
content: _t('app.admin.tour.settings.codeview.content'),
|
||||||
placement: 'bottom'
|
placement: 'bottom'
|
||||||
@ -408,7 +365,7 @@ Application.Controllers.controller('SettingsController', ['$scope', '$rootScope'
|
|||||||
uitour.createStep({
|
uitour.createStep({
|
||||||
selector: '.admin-settings .reset-button',
|
selector: '.admin-settings .reset-button',
|
||||||
stepId: 'reset',
|
stepId: 'reset',
|
||||||
order: 4,
|
order: 5,
|
||||||
title: _t('app.admin.tour.settings.reset.title'),
|
title: _t('app.admin.tour.settings.reset.title'),
|
||||||
content: _t('app.admin.tour.settings.reset.content'),
|
content: _t('app.admin.tour.settings.reset.content'),
|
||||||
placement: 'left'
|
placement: 'left'
|
||||||
@ -416,7 +373,7 @@ Application.Controllers.controller('SettingsController', ['$scope', '$rootScope'
|
|||||||
uitour.createStep({
|
uitour.createStep({
|
||||||
selector: '.admin-settings .home-page-style',
|
selector: '.admin-settings .home-page-style',
|
||||||
stepId: 'css',
|
stepId: 'css',
|
||||||
order: 5,
|
order: 6,
|
||||||
title: _t('app.admin.tour.settings.css.title'),
|
title: _t('app.admin.tour.settings.css.title'),
|
||||||
content: _t('app.admin.tour.settings.css.content'),
|
content: _t('app.admin.tour.settings.css.content'),
|
||||||
placement: 'top'
|
placement: 'top'
|
||||||
@ -424,7 +381,7 @@ Application.Controllers.controller('SettingsController', ['$scope', '$rootScope'
|
|||||||
uitour.createStep({
|
uitour.createStep({
|
||||||
selector: '.admin-settings .about-page-tab',
|
selector: '.admin-settings .about-page-tab',
|
||||||
stepId: 'about',
|
stepId: 'about',
|
||||||
order: 6,
|
order: 7,
|
||||||
title: _t('app.admin.tour.settings.about.title'),
|
title: _t('app.admin.tour.settings.about.title'),
|
||||||
content: _t('app.admin.tour.settings.about.content'),
|
content: _t('app.admin.tour.settings.about.content'),
|
||||||
placement: 'bottom'
|
placement: 'bottom'
|
||||||
@ -432,7 +389,7 @@ Application.Controllers.controller('SettingsController', ['$scope', '$rootScope'
|
|||||||
uitour.createStep({
|
uitour.createStep({
|
||||||
selector: '.admin-settings .privacy-page-tab',
|
selector: '.admin-settings .privacy-page-tab',
|
||||||
stepId: 'privacy',
|
stepId: 'privacy',
|
||||||
order: 7,
|
order: 8,
|
||||||
title: _t('app.admin.tour.settings.privacy.title'),
|
title: _t('app.admin.tour.settings.privacy.title'),
|
||||||
content: _t('app.admin.tour.settings.privacy.content'),
|
content: _t('app.admin.tour.settings.privacy.content'),
|
||||||
placement: 'bottom'
|
placement: 'bottom'
|
||||||
@ -440,15 +397,24 @@ Application.Controllers.controller('SettingsController', ['$scope', '$rootScope'
|
|||||||
uitour.createStep({
|
uitour.createStep({
|
||||||
selector: '.admin-settings .history-select',
|
selector: '.admin-settings .history-select',
|
||||||
stepId: 'draft',
|
stepId: 'draft',
|
||||||
order: 8,
|
order: 9,
|
||||||
title: _t('app.admin.tour.settings.draft.title'),
|
title: _t('app.admin.tour.settings.draft.title'),
|
||||||
content: _t('app.admin.tour.settings.draft.content'),
|
content: _t('app.admin.tour.settings.draft.content'),
|
||||||
placement: 'bottom'
|
placement: 'bottom'
|
||||||
});
|
});
|
||||||
|
uitour.createStep({
|
||||||
|
selector: '.admin-settings .reservations-page-tab',
|
||||||
|
stepId: 'reservations',
|
||||||
|
order: 10,
|
||||||
|
title: _t('app.admin.tour.settings.reservations.title'),
|
||||||
|
content: _t('app.admin.tour.settings.reservations.content'),
|
||||||
|
placement: 'bottom',
|
||||||
|
popupClass: 'shift-left-50'
|
||||||
|
});
|
||||||
uitour.createStep({
|
uitour.createStep({
|
||||||
selector: 'body',
|
selector: 'body',
|
||||||
stepId: 'conclusion',
|
stepId: 'conclusion',
|
||||||
order: 9,
|
order: 11,
|
||||||
title: _t('app.admin.tour.conclusion.title'),
|
title: _t('app.admin.tour.conclusion.title'),
|
||||||
content: _t('app.admin.tour.conclusion.content'),
|
content: _t('app.admin.tour.conclusion.content'),
|
||||||
placement: 'bottom',
|
placement: 'bottom',
|
||||||
@ -456,9 +422,11 @@ Application.Controllers.controller('SettingsController', ['$scope', '$rootScope'
|
|||||||
});
|
});
|
||||||
// on step change, change the active tab if needed
|
// on step change, change the active tab if needed
|
||||||
uitour.on('stepChanged', function (nextStep) {
|
uitour.on('stepChanged', function (nextStep) {
|
||||||
|
if (nextStep.stepId === 'general') { $scope.tabs.active = 0; }
|
||||||
if (nextStep.stepId === 'home' || nextStep.stepId === 'css') { $scope.tabs.active = 1; }
|
if (nextStep.stepId === 'home' || nextStep.stepId === 'css') { $scope.tabs.active = 1; }
|
||||||
if (nextStep.stepId === 'about') { $scope.tabs.active = 2; }
|
if (nextStep.stepId === 'about') { $scope.tabs.active = 2; }
|
||||||
if (nextStep.stepId === 'privacy' || nextStep.stepId === 'draft') { $scope.tabs.active = 3; }
|
if (nextStep.stepId === 'privacy' || nextStep.stepId === 'draft') { $scope.tabs.active = 3; }
|
||||||
|
if (nextStep.stepId === 'reservations') { $scope.tabs.active = 4; }
|
||||||
});
|
});
|
||||||
// on tour end, save the status in database
|
// on tour end, save the status in database
|
||||||
uitour.on('ended', function () {
|
uitour.on('ended', function () {
|
||||||
@ -469,7 +437,7 @@ Application.Controllers.controller('SettingsController', ['$scope', '$rootScope'
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
// if the user has never seen the tour, show him now
|
// if the user has never seen the tour, show him now
|
||||||
if (Fablab.featureTourDisplay !== 'manual' && $scope.currentUser.profile.tours.indexOf('settings') < 0) {
|
if ($scope.allSettings.feature_tour_display !== 'manual' && $scope.currentUser.profile.tours.indexOf('settings') < 0) {
|
||||||
uitour.start();
|
uitour.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -524,6 +492,19 @@ Application.Controllers.controller('SettingsController', ['$scope', '$rootScope'
|
|||||||
$scope.$watch('advancedSettings.open', function (newValue) {
|
$scope.$watch('advancedSettings.open', function (newValue) {
|
||||||
if (newValue) $scope.codeMirrorEditor.refresh();
|
if (newValue) $scope.codeMirrorEditor.refresh();
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// use the tours list, based on the selected value
|
||||||
|
$scope.$watch('allSettings.feature_tour_display', function (newValue, oldValue, scope) {
|
||||||
|
if (newValue === oldValue) return;
|
||||||
|
|
||||||
|
if (newValue === 'session') {
|
||||||
|
$scope.currentUser.profile.tours = Fablab.sessionTours;
|
||||||
|
} else if (newValue === 'once') {
|
||||||
|
Member.get({ id: $scope.currentUser.id }, function (user) {
|
||||||
|
$scope.currentUser.profile.tours = user.profile.tours;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// init the controller (call at the end !)
|
// init the controller (call at the end !)
|
||||||
|
@ -15,8 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
Application.Controllers.controller('StatisticsController', ['$scope', '$state', '$rootScope', '$uibModal', 'es', 'Member', '_t', 'membersPromise', 'statisticsPromise', 'uiTourService',
|
Application.Controllers.controller('StatisticsController', ['$scope', '$state', '$rootScope', '$uibModal', 'es', 'Member', '_t', 'membersPromise', 'statisticsPromise', 'uiTourService', 'settingsPromise',
|
||||||
function ($scope, $state, $rootScope, $uibModal, es, Member, _t, membersPromise, statisticsPromise, uiTourService) {
|
function ($scope, $state, $rootScope, $uibModal, es, Member, _t, membersPromise, statisticsPromise, uiTourService, settingsPromise) {
|
||||||
/* PRIVATE STATIC CONSTANTS */
|
/* PRIVATE STATIC CONSTANTS */
|
||||||
|
|
||||||
// search window size
|
// search window size
|
||||||
@ -179,9 +179,9 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
|||||||
*/
|
*/
|
||||||
$scope.hiddenTab = function (tab) {
|
$scope.hiddenTab = function (tab) {
|
||||||
if (tab.table) {
|
if (tab.table) {
|
||||||
if ((tab.es_type_key === 'subscription') && $rootScope.fablabWithoutPlans) {
|
if ((tab.es_type_key === 'subscription') && !$rootScope.modules.plans) {
|
||||||
return true;
|
return true;
|
||||||
} else return (tab.es_type_key === 'space') && $rootScope.fablabWithoutSpaces;
|
} else return (tab.es_type_key === 'space') && !$rootScope.modules.spaces;
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -388,7 +388,7 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
// if the user has never seen the tour, show him now
|
// if the user has never seen the tour, show him now
|
||||||
if (Fablab.featureTourDisplay !== 'manual' && $scope.currentUser.profile.tours.indexOf('statistics') < 0) {
|
if (settingsPromise.feature_tour_display !== 'manual' && $scope.currentUser.profile.tours.indexOf('statistics') < 0) {
|
||||||
uitour.start();
|
uitour.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -150,8 +150,8 @@ Application.Controllers.controller('EditTrainingController', [ '$scope', '$state
|
|||||||
/**
|
/**
|
||||||
* Controller used in the trainings management page, allowing admins users to see and manage the list of trainings and reservations.
|
* Controller used in the trainings management page, allowing admins users to see and manage the list of trainings and reservations.
|
||||||
*/
|
*/
|
||||||
Application.Controllers.controller('TrainingsAdminController', ['$scope', '$state', '$uibModal', 'Training', 'trainingsPromise', 'machinesPromise', '_t', 'growl', 'dialogs', 'Member', 'uiTourService',
|
Application.Controllers.controller('TrainingsAdminController', ['$scope', '$state', '$uibModal', 'Training', 'trainingsPromise', 'machinesPromise', '_t', 'growl', 'dialogs', 'Member', 'uiTourService', 'settingsPromise',
|
||||||
function ($scope, $state, $uibModal, Training, trainingsPromise, machinesPromise, _t, growl, dialogs, Member, uiTourService) {
|
function ($scope, $state, $uibModal, Training, trainingsPromise, machinesPromise, _t, growl, dialogs, Member, uiTourService, settingsPromise) {
|
||||||
|
|
||||||
// list of trainings
|
// list of trainings
|
||||||
$scope.trainings = trainingsPromise;
|
$scope.trainings = trainingsPromise;
|
||||||
@ -398,7 +398,7 @@ Application.Controllers.controller('TrainingsAdminController', ['$scope', '$stat
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
// if the user has never seen the tour, show him now
|
// if the user has never seen the tour, show him now
|
||||||
if (Fablab.featureTourDisplay !== 'manual' && $scope.currentUser.profile.tours.indexOf('trainings') < 0) {
|
if (settingsPromise.feature_tour_display !== 'manual' && $scope.currentUser.profile.tours.indexOf('trainings') < 0) {
|
||||||
uitour.start();
|
uitour.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,10 @@ Application.Controllers.controller('ApplicationController', ['$rootScope', '$sco
|
|||||||
return $uibModal.open({
|
return $uibModal.open({
|
||||||
templateUrl: '<%= asset_path "shared/signupModal.html" %>',
|
templateUrl: '<%= asset_path "shared/signupModal.html" %>',
|
||||||
size: 'md',
|
size: 'md',
|
||||||
controller: ['$scope', '$uibModalInstance', 'Group', 'CustomAsset', 'growl', '_t', function ($scope, $uibModalInstance, Group, CustomAsset, growl, _t) {
|
resolve: {
|
||||||
|
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['phone_required', 'recaptcha_site_key', 'confirmation_required']" }).$promise; }]
|
||||||
|
},
|
||||||
|
controller: ['$scope', '$uibModalInstance', 'Group', 'CustomAsset', 'settingsPromise', 'growl', '_t', function ($scope, $uibModalInstance, Group, CustomAsset, settingsPromise, growl, _t) {
|
||||||
// default parameters for the date picker in the account creation modal
|
// default parameters for the date picker in the account creation modal
|
||||||
$scope.datePicker = {
|
$scope.datePicker = {
|
||||||
format: Fablab.uibDateFormat,
|
format: Fablab.uibDateFormat,
|
||||||
@ -101,8 +104,11 @@ Application.Controllers.controller('ApplicationController', ['$rootScope', '$sco
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// is the phone number required to sign-up?
|
||||||
|
$scope.phoneRequired = (settingsPromise.phone_required === 'true');
|
||||||
|
|
||||||
// reCaptcha v2 site key (or undefined)
|
// reCaptcha v2 site key (or undefined)
|
||||||
$scope.recaptchaSiteKey = Fablab.recaptchaSiteKey;
|
$scope.recaptchaSiteKey = settingsPromise.recaptcha_site_key;
|
||||||
|
|
||||||
// callback to open the date picker (account creation modal)
|
// callback to open the date picker (account creation modal)
|
||||||
$scope.openDatePicker = function ($event) {
|
$scope.openDatePicker = function ($event) {
|
||||||
@ -147,7 +153,7 @@ Application.Controllers.controller('ApplicationController', ['$rootScope', '$sco
|
|||||||
return Auth.register($scope.user).then(function (user) {
|
return Auth.register($scope.user).then(function (user) {
|
||||||
if (user.id) {
|
if (user.id) {
|
||||||
// creation successful
|
// creation successful
|
||||||
$uibModalInstance.close(user);
|
$uibModalInstance.close({ user, settings: settingsPromise });
|
||||||
} else {
|
} else {
|
||||||
// the user was not saved in database, something wrong occurred
|
// the user was not saved in database, something wrong occurred
|
||||||
growl.error(_t('app.public.common.unexpected_error_occurred'));
|
growl.error(_t('app.public.common.unexpected_error_occurred'));
|
||||||
@ -168,13 +174,13 @@ Application.Controllers.controller('ApplicationController', ['$rootScope', '$sco
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
}]
|
}]
|
||||||
}).result['finally'](null).then(function (user) {
|
}).result['finally'](null).then(function (res) {
|
||||||
// when the account was created successfully, set the session to the newly created account
|
// when the account was created successfully, set the session to the newly created account
|
||||||
if(Fablab.userConfirmationNeededToSignIn) {
|
if(res.settings.confirmation_required) {
|
||||||
Auth._currentUser = null;
|
Auth._currentUser = null;
|
||||||
growl.info(_t('app.public.common.you_will_receive_confirmation_instructions_by_email_detailed'));
|
growl.info(_t('app.public.common.you_will_receive_confirmation_instructions_by_email_detailed'));
|
||||||
} else {
|
} else {
|
||||||
$scope.setCurrentUser(user);
|
$scope.setCurrentUser(res.user);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
<% end %>
|
<% end %>
|
||||||
@ -403,8 +409,15 @@ Application.Controllers.controller('ApplicationController', ['$rootScope', '$sco
|
|||||||
return $uibModal.open({
|
return $uibModal.open({
|
||||||
templateUrl: '<%= asset_path "shared/deviseModal.html" %>',
|
templateUrl: '<%= asset_path "shared/deviseModal.html" %>',
|
||||||
size: 'sm',
|
size: 'sm',
|
||||||
controller: ['$scope', '$uibModalInstance', '_t', function ($scope, $uibModalInstance, _t) {
|
resolve: {
|
||||||
|
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['confirmation_required']" }).$promise; }]
|
||||||
|
},
|
||||||
|
controller: ['$scope', '$uibModalInstance', '_t', 'settingsPromise', function ($scope, $uibModalInstance, _t, settingsPromise) {
|
||||||
const user = ($scope.user = {});
|
const user = ($scope.user = {});
|
||||||
|
|
||||||
|
// email confirmation required before user sign-in?
|
||||||
|
$scope.confirmationRequired = settingsPromise.confirmation_required;
|
||||||
|
|
||||||
$scope.login = function () {
|
$scope.login = function () {
|
||||||
Auth.login(user).then(function (user) {
|
Auth.login(user).then(function (user) {
|
||||||
// Authentication succeeded ...
|
// Authentication succeeded ...
|
||||||
@ -435,7 +448,7 @@ Application.Controllers.controller('ApplicationController', ['$rootScope', '$sco
|
|||||||
return $uibModalInstance.dismiss('confirmationNew');
|
return $uibModalInstance.dismiss('confirmationNew');
|
||||||
};
|
};
|
||||||
|
|
||||||
return $scope.openResetPassword = function (e) {
|
$scope.openResetPassword = function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
return $uibModalInstance.dismiss('resetPassword');
|
return $uibModalInstance.dismiss('resetPassword');
|
||||||
};
|
};
|
||||||
|
@ -32,7 +32,7 @@ Application.Controllers.controller('CookiesController', ['$scope', '$cookies', '
|
|||||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
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');
|
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
||||||
|
|
||||||
ga('create', Fablab.gaId, 'auto');
|
ga('create', Fablab.trackingId, 'auto');
|
||||||
ga('send', 'pageview');
|
ga('send', 'pageview');
|
||||||
/* eslint-enable */
|
/* eslint-enable */
|
||||||
};
|
};
|
||||||
@ -50,8 +50,8 @@ Application.Controllers.controller('CookiesController', ['$scope', '$cookies', '
|
|||||||
$scope.learnMoreUrl = '#!/privacy-policy';
|
$scope.learnMoreUrl = '#!/privacy-policy';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// if the GA_ID environment variable was not set, only functional cookies will be set, so user consent is not required
|
// if the tracking ID was not set in the settings, only functional cookies will be set, so user consent is not required
|
||||||
if (!Fablab.gaId) $scope.cookiesState = 'ignore';
|
if (!Fablab.trackingId) $scope.cookiesState = 'ignore';
|
||||||
};
|
};
|
||||||
|
|
||||||
const readCookie = function () {
|
const readCookie = function () {
|
||||||
|
@ -13,8 +13,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('EventsController', ['$scope', '$state', 'Event', 'categoriesPromise', 'themesPromise', 'ageRangesPromise',
|
Application.Controllers.controller('EventsController', ['$scope', '$state', 'Event', 'categoriesPromise', 'themesPromise', 'ageRangesPromise', 'settingsPromise',
|
||||||
function ($scope, $state, Event, categoriesPromise, themesPromise, ageRangesPromise) {
|
function ($scope, $state, Event, categoriesPromise, themesPromise, ageRangesPromise, settingsPromise) {
|
||||||
/* PUBLIC SCOPE */
|
/* PUBLIC SCOPE */
|
||||||
|
|
||||||
// The events displayed on the page
|
// The events displayed on the page
|
||||||
@ -305,7 +305,7 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
|||||||
const amountToPay = helpers.getAmountToPay($scope.reserve.amountTotal, wallet.amount);
|
const amountToPay = helpers.getAmountToPay($scope.reserve.amountTotal, wallet.amount);
|
||||||
if ((AuthService.isAuthorized(['member']) && amountToPay > 0)
|
if ((AuthService.isAuthorized(['member']) && amountToPay > 0)
|
||||||
|| (AuthService.isAuthorized('manager') && $scope.ctrl.member.id === $rootScope.currentUser.id && amountToPay > 0)) {
|
|| (AuthService.isAuthorized('manager') && $scope.ctrl.member.id === $rootScope.currentUser.id && amountToPay > 0)) {
|
||||||
if ($rootScope.fablabWithoutOnlinePayment) {
|
if (settingsPromise.online_payment_module !== 'true') {
|
||||||
growl.error(_t('app.public.events_show.online_payment_disabled'));
|
growl.error(_t('app.public.events_show.online_payment_disabled'));
|
||||||
} else {
|
} else {
|
||||||
return payByStripe(reservation);
|
return payByStripe(reservation);
|
||||||
@ -698,10 +698,11 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
|||||||
},
|
},
|
||||||
cartItems () {
|
cartItems () {
|
||||||
return mkRequestParams(reservation, $scope.coupon.applied);
|
return mkRequestParams(reservation, $scope.coupon.applied);
|
||||||
}
|
},
|
||||||
|
stripeKey: ['Setting', function (Setting) { return Setting.get({ name: 'stripe_public_key' }).$promise; }]
|
||||||
},
|
},
|
||||||
controller: ['$scope', '$uibModalInstance', '$state', 'reservation', 'price', 'cgv', 'Auth', 'Reservation', 'growl', 'wallet', 'helpers', '$filter', 'coupon', 'cartItems',
|
controller: ['$scope', '$uibModalInstance', '$state', 'reservation', 'price', 'cgv', 'Auth', 'Reservation', 'growl', 'wallet', 'helpers', '$filter', 'coupon', 'cartItems', 'stripeKey',
|
||||||
function ($scope, $uibModalInstance, $state, reservation, price, cgv, Auth, Reservation, growl, wallet, helpers, $filter, coupon, cartItems) {
|
function ($scope, $uibModalInstance, $state, reservation, price, cgv, Auth, Reservation, growl, wallet, helpers, $filter, coupon, cartItems, stripeKey) {
|
||||||
// User's wallet amount
|
// User's wallet amount
|
||||||
$scope.walletAmount = wallet.amount;
|
$scope.walletAmount = wallet.amount;
|
||||||
|
|
||||||
@ -720,8 +721,11 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
|||||||
// Used in wallet info template to interpolate some translations
|
// Used in wallet info template to interpolate some translations
|
||||||
$scope.numberFilter = $filter('number');
|
$scope.numberFilter = $filter('number');
|
||||||
|
|
||||||
|
// stripe publishable key
|
||||||
|
$scope.stripeKey = stripeKey.setting.value;
|
||||||
|
|
||||||
// Callback to handle the post-payment and reservation
|
// Callback to handle the post-payment and reservation
|
||||||
return $scope.onPaymentSuccess = function (reservation) {
|
$scope.onPaymentSuccess = function (reservation) {
|
||||||
$uibModalInstance.close(reservation);
|
$uibModalInstance.close(reservation);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -859,6 +863,7 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
|||||||
controller: 'ReserveSlotSameTimeController',
|
controller: 'ReserveSlotSameTimeController',
|
||||||
resolve: {
|
resolve: {
|
||||||
sameTimeReservations: function() { return sameTimeReservations; },
|
sameTimeReservations: function() { return sameTimeReservations; },
|
||||||
|
bookOverlappingSlotsPromise: ['Setting', function (Setting) { return Setting.get({ name: 'book_overlapping_slots' }).$promise; }]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
modalInstance.result.then(callback);
|
modalInstance.result.then(callback);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
Application.Controllers.controller('HomeController', ['$scope', '$stateParams', '$translatePartialLoader', 'AuthService', 'settingsPromise', 'Member', 'uiTourService', '_t', 'Help',
|
Application.Controllers.controller('HomeController', ['$scope', '$stateParams', '$translatePartialLoader', 'AuthService', 'settingsPromise', 'Member', 'uiTourService', '_t',
|
||||||
function ($scope, $stateParams, $translatePartialLoader, AuthService, settingsPromise, Member, uiTourService, _t, Help) {
|
function ($scope, $stateParams, $translatePartialLoader, AuthService, settingsPromise, Member, uiTourService, _t) {
|
||||||
/* PUBLIC SCOPE */
|
/* PUBLIC SCOPE */
|
||||||
|
|
||||||
// Home page HTML content
|
// Home page HTML content
|
||||||
@ -140,7 +140,7 @@ Application.Controllers.controller('HomeController', ['$scope', '$stateParams',
|
|||||||
content: _t('app.public.tour.welcome.machines.content'),
|
content: _t('app.public.tour.welcome.machines.content'),
|
||||||
placement: 'right'
|
placement: 'right'
|
||||||
});
|
});
|
||||||
if (!Fablab.withoutSpaces) {
|
if ($scope.modules.spaces) {
|
||||||
uitour.createStep({
|
uitour.createStep({
|
||||||
selector: '.nav-primary li.reserve-space-link',
|
selector: '.nav-primary li.reserve-space-link',
|
||||||
stepId: 'spaces',
|
stepId: 'spaces',
|
||||||
@ -303,7 +303,7 @@ Application.Controllers.controller('HomeController', ['$scope', '$stateParams',
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
// if the user has never seen the tour, show him now
|
// if the user has never seen the tour, show him now
|
||||||
if (Fablab.featureTourDisplay !== 'manual' && $scope.currentUser.profile.tours.indexOf('welcome') < 0) {
|
if (settingsPromise.feature_tour_display !== 'manual' && $scope.currentUser.profile.tours.indexOf('welcome') < 0) {
|
||||||
uitour.start();
|
uitour.start();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -180,8 +180,8 @@ const _reserveMachine = function (machine, e) {
|
|||||||
/**
|
/**
|
||||||
* Controller used in the public listing page, allowing everyone to see the list of machines
|
* Controller used in the public listing page, allowing everyone to see the list of machines
|
||||||
*/
|
*/
|
||||||
Application.Controllers.controller('MachinesController', ['$scope', '$state', '_t', 'AuthService', 'Machine', '$uibModal', 'machinesPromise', 'Member', 'uiTourService',
|
Application.Controllers.controller('MachinesController', ['$scope', '$state', '_t', 'AuthService', 'Machine', '$uibModal', 'machinesPromise', 'settingsPromise', 'Member', 'uiTourService',
|
||||||
function ($scope, $state, _t, AuthService, Machine, $uibModal, machinesPromise, Member, uiTourService) {
|
function ($scope, $state, _t, AuthService, Machine, $uibModal, machinesPromise, settingsPromise, Member, uiTourService) {
|
||||||
/* PUBLIC SCOPE */
|
/* PUBLIC SCOPE */
|
||||||
|
|
||||||
// Retrieve the list of machines
|
// Retrieve the list of machines
|
||||||
@ -281,7 +281,7 @@ Application.Controllers.controller('MachinesController', ['$scope', '$state', '_
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
// if the user has never seen the tour, show him now
|
// if the user has never seen the tour, show him now
|
||||||
if (Fablab.featureTourDisplay !== 'manual' && $scope.currentUser.profile.tours.indexOf('machines') < 0) {
|
if (settingsPromise.feature_tour_display !== 'manual' && $scope.currentUser.profile.tours.indexOf('machines') < 0) {
|
||||||
uitour.start();
|
uitour.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ Application.Controllers.controller('MainNavController', ['$scope', function ($sc
|
|||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
if (!Fablab.withoutPlans) {
|
if ($scope.modules.plans) {
|
||||||
$scope.navLinks.push({
|
$scope.navLinks.push({
|
||||||
state: 'app.public.plans',
|
state: 'app.public.plans',
|
||||||
linkText: 'app.public.common.subscriptions',
|
linkText: 'app.public.common.subscriptions',
|
||||||
@ -67,7 +67,7 @@ Application.Controllers.controller('MainNavController', ['$scope', function ($sc
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Fablab.withoutSpaces) {
|
if ($scope.modules.spaces) {
|
||||||
$scope.navLinks.splice(4, 0, {
|
$scope.navLinks.splice(4, 0, {
|
||||||
state: 'app.public.spaces_list',
|
state: 'app.public.spaces_list',
|
||||||
linkText: 'app.public.common.reserve_a_space',
|
linkText: 'app.public.common.reserve_a_space',
|
||||||
@ -138,8 +138,8 @@ Application.Controllers.controller('MainNavController', ['$scope', function ($sc
|
|||||||
authorizedRoles: ['admin']
|
authorizedRoles: ['admin']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
state: 'app.admin.project_elements',
|
state: 'app.admin.projects',
|
||||||
linkText: 'app.public.common.manage_the_projects_elements',
|
linkText: 'app.public.common.projects',
|
||||||
linkIcon: 'tasks',
|
linkIcon: 'tasks',
|
||||||
authorizedRoles: ['admin']
|
authorizedRoles: ['admin']
|
||||||
},
|
},
|
||||||
@ -153,7 +153,7 @@ Application.Controllers.controller('MainNavController', ['$scope', function ($sc
|
|||||||
|
|
||||||
$scope.adminNavLinks = adminNavLinks;
|
$scope.adminNavLinks = adminNavLinks;
|
||||||
|
|
||||||
if (!Fablab.withoutSpaces) {
|
if ($scope.modules.spaces) {
|
||||||
return $scope.adminNavLinks.splice(3, 0, {
|
return $scope.adminNavLinks.splice(3, 0, {
|
||||||
state: 'app.public.spaces_list',
|
state: 'app.public.spaces_list',
|
||||||
linkText: 'app.public.common.manage_the_spaces',
|
linkText: 'app.public.common.manage_the_spaces',
|
||||||
|
@ -72,8 +72,8 @@ Application.Controllers.controller('MembersController', ['$scope', 'Member', 'me
|
|||||||
/**
|
/**
|
||||||
* Controller used when editing the current user's profile (in dashboard)
|
* Controller used when editing the current user's profile (in dashboard)
|
||||||
*/
|
*/
|
||||||
Application.Controllers.controller('EditProfileController', ['$scope', '$rootScope', '$state', '$window', '$sce', '$cookies', '$injector', 'Member', 'Auth', 'Session', 'activeProviderPromise', 'growl', 'dialogs', 'CSRF', 'memberPromise', 'groups', '_t',
|
Application.Controllers.controller('EditProfileController', ['$scope', '$rootScope', '$state', '$window', '$sce', '$cookies', '$injector', 'Member', 'Auth', 'Session', 'activeProviderPromise', 'phoneRequiredPromise', 'growl', 'dialogs', 'CSRF', 'memberPromise', 'groups', '_t',
|
||||||
function ($scope, $rootScope, $state, $window, $sce, $cookies, $injector, Member, Auth, Session, activeProviderPromise, growl, dialogs, CSRF, memberPromise, groups, _t) {
|
function ($scope, $rootScope, $state, $window, $sce, $cookies, $injector, Member, Auth, Session, activeProviderPromise, phoneRequiredPromise, growl, dialogs, CSRF, memberPromise, groups, _t) {
|
||||||
/* PUBLIC SCOPE */
|
/* PUBLIC SCOPE */
|
||||||
|
|
||||||
// API URL where the form will be posted
|
// API URL where the form will be posted
|
||||||
@ -110,6 +110,9 @@ Application.Controllers.controller('EditProfileController', ['$scope', '$rootSco
|
|||||||
// Should the passord be modified?
|
// Should the passord be modified?
|
||||||
$scope.password = { change: false };
|
$scope.password = { change: false };
|
||||||
|
|
||||||
|
// is the phone number required in _member_form?
|
||||||
|
$scope.phoneRequired = (phoneRequiredPromise.setting.value === 'true');
|
||||||
|
|
||||||
// Angular-Bootstrap datepicker configuration for birthday
|
// Angular-Bootstrap datepicker configuration for birthday
|
||||||
$scope.datePicker = {
|
$scope.datePicker = {
|
||||||
format: Fablab.uibDateFormat,
|
format: Fablab.uibDateFormat,
|
||||||
|
@ -12,8 +12,8 @@
|
|||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScope', '$state', '$uibModal', 'Auth', 'AuthService', 'dialogs', 'growl', 'plansPromise', 'groupsPromise', 'Subscription', 'Member', 'subscriptionExplicationsPromise', '_t', 'Wallet', 'helpers',
|
Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScope', '$state', '$uibModal', 'Auth', 'AuthService', 'dialogs', 'growl', 'plansPromise', 'groupsPromise', 'Subscription', 'Member', 'subscriptionExplicationsPromise', '_t', 'Wallet', 'helpers', 'settingsPromise',
|
||||||
function ($scope, $rootScope, $state, $uibModal, Auth, AuthService, dialogs, growl, plansPromise, groupsPromise, Subscription, Member, subscriptionExplicationsPromise, _t, Wallet, helpers) {
|
function ($scope, $rootScope, $state, $uibModal, Auth, AuthService, dialogs, growl, plansPromise, groupsPromise, Subscription, Member, subscriptionExplicationsPromise, _t, Wallet, helpers, settingsPromise) {
|
||||||
/* PUBLIC SCOPE */
|
/* PUBLIC SCOPE */
|
||||||
|
|
||||||
// list of groups
|
// list of groups
|
||||||
@ -92,7 +92,7 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
|||||||
const amountToPay = helpers.getAmountToPay($scope.cart.total, wallet.amount);
|
const amountToPay = helpers.getAmountToPay($scope.cart.total, wallet.amount);
|
||||||
if ((AuthService.isAuthorized('member') && amountToPay > 0)
|
if ((AuthService.isAuthorized('member') && amountToPay > 0)
|
||||||
|| (AuthService.isAuthorized('manager') && $scope.ctrl.member.id === $rootScope.currentUser.id && amountToPay > 0)) {
|
|| (AuthService.isAuthorized('manager') && $scope.ctrl.member.id === $rootScope.currentUser.id && amountToPay > 0)) {
|
||||||
if ($rootScope.fablabWithoutOnlinePayment) {
|
if (settingsPromise.online_payment_module !== 'true') {
|
||||||
growl.error(_t('app.public.plans.online_payment_disabled'));
|
growl.error(_t('app.public.plans.online_payment_disabled'));
|
||||||
} else {
|
} else {
|
||||||
return payByStripe();
|
return payByStripe();
|
||||||
@ -244,10 +244,11 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
|||||||
wallet () {
|
wallet () {
|
||||||
return Wallet.getWalletByUser({ user_id: $scope.ctrl.member.id }).$promise;
|
return Wallet.getWalletByUser({ user_id: $scope.ctrl.member.id }).$promise;
|
||||||
},
|
},
|
||||||
coupon () { return $scope.coupon.applied; }
|
coupon () { return $scope.coupon.applied; },
|
||||||
|
stripeKey: ['Setting', function (Setting) { return Setting.get({ name: 'stripe_public_key' }).$promise; }]
|
||||||
},
|
},
|
||||||
controller: ['$scope', '$uibModalInstance', '$state', 'selectedPlan', 'member', 'price', 'Subscription', 'CustomAsset', 'wallet', 'helpers', '$filter', 'coupon',
|
controller: ['$scope', '$uibModalInstance', '$state', 'selectedPlan', 'member', 'price', 'Subscription', 'CustomAsset', 'wallet', 'helpers', '$filter', 'coupon', 'stripeKey',
|
||||||
function ($scope, $uibModalInstance, $state, selectedPlan, member, price, Subscription, CustomAsset, wallet, helpers, $filter, coupon) {
|
function ($scope, $uibModalInstance, $state, selectedPlan, member, price, Subscription, CustomAsset, wallet, helpers, $filter, coupon, stripeKey) {
|
||||||
// User's wallet amount
|
// User's wallet amount
|
||||||
$scope.walletAmount = wallet.amount;
|
$scope.walletAmount = wallet.amount;
|
||||||
|
|
||||||
@ -268,6 +269,9 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// stripe publishable key
|
||||||
|
$scope.stripeKey = stripeKey.setting.value;
|
||||||
|
|
||||||
// retrieve the CGV
|
// retrieve the CGV
|
||||||
CustomAsset.get({ name: 'cgv-file' }, function (cgv) { $scope.cgv = cgv.custom_asset; });
|
CustomAsset.get({ name: 'cgv-file' }, function (cgv) { $scope.cgv = cgv.custom_asset; });
|
||||||
|
|
||||||
|
@ -13,8 +13,8 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
Application.Controllers.controller('CompleteProfileController', ['$scope', '$rootScope', '$state', '$window', '_t', 'growl', 'CSRF', 'Auth', 'Member', 'settingsPromise', 'activeProviderPromise', 'groupsPromise', 'cguFile', 'memberPromise', 'Session', 'dialogs', 'AuthProvider',
|
Application.Controllers.controller('CompleteProfileController', ['$scope', '$rootScope', '$state', '$window', '_t', 'growl', 'CSRF', 'Auth', 'Member', 'settingsPromise', 'activeProviderPromise', 'groupsPromise', 'cguFile', 'memberPromise', 'Session', 'dialogs', 'AuthProvider', 'phoneRequiredPromise',
|
||||||
function ($scope, $rootScope, $state, $window, _t, growl, CSRF, Auth, Member, settingsPromise, activeProviderPromise, groupsPromise, cguFile, memberPromise, Session, dialogs, AuthProvider) {
|
function ($scope, $rootScope, $state, $window, _t, growl, CSRF, Auth, Member, settingsPromise, activeProviderPromise, groupsPromise, cguFile, memberPromise, Session, dialogs, AuthProvider, phoneRequiredPromise) {
|
||||||
/* PUBLIC SCOPE */
|
/* PUBLIC SCOPE */
|
||||||
|
|
||||||
// API URL where the form will be posted
|
// API URL where the form will be posted
|
||||||
@ -47,6 +47,9 @@ Application.Controllers.controller('CompleteProfileController', ['$scope', '$roo
|
|||||||
// CGU
|
// CGU
|
||||||
$scope.cgu = cguFile.custom_asset;
|
$scope.cgu = cguFile.custom_asset;
|
||||||
|
|
||||||
|
// is the phone number required in _member_form?
|
||||||
|
$scope.phoneRequired = (phoneRequiredPromise.setting.value === 'true');
|
||||||
|
|
||||||
// Angular-Bootstrap datepicker configuration for birthday
|
// Angular-Bootstrap datepicker configuration for birthday
|
||||||
$scope.datePicker = {
|
$scope.datePicker = {
|
||||||
format: Fablab.uibDateFormat,
|
format: Fablab.uibDateFormat,
|
||||||
|
@ -87,7 +87,7 @@ class ProjectsController {
|
|||||||
$scope.totalSteps = $scope.project.project_steps_attributes.length;
|
$scope.totalSteps = $scope.project.project_steps_attributes.length;
|
||||||
|
|
||||||
// List of extensions allowed for CAD attachements upload
|
// List of extensions allowed for CAD attachements upload
|
||||||
$scope.allowedExtensions = allowedExtensions;
|
$scope.allowedExtensions = allowedExtensions.setting.value.split(' ');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For use with ngUpload (https://github.com/twilson63/ngUpload).
|
* For use with ngUpload (https://github.com/twilson63/ngUpload).
|
||||||
@ -266,8 +266,8 @@ class ProjectsController {
|
|||||||
/**
|
/**
|
||||||
* Controller used on projects listing page
|
* Controller used on projects listing page
|
||||||
*/
|
*/
|
||||||
Application.Controllers.controller('ProjectsController', ['$scope', '$state', 'Project', 'machinesPromise', 'themesPromise', 'componentsPromise', 'paginationService', 'OpenlabProject', '$window', 'growl', '_t', '$location', '$timeout',
|
Application.Controllers.controller('ProjectsController', ['$scope', '$state', 'Project', 'machinesPromise', 'themesPromise', 'componentsPromise', 'paginationService', 'OpenlabProject', '$window', 'growl', '_t', '$location', '$timeout', 'settingsPromise', 'openLabActive',
|
||||||
function ($scope, $state, Project, machinesPromise, themesPromise, componentsPromise, paginationService, OpenlabProject, $window, growl, _t, $location, $timeout) {
|
function ($scope, $state, Project, machinesPromise, themesPromise, componentsPromise, paginationService, OpenlabProject, $window, growl, _t, $location, $timeout, settingsPromise, openLabActive) {
|
||||||
/* PRIVATE STATIC CONSTANTS */
|
/* PRIVATE STATIC CONSTANTS */
|
||||||
|
|
||||||
// Number of projects added to the page when the user clicks on 'load more projects'
|
// Number of projects added to the page when the user clicks on 'load more projects'
|
||||||
@ -277,11 +277,11 @@ Application.Controllers.controller('ProjectsController', ['$scope', '$state', 'P
|
|||||||
/* PUBLIC SCOPE */
|
/* PUBLIC SCOPE */
|
||||||
|
|
||||||
// Fab-manager's instance ID in the openLab network
|
// Fab-manager's instance ID in the openLab network
|
||||||
$scope.openlabAppId = Fablab.openlabAppId;
|
$scope.openlabAppId = settingsPromise.openlab_app_id
|
||||||
|
|
||||||
// Is openLab enabled on the instance?
|
// Is openLab enabled on the instance?
|
||||||
$scope.openlab = {
|
$scope.openlab = {
|
||||||
projectsActive: Fablab.openlabProjectsActive,
|
projectsActive: openLabActive.isPresent,
|
||||||
searchOverWholeNetwork: false
|
searchOverWholeNetwork: false
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -390,32 +390,32 @@ Application.Controllers.controller('ProjectsController', ['$scope', '$state', 'P
|
|||||||
if ($location.$$search.whole_network === 'f') {
|
if ($location.$$search.whole_network === 'f') {
|
||||||
$scope.openlab.searchOverWholeNetwork = false;
|
$scope.openlab.searchOverWholeNetwork = false;
|
||||||
} else {
|
} else {
|
||||||
$scope.openlab.searchOverWholeNetwork = ($scope.openlab.projectsActive && Fablab.openlabDefault) || false;
|
$scope.openlab.searchOverWholeNetwork = ($scope.openlab.projectsActive && settingsPromise.openlab_default === 'true') || false;
|
||||||
}
|
}
|
||||||
return $scope.triggerSearch();
|
return $scope.triggerSearch();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* function to update url query param, little hack to turn off reloadOnSearch and re-enable it after setting the params
|
* function to update url query param, little hack to turn off reloadOnSearch and re-enable it after we set the params.
|
||||||
* params example: 'q' , 'presse-purée'
|
* params example: 'q' , 'presse-purée'
|
||||||
*/
|
*/
|
||||||
var updateUrlParam = function (name, value) {
|
const updateUrlParam = function (name, value) {
|
||||||
$state.current.reloadOnSearch = false;
|
$state.current.reloadOnSearch = false;
|
||||||
$location.search(name, value);
|
$location.search(name, value);
|
||||||
return $timeout(function () { $state.current.reloadOnSearch = undefined; });
|
return $timeout(function () { $state.current.reloadOnSearch = undefined; });
|
||||||
};
|
};
|
||||||
|
|
||||||
var loadMoreCallback = function (projectsPromise) {
|
const loadMoreCallback = function (projectsPromise) {
|
||||||
$scope.projects = $scope.projects.concat(projectsPromise.projects);
|
$scope.projects = $scope.projects.concat(projectsPromise.projects);
|
||||||
return updateUrlParam('page', $scope.projectsPagination.currentPage);
|
return updateUrlParam('page', $scope.projectsPagination.currentPage);
|
||||||
};
|
};
|
||||||
|
|
||||||
var loadMoreOpenlabCallback = function (projectsPromise) {
|
const loadMoreOpenlabCallback = function (projectsPromise) {
|
||||||
$scope.projects = $scope.projects.concat(normalizeProjectsAttrs(projectsPromise.projects));
|
$scope.projects = $scope.projects.concat(normalizeProjectsAttrs(projectsPromise.projects));
|
||||||
return updateUrlParam('page', $scope.projectsPagination.currentPage);
|
return updateUrlParam('page', $scope.projectsPagination.currentPage);
|
||||||
};
|
};
|
||||||
|
|
||||||
var normalizeProjectsAttrs = function (projects) {
|
const normalizeProjectsAttrs = function (projects) {
|
||||||
return projects.map(function (project) {
|
return projects.map(function (project) {
|
||||||
project.project_image = project.image_url;
|
project.project_image = project.image_url;
|
||||||
return project;
|
return project;
|
||||||
@ -501,14 +501,14 @@ Application.Controllers.controller('EditProjectController', ['$rootScope', '$sco
|
|||||||
/**
|
/**
|
||||||
* Controller used in the public project's details page
|
* Controller used in the public project's details page
|
||||||
*/
|
*/
|
||||||
Application.Controllers.controller('ShowProjectController', ['$scope', '$state', 'projectPromise', '$location', '$uibModal', 'dialogs', '_t',
|
Application.Controllers.controller('ShowProjectController', ['$scope', '$state', 'projectPromise', 'shortnamePromise', '$location', '$uibModal', 'dialogs', '_t',
|
||||||
function ($scope, $state, projectPromise, $location, $uibModal, dialogs, _t) {
|
function ($scope, $state, projectPromise, shortnamePromise, $location, $uibModal, dialogs, _t) {
|
||||||
/* PUBLIC SCOPE */
|
/* PUBLIC SCOPE */
|
||||||
|
|
||||||
// Store the project's details
|
// Store the project's details
|
||||||
$scope.project = projectPromise;
|
$scope.project = projectPromise;
|
||||||
$scope.projectUrl = $location.absUrl();
|
$scope.projectUrl = $location.absUrl();
|
||||||
$scope.disqusShortname = Fablab.disqusShortname;
|
$scope.disqusShortname = shortnamePromise.setting.value;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test if the provided user has the edition rights on the current project
|
* Test if the provided user has the edition rights on the current project
|
||||||
|
@ -98,8 +98,8 @@ class SpacesController {
|
|||||||
/**
|
/**
|
||||||
* Controller used in the public listing page, allowing everyone to see the list of spaces
|
* Controller used in the public listing page, allowing everyone to see the list of spaces
|
||||||
*/
|
*/
|
||||||
Application.Controllers.controller('SpacesController', ['$scope', '$state', 'spacesPromise', 'AuthService', '_t', 'Member', 'uiTourService',
|
Application.Controllers.controller('SpacesController', ['$scope', '$state', 'spacesPromise', 'AuthService', '_t', 'Member', 'uiTourService', 'settingsPromise',
|
||||||
function ($scope, $state, spacesPromise, AuthService, _t, Member, uiTourService) {
|
function ($scope, $state, spacesPromise, AuthService, _t, Member, uiTourService, settingsPromise) {
|
||||||
/* PUBLIC SCOPE */
|
/* PUBLIC SCOPE */
|
||||||
|
|
||||||
// Retrieve the list of spaces
|
// Retrieve the list of spaces
|
||||||
@ -193,7 +193,7 @@ Application.Controllers.controller('SpacesController', ['$scope', '$state', 'spa
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
// if the user has never seen the tour, show him now
|
// if the user has never seen the tour, show him now
|
||||||
if (Fablab.featureTourDisplay !== 'manual' && $scope.currentUser.profile.tours.indexOf('spaces') < 0) {
|
if (settingsPromise.feature_tour_display !== 'manual' && $scope.currentUser.profile.tours.indexOf('spaces') < 0) {
|
||||||
uitour.start();
|
uitour.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -361,7 +361,8 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
|||||||
size: 'md',
|
size: 'md',
|
||||||
controller: 'ReserveSlotSameTimeController',
|
controller: 'ReserveSlotSameTimeController',
|
||||||
resolve: {
|
resolve: {
|
||||||
sameTimeReservations: function() { return sameTimeReservations; }
|
sameTimeReservations: function() { return sameTimeReservations; },
|
||||||
|
bookOverlappingSlotsPromise: ['Setting', function (Setting) { return Setting.get({ name: 'book_overlapping_slots' }).$promise; }]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
modalInstance.result.then(function(res) {
|
modalInstance.result.then(function(res) {
|
||||||
@ -631,10 +632,11 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
|||||||
},
|
},
|
||||||
cartItems () {
|
cartItems () {
|
||||||
return mkRequestParams(reservation, $scope.coupon.applied);
|
return mkRequestParams(reservation, $scope.coupon.applied);
|
||||||
}
|
},
|
||||||
|
stripeKey: ['Setting', function (Setting) { return Setting.get({ name: 'stripe_public_key' }).$promise; }]
|
||||||
},
|
},
|
||||||
controller: ['$scope', '$uibModalInstance', '$state', 'reservation', 'price', 'cgv', 'Auth', 'Reservation', 'wallet', 'helpers', '$filter', 'coupon', 'cartItems',
|
controller: ['$scope', '$uibModalInstance', '$state', 'reservation', 'price', 'cgv', 'Auth', 'Reservation', 'wallet', 'helpers', '$filter', 'coupon', 'cartItems', 'stripeKey',
|
||||||
function ($scope, $uibModalInstance, $state, reservation, price, cgv, Auth, Reservation, wallet, helpers, $filter, coupon, cartItems) {
|
function ($scope, $uibModalInstance, $state, reservation, price, cgv, Auth, Reservation, wallet, helpers, $filter, coupon, cartItems, stripeKey) {
|
||||||
// user wallet amount
|
// user wallet amount
|
||||||
$scope.walletAmount = wallet.amount;
|
$scope.walletAmount = wallet.amount;
|
||||||
|
|
||||||
@ -653,6 +655,9 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
|||||||
// Used in wallet info template to interpolate some translations
|
// Used in wallet info template to interpolate some translations
|
||||||
$scope.numberFilter = $filter('number');
|
$scope.numberFilter = $filter('number');
|
||||||
|
|
||||||
|
// stripe publishable key
|
||||||
|
$scope.stripeKey = stripeKey.setting.value;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback to handle the post-payment and reservation
|
* Callback to handle the post-payment and reservation
|
||||||
*/
|
*/
|
||||||
@ -758,7 +763,7 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
|||||||
const amountToPay = helpers.getAmountToPay($scope.amountTotal, wallet.amount);
|
const amountToPay = helpers.getAmountToPay($scope.amountTotal, wallet.amount);
|
||||||
if ((AuthService.isAuthorized(['member']) && amountToPay > 0)
|
if ((AuthService.isAuthorized(['member']) && amountToPay > 0)
|
||||||
|| (AuthService.isAuthorized('manager') && $scope.user.id === $rootScope.currentUser.id && amountToPay > 0)) {
|
|| (AuthService.isAuthorized('manager') && $scope.user.id === $rootScope.currentUser.id && amountToPay > 0)) {
|
||||||
if ($rootScope.fablabWithoutOnlinePayment) {
|
if ($scope.settings.online_payment_module !== 'true') {
|
||||||
growl.error(_t('app.shared.cart.online_payment_disabled'));
|
growl.error(_t('app.shared.cart.online_payment_disabled'));
|
||||||
} else {
|
} else {
|
||||||
return payByStripe(reservation);
|
return payByStripe(reservation);
|
||||||
@ -783,10 +788,10 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
|||||||
/**
|
/**
|
||||||
* Controller of the modal showing the reservations the same date at the same time
|
* Controller of the modal showing the reservations the same date at the same time
|
||||||
*/
|
*/
|
||||||
Application.Controllers.controller('ReserveSlotSameTimeController', ['$scope', '$uibModalInstance', 'AuthService', 'sameTimeReservations',
|
Application.Controllers.controller('ReserveSlotSameTimeController', ['$scope', '$uibModalInstance', 'AuthService', 'sameTimeReservations', 'bookOverlappingSlotsPromise',
|
||||||
function ($scope, $uibModalInstance, AuthService, sameTimeReservations) {
|
function ($scope, $uibModalInstance, AuthService, sameTimeReservations, bookOverlappingSlotsPromise) {
|
||||||
$scope.sameTimeReservations = sameTimeReservations;
|
$scope.sameTimeReservations = sameTimeReservations;
|
||||||
$scope.bookSlotAtSameTime = Fablab.bookSlotAtSameTime;
|
$scope.bookSlotAtSameTime = (bookOverlappingSlotsPromise.setting.value === 'true');
|
||||||
$scope.isAuthorized = AuthService.isAuthorized;
|
$scope.isAuthorized = AuthService.isAuthorized;
|
||||||
/**
|
/**
|
||||||
* Confirmation callback
|
* Confirmation callback
|
||||||
|
@ -0,0 +1,89 @@
|
|||||||
|
Application.Directives.directive('booleanSetting', ['Setting', 'growl', '_t',
|
||||||
|
function (Setting, growl, _t) {
|
||||||
|
return ({
|
||||||
|
restrict: 'E',
|
||||||
|
scope: {
|
||||||
|
name: '@',
|
||||||
|
label: '@',
|
||||||
|
settings: '=',
|
||||||
|
yesLabel: '@',
|
||||||
|
noLabel: '@',
|
||||||
|
classes: '@',
|
||||||
|
onBeforeSave: '='
|
||||||
|
},
|
||||||
|
templateUrl: '<%= asset_path "admin/settings/boolean.html" %>',
|
||||||
|
link ($scope, element, attributes) {
|
||||||
|
// The setting
|
||||||
|
$scope.setting = {
|
||||||
|
name: $scope.name,
|
||||||
|
value: ($scope.settings[$scope.name] === 'true')
|
||||||
|
};
|
||||||
|
|
||||||
|
// default values for the switch labels
|
||||||
|
$scope.yesLabel = $scope.yesLabel || 'app.admin.settings.enabled';
|
||||||
|
$scope.noLabel = $scope.noLabel || 'app.admin.settings.disabled';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to save the setting value to the database
|
||||||
|
* @param setting {{value:*, name:string}} note that the value will be stringified
|
||||||
|
*/
|
||||||
|
$scope.save = function (setting) {
|
||||||
|
if (typeof $scope.onBeforeSave === 'function') {
|
||||||
|
const res = $scope.onBeforeSave(setting);
|
||||||
|
if (res && _.isFunction(res.then)) {
|
||||||
|
// res is a promise, wait for it before proceed
|
||||||
|
res.then(function (success) {
|
||||||
|
if (success) saveValue(setting);
|
||||||
|
else resetValue();
|
||||||
|
}, function () {
|
||||||
|
resetValue();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (res) saveValue(setting);
|
||||||
|
else resetValue();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
saveValue(setting);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* PRIVATE SCOPE */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the setting's new value in DB
|
||||||
|
* @param setting
|
||||||
|
*/
|
||||||
|
const saveValue = function (setting) {
|
||||||
|
const value = setting.value.toString();
|
||||||
|
|
||||||
|
Setting.update(
|
||||||
|
{ name: setting.name },
|
||||||
|
{ value },
|
||||||
|
function () {
|
||||||
|
growl.success(_t('app.admin.settings.customization_of_SETTING_successfully_saved', { SETTING: _t(`app.admin.settings.${setting.name}`) }));
|
||||||
|
$scope.settings[$scope.name] = value;
|
||||||
|
},
|
||||||
|
function (error) {
|
||||||
|
if (error.status === 304) return;
|
||||||
|
|
||||||
|
if (error.status === 423) {
|
||||||
|
growl.error(_t('app.admin.settings.error_SETTING_locked', { SETTING: _t(`app.admin.settings.${setting.name}`) }));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
growl.error(_t('app.admin.settings.an_error_occurred_saving_the_setting'));
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the value of the setting to its original state (when the component loads)
|
||||||
|
*/
|
||||||
|
const resetValue = function () {
|
||||||
|
$scope.setting.value = $scope.settings[$scope.name] === 'true';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
]);
|
@ -0,0 +1,58 @@
|
|||||||
|
Application.Directives.directive('numberSetting', ['Setting', 'growl', '_t',
|
||||||
|
function (Setting, growl, _t) {
|
||||||
|
return ({
|
||||||
|
restrict: 'E',
|
||||||
|
scope: {
|
||||||
|
name: '@',
|
||||||
|
label: '@',
|
||||||
|
settings: '=',
|
||||||
|
classes: '@',
|
||||||
|
faIcon: '@',
|
||||||
|
helperText: '@',
|
||||||
|
min: '@',
|
||||||
|
required: '<'
|
||||||
|
},
|
||||||
|
templateUrl: '<%= asset_path "admin/settings/number.html" %>',
|
||||||
|
link ($scope, element, attributes) {
|
||||||
|
// The setting
|
||||||
|
$scope.setting = {
|
||||||
|
name: $scope.name,
|
||||||
|
value: parseInt($scope.settings[$scope.name], 10)
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to save the setting value to the database
|
||||||
|
* @param setting {{value:*, name:string}} note that the value will be stringified
|
||||||
|
*/
|
||||||
|
$scope.save = function (setting) {
|
||||||
|
let value;
|
||||||
|
if (typeof setting.value === 'number') {
|
||||||
|
value = setting.value.toString();
|
||||||
|
} else {
|
||||||
|
({ value } = setting);
|
||||||
|
}
|
||||||
|
|
||||||
|
Setting.update(
|
||||||
|
{ name: setting.name },
|
||||||
|
{ value },
|
||||||
|
function () {
|
||||||
|
growl.success(_t('app.admin.settings.customization_of_SETTING_successfully_saved', { SETTING: _t(`app.admin.settings.${setting.name}`) }));
|
||||||
|
$scope.settings[$scope.name] = value;
|
||||||
|
},
|
||||||
|
function (error) {
|
||||||
|
if (error.status === 304) return;
|
||||||
|
|
||||||
|
if (error.status === 423) {
|
||||||
|
growl.error(_t('app.admin.settings.error_SETTING_locked', { SETTING: _t(`app.admin.settings.${setting.name}`) }));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
growl.error(_t('app.admin.settings.an_error_occurred_saving_the_setting'));
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
]);
|
@ -0,0 +1,103 @@
|
|||||||
|
Application.Directives.directive('selectMultipleSetting', ['Setting', 'growl', '_t', '$uibModal',
|
||||||
|
function (Setting, growl, _t, $uibModal) {
|
||||||
|
return ({
|
||||||
|
restrict: 'E',
|
||||||
|
scope: {
|
||||||
|
name: '@',
|
||||||
|
label: '@',
|
||||||
|
settings: '=',
|
||||||
|
classes: '@',
|
||||||
|
required: '<',
|
||||||
|
titleNew: '@',
|
||||||
|
descriptionNew: '@',
|
||||||
|
beforeAdd: '='
|
||||||
|
},
|
||||||
|
templateUrl: '<%= asset_path "admin/settings/select-multiple.html" %>',
|
||||||
|
link ($scope, element, attributes) {
|
||||||
|
// The setting
|
||||||
|
$scope.setting = {
|
||||||
|
name: $scope.name,
|
||||||
|
value: $scope.settings[$scope.name]
|
||||||
|
};
|
||||||
|
|
||||||
|
// the options
|
||||||
|
$scope.options = $scope.settings[$scope.name].split(' ');
|
||||||
|
|
||||||
|
// the selected options
|
||||||
|
$scope.selection = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the items in the selection from the options and update setting.value
|
||||||
|
*/
|
||||||
|
$scope.removeItem = function() {
|
||||||
|
const options = $scope.options.filter(function (opt) {
|
||||||
|
return $scope.selection.indexOf(opt) < 0;
|
||||||
|
})
|
||||||
|
$scope.options = options;
|
||||||
|
$scope.setting.value = options.join(' ');
|
||||||
|
growl.success(_t('app.admin.settings.COUNT_items_removed', { COUNT: $scope.selection.length }));
|
||||||
|
$scope.selection = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a modal dialog asking for the value of a new item to add
|
||||||
|
*/
|
||||||
|
$scope.addItem = function() {
|
||||||
|
$uibModal.open({
|
||||||
|
templateUrl: 'newSelectOption.html',
|
||||||
|
resolve: {
|
||||||
|
titleNew: function () { return $scope.titleNew; },
|
||||||
|
descriptionNew: function () { return $scope.descriptionNew; }
|
||||||
|
},
|
||||||
|
controller: function ($scope, $uibModalInstance, titleNew, descriptionNew) {
|
||||||
|
$scope.value = undefined;
|
||||||
|
$scope.titleNew = titleNew;
|
||||||
|
$scope.descriptionNew = descriptionNew;
|
||||||
|
$scope.ok = function () {
|
||||||
|
$uibModalInstance.close($scope.value);
|
||||||
|
};
|
||||||
|
$scope.dismiss = function () {
|
||||||
|
$uibModalInstance.dismiss('cancel');
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}).result['finally'](null).then(function(val) {
|
||||||
|
const options = Array.from($scope.options);
|
||||||
|
if (typeof $scope.beforeAdd === 'function') { val = $scope.beforeAdd(val); }
|
||||||
|
options.push(val);
|
||||||
|
$scope.options = options;
|
||||||
|
$scope.setting.value = options.join(' ');
|
||||||
|
growl.success(_t('app.admin.settings.item_added'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to save the setting value to the database
|
||||||
|
* @param setting {{value:*, name:string}} note that the value will be stringified
|
||||||
|
*/
|
||||||
|
$scope.save = function (setting) {
|
||||||
|
let { value } = setting;
|
||||||
|
|
||||||
|
Setting.update(
|
||||||
|
{ name: setting.name },
|
||||||
|
{ value },
|
||||||
|
function () {
|
||||||
|
growl.success(_t('app.admin.settings.customization_of_SETTING_successfully_saved', { SETTING: _t(`app.admin.settings.${setting.name}`) }));
|
||||||
|
$scope.settings[$scope.name] = value;
|
||||||
|
},
|
||||||
|
function (error) {
|
||||||
|
if (error.status === 304) return;
|
||||||
|
|
||||||
|
if (error.status === 423) {
|
||||||
|
growl.error(_t('app.admin.settings.error_SETTING_locked', { SETTING: _t(`app.admin.settings.${setting.name}`) }));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
growl.error(_t('app.admin.settings.an_error_occurred_saving_the_setting'));
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
]);
|
@ -0,0 +1,55 @@
|
|||||||
|
Application.Directives.directive('selectSetting', ['Setting', 'growl', '_t',
|
||||||
|
function (Setting, growl, _t) {
|
||||||
|
return ({
|
||||||
|
restrict: 'E',
|
||||||
|
scope: {
|
||||||
|
name: '@',
|
||||||
|
label: '@',
|
||||||
|
settings: '=',
|
||||||
|
classes: '@',
|
||||||
|
required: '<',
|
||||||
|
option1: '<',
|
||||||
|
option2: '<',
|
||||||
|
option3: '<',
|
||||||
|
option4: '<',
|
||||||
|
option5: '<'
|
||||||
|
},
|
||||||
|
templateUrl: '<%= asset_path "admin/settings/select.html" %>',
|
||||||
|
link ($scope, element, attributes) {
|
||||||
|
// The setting
|
||||||
|
$scope.setting = {
|
||||||
|
name: $scope.name,
|
||||||
|
value: $scope.settings[$scope.name]
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to save the setting value to the database
|
||||||
|
* @param setting {{value:*, name:string}} note that the value will be stringified
|
||||||
|
*/
|
||||||
|
$scope.save = function (setting) {
|
||||||
|
let { value } = setting;
|
||||||
|
|
||||||
|
Setting.update(
|
||||||
|
{ name: setting.name },
|
||||||
|
{ value },
|
||||||
|
function () {
|
||||||
|
growl.success(_t('app.admin.settings.customization_of_SETTING_successfully_saved', { SETTING: _t(`app.admin.settings.${setting.name}`) }));
|
||||||
|
$scope.settings[$scope.name] = value;
|
||||||
|
},
|
||||||
|
function (error) {
|
||||||
|
if (error.status === 304) return;
|
||||||
|
|
||||||
|
if (error.status === 423) {
|
||||||
|
growl.error(_t('app.admin.settings.error_SETTING_locked', { SETTING: _t(`app.admin.settings.${setting.name}`) }));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
growl.error(_t('app.admin.settings.an_error_occurred_saving_the_setting'));
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
]);
|
@ -0,0 +1,66 @@
|
|||||||
|
Application.Directives.directive('textSetting', ['Setting', 'growl', '_t',
|
||||||
|
function (Setting, growl, _t) {
|
||||||
|
return ({
|
||||||
|
restrict: 'E',
|
||||||
|
scope: {
|
||||||
|
name: '@',
|
||||||
|
label: '@',
|
||||||
|
settings: '=',
|
||||||
|
classes: '@',
|
||||||
|
faIcon: '@',
|
||||||
|
placeholder: '@',
|
||||||
|
required: '<',
|
||||||
|
type: '@',
|
||||||
|
maxLength: '@',
|
||||||
|
minLength: '@',
|
||||||
|
readOnly: '<'
|
||||||
|
},
|
||||||
|
templateUrl: '<%= asset_path "admin/settings/text.html" %>',
|
||||||
|
link ($scope, element, attributes) {
|
||||||
|
// if type is not specified, use text as default
|
||||||
|
if (typeof $scope.type === 'undefined') {
|
||||||
|
$scope.type = 'text';
|
||||||
|
}
|
||||||
|
// The setting
|
||||||
|
$scope.setting = {
|
||||||
|
name: $scope.name,
|
||||||
|
value: $scope.settings[$scope.name]
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.$watch(`settings.${$scope.name}`, function (newValue, oldValue, scope) {
|
||||||
|
if (newValue !== oldValue) {
|
||||||
|
$scope.setting.value = newValue;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to save the setting value to the database
|
||||||
|
* @param setting {{value:*, name:string}} note that the value will be stringified
|
||||||
|
*/
|
||||||
|
$scope.save = function (setting) {
|
||||||
|
let { value } = setting;
|
||||||
|
|
||||||
|
Setting.update(
|
||||||
|
{ name: setting.name },
|
||||||
|
{ value },
|
||||||
|
function () {
|
||||||
|
growl.success(_t('app.admin.settings.customization_of_SETTING_successfully_saved', { SETTING: _t(`app.admin.settings.${setting.name}`) }));
|
||||||
|
$scope.settings[$scope.name] = value;
|
||||||
|
},
|
||||||
|
function (error) {
|
||||||
|
if (error.status === 304) return;
|
||||||
|
|
||||||
|
if (error.status === 423) {
|
||||||
|
growl.error(_t('app.admin.settings.error_SETTING_locked', { SETTING: _t(`app.admin.settings.${setting.name}`) }));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
growl.error(_t('app.admin.settings.an_error_occurred_saving_the_setting'));
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
]);
|
@ -12,10 +12,11 @@ Application.Directives.directive('stripeForm', ['Payment', 'growl', '_t',
|
|||||||
restrict: 'A',
|
restrict: 'A',
|
||||||
scope: {
|
scope: {
|
||||||
cartItems: '=',
|
cartItems: '=',
|
||||||
onPaymentSuccess: '='
|
onPaymentSuccess: '=',
|
||||||
|
stripeKey: '@'
|
||||||
},
|
},
|
||||||
link: function($scope, element, attributes) {
|
link: function($scope, element, attributes) {
|
||||||
const stripe = Stripe('<%= Rails.application.secrets.stripe_publishable_key %>');
|
const stripe = Stripe($scope.stripeKey);
|
||||||
const elements = stripe.elements();
|
const elements = stripe.elements();
|
||||||
|
|
||||||
const style = {
|
const style = {
|
||||||
|
@ -16,7 +16,7 @@ angular.module('application.router', ['ui.router'])
|
|||||||
|
|
||||||
// abstract root parents states
|
// abstract root parents states
|
||||||
// these states controls the access rights to the various routes inherited from them
|
// these states controls the access rights to the various routes inherited from them
|
||||||
return $stateProvider
|
$stateProvider
|
||||||
.state('app', {
|
.state('app', {
|
||||||
abstract: true,
|
abstract: true,
|
||||||
views: {
|
views: {
|
||||||
@ -36,14 +36,21 @@ angular.module('application.router', ['ui.router'])
|
|||||||
resolve: {
|
resolve: {
|
||||||
logoFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'logo-file' }).$promise; }],
|
logoFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'logo-file' }).$promise; }],
|
||||||
logoBlackFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'logo-black-file' }).$promise; }],
|
logoBlackFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'logo-black-file' }).$promise; }],
|
||||||
sharedTranslations: ['Translations', function (Translations) { return Translations.query(['app.shared', 'app.public.common']).$promise; }]
|
sharedTranslations: ['Translations', function (Translations) { return Translations.query(['app.shared', 'app.public.common']).$promise; }],
|
||||||
|
modulesPromise: ['Setting', function (Setting) { return Setting.query({ names: "['spaces_module', 'plans_module', 'invoicing_module', 'wallet_module']" }).$promise; }]
|
||||||
},
|
},
|
||||||
onEnter: ['$rootScope', 'logoFile', 'logoBlackFile', 'CSRF', function ($rootScope, logoFile, logoBlackFile, CSRF) {
|
onEnter: ['$rootScope', 'logoFile', 'logoBlackFile', 'modulesPromise', 'CSRF', function ($rootScope, logoFile, logoBlackFile, modulesPromise, CSRF) {
|
||||||
// Retrieve Anti-CSRF tokens from cookies
|
// Retrieve Anti-CSRF tokens from cookies
|
||||||
CSRF.setMetaTags();
|
CSRF.setMetaTags();
|
||||||
// Application logo
|
// Application logo
|
||||||
$rootScope.logo = logoFile.custom_asset;
|
$rootScope.logo = logoFile.custom_asset;
|
||||||
$rootScope.logoBlack = logoBlackFile.custom_asset;
|
$rootScope.logoBlack = logoBlackFile.custom_asset;
|
||||||
|
$rootScope.modules = {
|
||||||
|
spaces: (modulesPromise.spaces_module === 'true'),
|
||||||
|
plans: (modulesPromise.plans_module === 'true'),
|
||||||
|
invoicing: (modulesPromise.invoicing_module === 'true'),
|
||||||
|
wallet: (modulesPromise.wallet_module === 'true'),
|
||||||
|
};
|
||||||
}]
|
}]
|
||||||
})
|
})
|
||||||
.state('app.public', {
|
.state('app.public', {
|
||||||
@ -98,7 +105,7 @@ angular.module('application.router', ['ui.router'])
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['home_content', 'home_blogpost']" }).$promise; }]
|
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['home_content', 'home_blogpost', 'spaces_module', 'feature_tour_display']" }).$promise; }]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('app.public.privacy', {
|
.state('app.public.privacy', {
|
||||||
@ -126,6 +133,7 @@ angular.module('application.router', ['ui.router'])
|
|||||||
groupsPromise: ['Group', function (Group) { return Group.query().$promise; }],
|
groupsPromise: ['Group', function (Group) { return Group.query().$promise; }],
|
||||||
cguFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'cgu-file' }).$promise; }],
|
cguFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'cgu-file' }).$promise; }],
|
||||||
memberPromise: ['Member', 'currentUser', function (Member, currentUser) { return Member.get({ id: currentUser.id }).$promise; }],
|
memberPromise: ['Member', 'currentUser', function (Member, currentUser) { return Member.get({ id: currentUser.id }).$promise; }],
|
||||||
|
phoneRequiredPromise: ['Setting', function (Setting) { return Setting.get({ name: 'phone_required' }).$promise; }]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -157,6 +165,7 @@ angular.module('application.router', ['ui.router'])
|
|||||||
resolve: {
|
resolve: {
|
||||||
groups: ['Group', function (Group) { return Group.query().$promise; }],
|
groups: ['Group', function (Group) { return Group.query().$promise; }],
|
||||||
activeProviderPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.active().$promise; }],
|
activeProviderPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.active().$promise; }],
|
||||||
|
phoneRequiredPromise: ['Setting', function (Setting) { return Setting.get({ name: 'phone_required' }).$promise; }]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('app.logged.dashboard.projects', {
|
.state('app.logged.dashboard.projects', {
|
||||||
@ -197,6 +206,7 @@ angular.module('application.router', ['ui.router'])
|
|||||||
})
|
})
|
||||||
.state('app.logged.dashboard.wallet', {
|
.state('app.logged.dashboard.wallet', {
|
||||||
url: '/wallet',
|
url: '/wallet',
|
||||||
|
abstract: !Fablab.walletModule,
|
||||||
views: {
|
views: {
|
||||||
'main@': {
|
'main@': {
|
||||||
templateUrl: '<%= asset_path "dashboard/wallet.html" %>',
|
templateUrl: '<%= asset_path "dashboard/wallet.html" %>',
|
||||||
@ -247,7 +257,9 @@ angular.module('application.router', ['ui.router'])
|
|||||||
resolve: {
|
resolve: {
|
||||||
themesPromise: ['Theme', function (Theme) { return Theme.query().$promise; }],
|
themesPromise: ['Theme', function (Theme) { return Theme.query().$promise; }],
|
||||||
componentsPromise: ['Component', function (Component) { return Component.query().$promise; }],
|
componentsPromise: ['Component', function (Component) { return Component.query().$promise; }],
|
||||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }]
|
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }],
|
||||||
|
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['openlab_app_id', 'openlab_default']" }).$promise; }],
|
||||||
|
openLabActive: ['Setting', function (Setting) { return Setting.isPresent({ name: 'openlab_app_secret' }).$promise; }],
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('app.logged.projects_new', {
|
.state('app.logged.projects_new', {
|
||||||
@ -259,7 +271,7 @@ angular.module('application.router', ['ui.router'])
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
allowedExtensions: ['Project', function (Project) { return Project.allowedExtensions().$promise; }]
|
allowedExtensions: ['Setting', function (Setting) { return Setting.get({ name: 'allowed_cad_extensions' }).$promise; }]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('app.public.projects_show', {
|
.state('app.public.projects_show', {
|
||||||
@ -271,7 +283,8 @@ angular.module('application.router', ['ui.router'])
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
projectPromise: ['$stateParams', 'Project', function ($stateParams, Project) { return Project.get({ id: $stateParams.id }).$promise; }]
|
projectPromise: ['$stateParams', 'Project', function ($stateParams, Project) { return Project.get({ id: $stateParams.id }).$promise; }],
|
||||||
|
shortnamePromise: ['Setting', function (Setting) { return Setting.get({ name: 'disqus_shortname' }).$promise; }]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('app.logged.projects_edit', {
|
.state('app.logged.projects_edit', {
|
||||||
@ -284,7 +297,7 @@ angular.module('application.router', ['ui.router'])
|
|||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
projectPromise: ['$stateParams', 'Project', function ($stateParams, Project) { return Project.get({ id: $stateParams.id }).$promise; }],
|
projectPromise: ['$stateParams', 'Project', function ($stateParams, Project) { return Project.get({ id: $stateParams.id }).$promise; }],
|
||||||
allowedExtensions: ['Project', function (Project) { return Project.allowedExtensions().$promise; }]
|
allowedExtensions: ['Setting', function (Setting) { return Setting.get({ name: 'allowed_cad_extensions' }).$promise; }]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -298,7 +311,8 @@ angular.module('application.router', ['ui.router'])
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }]
|
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }],
|
||||||
|
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['feature_tour_display']" }).$promise; }]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('app.admin.machines_new', {
|
.state('app.admin.machines_new', {
|
||||||
@ -336,14 +350,9 @@ angular.module('application.router', ['ui.router'])
|
|||||||
machinePromise: ['Machine', '$stateParams', function (Machine, $stateParams) { return Machine.get({ id: $stateParams.id }).$promise; }],
|
machinePromise: ['Machine', '$stateParams', function (Machine, $stateParams) { return Machine.get({ id: $stateParams.id }).$promise; }],
|
||||||
settingsPromise: ['Setting', function (Setting) {
|
settingsPromise: ['Setting', function (Setting) {
|
||||||
return Setting.query({
|
return Setting.query({
|
||||||
names: `['machine_explications_alert', \
|
names: `['machine_explications_alert', 'booking_window_start', 'booking_window_end', 'booking_move_enable', \
|
||||||
'booking_window_start', \
|
'booking_move_delay', 'booking_cancel_enable', 'booking_cancel_delay', 'subscription_explications_alert', \
|
||||||
'booking_window_end', \
|
'online_payment_module']`
|
||||||
'booking_move_enable', \
|
|
||||||
'booking_move_delay', \
|
|
||||||
'booking_cancel_enable', \
|
|
||||||
'booking_cancel_delay', \
|
|
||||||
'subscription_explications_alert']`
|
|
||||||
}).$promise;
|
}).$promise;
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
@ -364,7 +373,7 @@ angular.module('application.router', ['ui.router'])
|
|||||||
// spaces
|
// spaces
|
||||||
.state('app.public.spaces_list', {
|
.state('app.public.spaces_list', {
|
||||||
url: '/spaces',
|
url: '/spaces',
|
||||||
abstract: Fablab.withoutSpaces,
|
abstract: !Fablab.spacesModule,
|
||||||
views: {
|
views: {
|
||||||
'main@': {
|
'main@': {
|
||||||
templateUrl: '<%= asset_path "spaces/index.html" %>',
|
templateUrl: '<%= asset_path "spaces/index.html" %>',
|
||||||
@ -372,12 +381,13 @@ angular.module('application.router', ['ui.router'])
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
spacesPromise: ['Space', function (Space) { return Space.query().$promise; }]
|
spacesPromise: ['Space', function (Space) { return Space.query().$promise; }],
|
||||||
|
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['feature_tour_display']" }).$promise; }]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('app.admin.space_new', {
|
.state('app.admin.space_new', {
|
||||||
url: '/spaces/new',
|
url: '/spaces/new',
|
||||||
abstract: Fablab.withoutSpaces,
|
abstract: !Fablab.spacesModule,
|
||||||
views: {
|
views: {
|
||||||
'main@': {
|
'main@': {
|
||||||
templateUrl: '<%= asset_path "spaces/new.html" %>',
|
templateUrl: '<%= asset_path "spaces/new.html" %>',
|
||||||
@ -387,7 +397,7 @@ angular.module('application.router', ['ui.router'])
|
|||||||
})
|
})
|
||||||
.state('app.public.space_show', {
|
.state('app.public.space_show', {
|
||||||
url: '/spaces/:id',
|
url: '/spaces/:id',
|
||||||
abstract: Fablab.withoutSpaces,
|
abstract: !Fablab.spacesModule,
|
||||||
views: {
|
views: {
|
||||||
'main@': {
|
'main@': {
|
||||||
templateUrl: '<%= asset_path "spaces/show.html" %>',
|
templateUrl: '<%= asset_path "spaces/show.html" %>',
|
||||||
@ -400,7 +410,7 @@ angular.module('application.router', ['ui.router'])
|
|||||||
})
|
})
|
||||||
.state('app.admin.space_edit', {
|
.state('app.admin.space_edit', {
|
||||||
url: '/spaces/:id/edit',
|
url: '/spaces/:id/edit',
|
||||||
abstract: Fablab.withoutSpaces,
|
abstract: !Fablab.spacesModule,
|
||||||
views: {
|
views: {
|
||||||
'main@': {
|
'main@': {
|
||||||
templateUrl: '<%= asset_path "spaces/edit.html" %>',
|
templateUrl: '<%= asset_path "spaces/edit.html" %>',
|
||||||
@ -413,7 +423,7 @@ angular.module('application.router', ['ui.router'])
|
|||||||
})
|
})
|
||||||
.state('app.logged.space_reserve', {
|
.state('app.logged.space_reserve', {
|
||||||
url: '/spaces/:id/reserve',
|
url: '/spaces/:id/reserve',
|
||||||
abstract: Fablab.withoutSpaces,
|
abstract: !Fablab.spacesModule,
|
||||||
views: {
|
views: {
|
||||||
'main@': {
|
'main@': {
|
||||||
templateUrl: '<%= asset_path "spaces/reserve.html" %>',
|
templateUrl: '<%= asset_path "spaces/reserve.html" %>',
|
||||||
@ -427,14 +437,9 @@ angular.module('application.router', ['ui.router'])
|
|||||||
groupsPromise: ['Group', function (Group) { return Group.query().$promise; }],
|
groupsPromise: ['Group', function (Group) { return Group.query().$promise; }],
|
||||||
settingsPromise: ['Setting', function (Setting) {
|
settingsPromise: ['Setting', function (Setting) {
|
||||||
return Setting.query({
|
return Setting.query({
|
||||||
names: `['booking_window_start', \
|
names: `['booking_window_start', 'booking_window_end', 'booking_move_enable', 'booking_move_delay', \
|
||||||
'booking_window_end', \
|
'booking_cancel_enable', 'booking_cancel_delay', 'subscription_explications_alert', \
|
||||||
'booking_move_enable', \
|
'space_explications_alert', 'online_payment_module']` }).$promise;
|
||||||
'booking_move_delay', \
|
|
||||||
'booking_cancel_enable', \
|
|
||||||
'booking_cancel_delay', \
|
|
||||||
'subscription_explications_alert', \
|
|
||||||
'space_explications_alert']` }).$promise;
|
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -482,15 +487,9 @@ angular.module('application.router', ['ui.router'])
|
|||||||
}],
|
}],
|
||||||
settingsPromise: ['Setting', function (Setting) {
|
settingsPromise: ['Setting', function (Setting) {
|
||||||
return Setting.query({
|
return Setting.query({
|
||||||
names: `['booking_window_start', \
|
names: `['booking_window_start', 'booking_window_end', 'booking_move_enable', 'booking_move_delay', \
|
||||||
'booking_window_end', \
|
'booking_cancel_enable', 'booking_cancel_delay', 'subscription_explications_alert', \
|
||||||
'booking_move_enable', \
|
'training_explications_alert', 'training_information_message', 'online_payment_module']` }).$promise;
|
||||||
'booking_move_delay', \
|
|
||||||
'booking_cancel_enable', \
|
|
||||||
'booking_cancel_delay', \
|
|
||||||
'subscription_explications_alert', \
|
|
||||||
'training_explications_alert', \
|
|
||||||
'training_information_message']` }).$promise;
|
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -508,7 +507,7 @@ angular.module('application.router', ['ui.router'])
|
|||||||
// pricing
|
// pricing
|
||||||
.state('app.public.plans', {
|
.state('app.public.plans', {
|
||||||
url: '/plans',
|
url: '/plans',
|
||||||
abstract: Fablab.withoutPlans,
|
abstract: !Fablab.plansModule,
|
||||||
views: {
|
views: {
|
||||||
'main@': {
|
'main@': {
|
||||||
templateUrl: '<%= asset_path "plans/index.html.erb" %>',
|
templateUrl: '<%= asset_path "plans/index.html.erb" %>',
|
||||||
@ -518,7 +517,8 @@ angular.module('application.router', ['ui.router'])
|
|||||||
resolve: {
|
resolve: {
|
||||||
subscriptionExplicationsPromise: ['Setting', function (Setting) { return Setting.get({ name: 'subscription_explications_alert' }).$promise; }],
|
subscriptionExplicationsPromise: ['Setting', function (Setting) { return Setting.get({ name: 'subscription_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; }],
|
||||||
|
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['online_payment_module']" }).$promise; }]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -534,7 +534,8 @@ angular.module('application.router', ['ui.router'])
|
|||||||
resolve: {
|
resolve: {
|
||||||
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; }],
|
||||||
|
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['online_payment_module']" }).$promise; }]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('app.public.events_show', {
|
.state('app.public.events_show', {
|
||||||
@ -586,7 +587,8 @@ angular.module('application.router', ['ui.router'])
|
|||||||
bookingWindowEnd: ['Setting', function (Setting) { return Setting.get({ name: 'booking_window_end' }).$promise; }],
|
bookingWindowEnd: ['Setting', function (Setting) { return Setting.get({ name: 'booking_window_end' }).$promise; }],
|
||||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }],
|
machinesPromise: ['Machine', function (Machine) { return Machine.query().$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) { return Setting.query({ names: "['slot_duration', 'events_in_calendar', 'feature_tour_display']" }).$promise; }]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('app.admin.calendar.icalendar', {
|
.state('app.admin.calendar.icalendar', {
|
||||||
@ -602,19 +604,23 @@ angular.module('application.router', ['ui.router'])
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// project's elements
|
// project's settings
|
||||||
.state('app.admin.project_elements', {
|
.state('app.admin.projects', {
|
||||||
url: '/admin/project_elements',
|
url: '/admin/projects',
|
||||||
views: {
|
views: {
|
||||||
'main@': {
|
'main@': {
|
||||||
templateUrl: '<%= asset_path "admin/project_elements/index.html.erb" %>',
|
templateUrl: '<%= asset_path "admin/projects/index.html.erb" %>',
|
||||||
controller: 'ProjectElementsController'
|
controller: 'AdminProjectsController'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
componentsPromise: ['Component', function (Component) { return Component.query().$promise; }],
|
componentsPromise: ['Component', function (Component) { return Component.query().$promise; }],
|
||||||
licencesPromise: ['Licence', function (Licence) { return Licence.query().$promise; }],
|
licencesPromise: ['Licence', function (Licence) { return Licence.query().$promise; }],
|
||||||
themesPromise: ['Theme', function (Theme) { return Theme.query().$promise; }]
|
themesPromise: ['Theme', function (Theme) { return Theme.query().$promise; }],
|
||||||
|
settingsPromise: ['Setting', function (Setting) {
|
||||||
|
return Setting.query({ names: "['feature_tour_display', 'disqus_shortname', 'allowed_cad_extensions', \
|
||||||
|
'allowed_cad_mime_types', 'openlab_app_id', 'openlab_app_secret', 'openlab_default']" }).$promise;
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('app.admin.manage_abuses', {
|
.state('app.admin.manage_abuses', {
|
||||||
@ -641,7 +647,8 @@ angular.module('application.router', ['ui.router'])
|
|||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
trainingsPromise: ['Training', function (Training) { return Training.query().$promise; }],
|
trainingsPromise: ['Training', function (Training) { return Training.query().$promise; }],
|
||||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }]
|
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }],
|
||||||
|
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['feature_tour_display']" }).$promise; }]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('app.admin.trainings_new', {
|
.state('app.admin.trainings_new', {
|
||||||
@ -683,7 +690,8 @@ angular.module('application.router', ['ui.router'])
|
|||||||
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; }],
|
||||||
priceCategoriesPromise: ['PriceCategory', function (PriceCategory) { return PriceCategory.query().$promise; }]
|
priceCategoriesPromise: ['PriceCategory', function (PriceCategory) { return PriceCategory.query().$promise; }],
|
||||||
|
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['feature_tour_display']" }).$promise; }]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('app.admin.events_new', {
|
.state('app.admin.events_new', {
|
||||||
@ -752,7 +760,8 @@ angular.module('application.router', ['ui.router'])
|
|||||||
couponsPromise: ['Coupon', function (Coupon) { return Coupon.query({ page: 1, filter: 'all' }).$promise; }],
|
couponsPromise: ['Coupon', function (Coupon) { return Coupon.query({ page: 1, filter: 'all' }).$promise; }],
|
||||||
spacesPromise: ['Space', function (Space) { return Space.query().$promise; }],
|
spacesPromise: ['Space', function (Space) { return Space.query().$promise; }],
|
||||||
spacesPricesPromise: ['Price', function (Price) { return Price.query({ priceable_type: 'Space', plan_id: 'null' }).$promise; }],
|
spacesPricesPromise: ['Price', function (Price) { return Price.query({ priceable_type: 'Space', plan_id: 'null' }).$promise; }],
|
||||||
spacesCreditsPromise: ['Credit', function (Credit) { return Credit.query({ creditable_type: 'Space' }).$promise; }]
|
spacesCreditsPromise: ['Credit', function (Credit) { return Credit.query({ creditable_type: 'Space' }).$promise; }],
|
||||||
|
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['feature_tour_display', 'slot_duration']" }).$promise; }]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -827,12 +836,15 @@ angular.module('application.router', ['ui.router'])
|
|||||||
return Setting.query({
|
return Setting.query({
|
||||||
names: `['invoice_legals', 'invoice_text', 'invoice_VAT-rate', 'invoice_VAT-active', 'invoice_order-nb', 'invoice_code-value', \
|
names: `['invoice_legals', 'invoice_text', 'invoice_VAT-rate', 'invoice_VAT-active', 'invoice_order-nb', 'invoice_code-value', \
|
||||||
'invoice_code-active', 'invoice_reference', 'invoice_logo', 'accounting_journal_code', 'accounting_card_client_code', \
|
'invoice_code-active', 'invoice_reference', 'invoice_logo', 'accounting_journal_code', 'accounting_card_client_code', \
|
||||||
'accounting_card_client_label', 'accounting_wallet_client_code', 'accounting_wallet_client_label', \
|
'accounting_card_client_label', 'accounting_wallet_client_code', 'accounting_wallet_client_label', 'invoicing_module', \
|
||||||
'accounting_other_client_code', 'accounting_other_client_label', 'accounting_wallet_code', 'accounting_wallet_label', \
|
'accounting_other_client_code', 'accounting_other_client_label', 'accounting_wallet_code', 'accounting_wallet_label', \
|
||||||
'accounting_VAT_code', 'accounting_VAT_label', 'accounting_subscription_code', 'accounting_subscription_label', \
|
'accounting_VAT_code', 'accounting_VAT_label', 'accounting_subscription_code', 'accounting_subscription_label', \
|
||||||
'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']` }).$promise;
|
'accounting_Event_code', 'accounting_Event_label', 'accounting_Space_code', 'accounting_Space_label', \
|
||||||
|
'feature_tour_display', 'online_payment_module', 'stripe_public_key', 'stripe_currency', 'invoice_prefix']` }).$promise;
|
||||||
}],
|
}],
|
||||||
|
stripeSecretKey: ['Setting', function (Setting) { return Setting.isPresent({ name: 'stripe_secret_key' }).$promise; }],
|
||||||
|
onlinePaymentStatus: ['Payment', function (Payment) { return Payment.onlinePaymentStatus().$promise; }],
|
||||||
invoices: [ 'Invoice', function (Invoice) {
|
invoices: [ 'Invoice', function (Invoice) {
|
||||||
return Invoice.list({
|
return Invoice.list({
|
||||||
query: { number: '', customer: '', date: null, order_by: '-reference', page: 1, size: 20 }
|
query: { number: '', customer: '', date: null, order_by: '-reference', page: 1, size: 20 }
|
||||||
@ -870,7 +882,8 @@ angular.module('application.router', ['ui.router'])
|
|||||||
managersPromise: ['User', function (User) { return User.query({ role: 'manager' }).$promise; }],
|
managersPromise: ['User', function (User) { return User.query({ role: 'manager' }).$promise; }],
|
||||||
groupsPromise: ['Group', function (Group) { return Group.query().$promise; }],
|
groupsPromise: ['Group', function (Group) { return Group.query().$promise; }],
|
||||||
tagsPromise: ['Tag', function (Tag) { return Tag.query().$promise; }],
|
tagsPromise: ['Tag', function (Tag) { return Tag.query().$promise; }],
|
||||||
authProvidersPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.query().$promise; }]
|
authProvidersPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.query().$promise; }],
|
||||||
|
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['feature_tour_display']" }).$promise; }]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('app.admin.members_new', {
|
.state('app.admin.members_new', {
|
||||||
@ -880,6 +893,9 @@ angular.module('application.router', ['ui.router'])
|
|||||||
templateUrl: '<%= asset_path "admin/members/new.html" %>',
|
templateUrl: '<%= asset_path "admin/members/new.html" %>',
|
||||||
controller: 'NewMemberController'
|
controller: 'NewMemberController'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
phoneRequiredPromise: ['Setting', function (Setting) { return Setting.get({ name: 'phone_required' }).$promise; }]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('app.admin.members_import', {
|
.state('app.admin.members_import', {
|
||||||
@ -919,7 +935,8 @@ angular.module('application.router', ['ui.router'])
|
|||||||
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', '$stateParams', function (Wallet, $stateParams) { return Wallet.getWalletByUser({ user_id: $stateParams.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; }],
|
||||||
|
phoneRequiredPromise: ['Setting', function (Setting) { return Setting.get({ name: 'phone_required' }).$promise; }]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('app.admin.admins_new', {
|
.state('app.admin.admins_new', {
|
||||||
@ -984,7 +1001,8 @@ angular.module('application.router', ['ui.router'])
|
|||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
membersPromise: ['Member', function (Member) { return Member.mapping().$promise; }],
|
membersPromise: ['Member', function (Member) { return Member.mapping().$promise; }],
|
||||||
statisticsPromise: ['Statistics', function (Statistics) { return Statistics.query().$promise; }]
|
statisticsPromise: ['Statistics', function (Statistics) { return Statistics.query().$promise; }],
|
||||||
|
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['feature_tour_display']" }).$promise; }]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('app.admin.stats_graphs', {
|
.state('app.admin.stats_graphs', {
|
||||||
@ -1009,17 +1027,17 @@ angular.module('application.router', ['ui.router'])
|
|||||||
resolve: {
|
resolve: {
|
||||||
settingsPromise: ['Setting', function (Setting) {
|
settingsPromise: ['Setting', function (Setting) {
|
||||||
return Setting.query({
|
return Setting.query({
|
||||||
names: `['twitter_name', 'about_title', 'about_body', \
|
names: `['twitter_name', 'about_title', 'about_body', 'tracking_id', 'facebook_app_id', 'email_from', \
|
||||||
'privacy_body', 'privacy_dpo', 'about_contacts', \
|
'privacy_body', 'privacy_dpo', 'about_contacts', 'book_overlapping_slots', 'invoicing_module', \
|
||||||
'home_blogpost', 'machine_explications_alert', 'training_explications_alert', \
|
'home_blogpost', 'machine_explications_alert', 'training_explications_alert', 'slot_duration', \
|
||||||
'training_information_message', 'subscription_explications_alert', 'event_explications_alert', \
|
'training_information_message', 'subscription_explications_alert', 'event_explications_alert', \
|
||||||
'space_explications_alert', 'booking_window_start', 'booking_window_end', \
|
'space_explications_alert', 'booking_window_start', 'booking_window_end', 'events_in_calendar', \
|
||||||
'booking_move_enable', 'booking_move_delay', 'booking_cancel_enable', \
|
'booking_move_enable', 'booking_move_delay', 'booking_cancel_enable', 'feature_tour_display', \
|
||||||
'booking_cancel_delay', 'main_color', 'secondary_color', \
|
'booking_cancel_delay', 'main_color', 'secondary_color', 'spaces_module', 'twitter_analytics', \
|
||||||
'fablab_name', 'name_genre', 'reminder_enable', \
|
'fablab_name', 'name_genre', 'reminder_enable', 'plans_module', 'confirmation_required', \
|
||||||
'reminder_delay', 'visibility_yearly', 'visibility_others', \
|
'reminder_delay', 'visibility_yearly', 'visibility_others', 'wallet_module', \
|
||||||
'display_name_enable', 'machines_sort_by', 'fab_analytics', \
|
'display_name_enable', 'machines_sort_by', 'fab_analytics', \
|
||||||
'link_name', 'home_content', 'home_css']` }).$promise;
|
'link_name', 'home_content', 'home_css', 'phone_required']` }).$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; }],
|
||||||
cguFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'cgu-file' }).$promise; }],
|
cguFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'cgu-file' }).$promise; }],
|
||||||
@ -1039,7 +1057,8 @@ angular.module('application.router', ['ui.router'])
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
clientsPromise: ['OpenAPIClient', function (OpenAPIClient) { return OpenAPIClient.query().$promise; }]
|
clientsPromise: ['OpenAPIClient', function (OpenAPIClient) { return OpenAPIClient.query().$promise; }],
|
||||||
|
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['feature_tour_display']" }).$promise; }]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ Application.Services.factory('Help', ['$rootScope', '$uibModal', '$state', 'Auth
|
|||||||
'app.admin.invoices': 'invoices',
|
'app.admin.invoices': 'invoices',
|
||||||
'app.admin.pricing': 'pricing',
|
'app.admin.pricing': 'pricing',
|
||||||
'app.admin.events': 'events',
|
'app.admin.events': 'events',
|
||||||
'app.admin.project_elements': 'project-elements',
|
'app.admin.projects': 'projects',
|
||||||
'app.admin.statistics': 'statistics',
|
'app.admin.statistics': 'statistics',
|
||||||
'app.admin.settings': 'settings',
|
'app.admin.settings': 'settings',
|
||||||
'app.admin.open_api_clients': 'open-api'
|
'app.admin.open_api_clients': 'open-api'
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
Application.Services.factory('Member', ['$resource', '$q', function ($resource, $q) {
|
Application.Services.factory('Member', ['$resource', 'Setting', function ($resource, Setting) {
|
||||||
return $resource('/api/members/:id',
|
return $resource('/api/members/:id',
|
||||||
{ id: '@id' }, {
|
{ id: '@id' }, {
|
||||||
update: {
|
update: {
|
||||||
@ -37,11 +37,13 @@ Application.Services.factory('Member', ['$resource', '$q', function ($resource,
|
|||||||
params: { id: '@id' },
|
params: { id: '@id' },
|
||||||
interceptor: {
|
interceptor: {
|
||||||
response: function (response) {
|
response: function (response) {
|
||||||
if (Fablab.featureTourDisplay === 'session') {
|
return Setting.query({ names: "['feature_tour_display']" }).$promise.then((settings) => {
|
||||||
Fablab.sessionTours.push(response.data.tours[0]);
|
if (settings.feature_tour_display === 'session') {
|
||||||
return { tours: Fablab.sessionTours };
|
Fablab.sessionTours.push(response.data.tours[0]);
|
||||||
}
|
return { tours: Fablab.sessionTours };
|
||||||
return response.data;
|
}
|
||||||
|
return response.data;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -7,6 +7,10 @@ Application.Services.factory('Payment', ['$resource', function ($resource) {
|
|||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: '/api/payments/confirm_payment',
|
url: '/api/payments/confirm_payment',
|
||||||
isArray: false
|
isArray: false
|
||||||
|
},
|
||||||
|
onlinePaymentStatus: {
|
||||||
|
method: 'GET',
|
||||||
|
url: '/api/payments/online_payment_status'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -12,11 +12,6 @@ Application.Services.factory('Project', ['$resource', function ($resource) {
|
|||||||
method: 'GET',
|
method: 'GET',
|
||||||
url: '/api/projects/search',
|
url: '/api/projects/search',
|
||||||
isArray: false
|
isArray: false
|
||||||
},
|
|
||||||
allowedExtensions: {
|
|
||||||
method: 'GET',
|
|
||||||
url: '/api/projects/allowed_extensions',
|
|
||||||
isArray: true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -20,6 +20,11 @@ Application.Services.factory('Setting', ['$resource', function ($resource) {
|
|||||||
url: '/api/settings/reset/:name',
|
url: '/api/settings/reset/:name',
|
||||||
params: { name: '@name' },
|
params: { name: '@name' },
|
||||||
method: 'PUT'
|
method: 'PUT'
|
||||||
|
},
|
||||||
|
isPresent: {
|
||||||
|
url: '/api/settings/is_present/:name',
|
||||||
|
params: { name: '@name' },
|
||||||
|
method: 'GET'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -8,6 +8,28 @@
|
|||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.invoice-file {
|
||||||
|
text-align: center;
|
||||||
|
line-height: 4em;
|
||||||
|
margin-top: 2em;
|
||||||
|
|
||||||
|
.fa-file-pdf-o {
|
||||||
|
font-size: 4em;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filename {
|
||||||
|
font-size: 1.1em;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-left: 1em;
|
||||||
|
|
||||||
|
.prefix:hover {
|
||||||
|
background-color: $yellow;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.invoice-placeholder {
|
.invoice-placeholder {
|
||||||
width: 80%;
|
width: 80%;
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
|
@ -67,4 +67,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.section-separator {
|
||||||
|
background: radial-gradient(#dddddd, transparent);
|
||||||
|
height: 1px;
|
||||||
|
margin: 24px 33% 12px 33%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
<div class="legends">
|
<div class="legends">
|
||||||
<span class="calendar-legend text-sm border-formation" translate>{{ 'app.admin.calendar.trainings' }}</span><br>
|
<span class="calendar-legend text-sm border-formation" translate>{{ 'app.admin.calendar.trainings' }}</span><br>
|
||||||
<span class="calendar-legend text-sm border-machine" translate>{{ 'app.admin.calendar.machines' }}</span><br>
|
<span class="calendar-legend text-sm border-machine" translate>{{ 'app.admin.calendar.machines' }}</span><br>
|
||||||
<span class="calendar-legend text-sm border-space" ng-hide="fablabWithoutSpaces" translate>{{ 'app.admin.calendar.spaces' }}</span>
|
<span class="calendar-legend text-sm border-space" ng-show="modules.spaces" translate>{{ 'app.admin.calendar.spaces' }}</span>
|
||||||
<span class="calendar-legend text-sm border-event" ng-show="eventsInCalendar" translate>{{ 'app.admin.calendar.events' }}</span>
|
<span class="calendar-legend text-sm border-event" ng-show="eventsInCalendar" translate>{{ 'app.admin.calendar.events' }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
<span translate>{{ 'app.admin.calendar.machine' }}</span>
|
<span translate>{{ 'app.admin.calendar.machine' }}</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="radio" ng-hide="fablabWithoutSpaces">
|
<div class="radio" ng-show="modules.spaces">
|
||||||
<label>
|
<label>
|
||||||
<input type="radio" id="space" name="available_type" value="space" ng-model="availability.available_type" ng-disabled="spaces.length === 0">
|
<input type="radio" id="space" name="available_type" value="space" ng-model="availability.available_type" ng-disabled="spaces.length === 0">
|
||||||
<span translate>{{ 'app.admin.calendar.space' }}</span>
|
<span translate>{{ 'app.admin.calendar.space' }}</span>
|
||||||
|
@ -53,8 +53,7 @@
|
|||||||
|
|
||||||
|
|
||||||
<div class="form-group" ng-class="{'has-error': couponForm['coupon[amount_off]'].$dirty && couponForm['coupon[amount_off]'].$invalid}" ng-show="coupon.type == 'amount_off'">
|
<div class="form-group" ng-class="{'has-error': couponForm['coupon[amount_off]'].$dirty && couponForm['coupon[amount_off]'].$invalid}" ng-show="coupon.type == 'amount_off'">
|
||||||
<label for="coupon[amount_off]">{{ 'app.shared.coupon.amount_off' | translate }} *</label>
|
²<div class="input-group">
|
||||||
<div class="input-group">
|
|
||||||
<span class="input-group-addon">{{currencySymbol}}</span>
|
<span class="input-group-addon">{{currencySymbol}}</span>
|
||||||
<input type="number" id="coupon[amount_off]"
|
<input type="number" id="coupon[amount_off]"
|
||||||
name="coupon[amount_off]"
|
name="coupon[amount_off]"
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12" ng-if="isAuthorized('admin')">
|
<div class="col-md-12" ng-if="isAuthorized('admin')">
|
||||||
<uib-tabset justified="true" active="tabs.active">
|
<uib-tabset justified="true" active="tabs.active">
|
||||||
<uib-tab heading="{{ 'app.admin.invoices.invoices_list' | translate }}" ng-hide="fablabWithoutInvoices" index="0">
|
<uib-tab heading="{{ 'app.admin.invoices.invoices_list' | translate }}" ng-show="modules.invoicing" index="0">
|
||||||
<ng-include src="'<%= asset_path "admin/invoices/list.html" %>'"></ng-include>
|
<ng-include src="'<%= asset_path "admin/invoices/list.html" %>'"></ng-include>
|
||||||
</uib-tab>
|
</uib-tab>
|
||||||
|
|
||||||
@ -41,6 +41,10 @@
|
|||||||
<uib-tab heading="{{ 'app.admin.invoices.accounting_codes' | translate }}" index="2" class="accounting-codes-tab">
|
<uib-tab heading="{{ 'app.admin.invoices.accounting_codes' | translate }}" index="2" class="accounting-codes-tab">
|
||||||
<ng-include src="'<%= asset_path "admin/invoices/codes.html" %>'"></ng-include>
|
<ng-include src="'<%= asset_path "admin/invoices/codes.html" %>'"></ng-include>
|
||||||
</uib-tab>
|
</uib-tab>
|
||||||
|
|
||||||
|
<uib-tab heading="{{ 'app.admin.invoices.payment.payment_settings' | translate }}" index="3" class="payment-settings">
|
||||||
|
<ng-include src="'<%= asset_path "admin/invoices/payment.html" %>'"></ng-include>
|
||||||
|
</uib-tab>
|
||||||
</uib-tabset>
|
</uib-tabset>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
114
app/assets/templates/admin/invoices/payment.html.erb
Normal file
114
app/assets/templates/admin/invoices/payment.html.erb
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
<div class="panel panel-default m-t-md">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<span class="font-sbold" translate>{{ 'app.admin.invoices.payment.payment_settings' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="row">
|
||||||
|
<h3 class="m-l" translate>{{ 'app.admin.invoices.payment.online_payment' }}</h3>
|
||||||
|
<p class="alert alert-warning m-h-md" ng-bind-html="'app.admin.invoices.payment.online_payment_info_html' | translate"></p>
|
||||||
|
<boolean-setting name="online_payment_module"
|
||||||
|
settings="allSettings"
|
||||||
|
label="app.admin.invoices.payment.enable_online_payment"
|
||||||
|
classes="m-l"
|
||||||
|
on-before-save="requireStripeKeys"
|
||||||
|
fa-icon="fa-font">
|
||||||
|
</boolean-setting>
|
||||||
|
</div>
|
||||||
|
<div class="row m-t" ng-show="allSettings.online_payment_module === 'true'">
|
||||||
|
<h3 class="m-l" translate>{{ 'app.admin.invoices.payment.stripe_keys' }}</h3>
|
||||||
|
<div class="col-md-4 m-l">
|
||||||
|
<label for="stripe_public_key" class="control-label">{{ 'app.admin.invoices.payment.public_key' | translate }}</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-addon"><i class="fa fa-info"></i></span>
|
||||||
|
<input type="text"
|
||||||
|
class="form-control"
|
||||||
|
id="stripe_public_key"
|
||||||
|
ng-model="allSettings.stripe_public_key"
|
||||||
|
readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 col-md-offset-1">
|
||||||
|
<label for="stripe_secret_key" class="control-label">{{ 'app.admin.invoices.payment.secret_key' | translate }}</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-addon"><i class="fa fa-key"></i></span>
|
||||||
|
<input type="password"
|
||||||
|
class="form-control"
|
||||||
|
id="stripe_secret_key"
|
||||||
|
ng-model="stripeSecretKey"
|
||||||
|
readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-1">
|
||||||
|
<button class="btn btn-default m-t-lg" ng-click="requireStripeKeys(allSettings.online_payment_module)" translate>{{ 'app.admin.invoices.payment.edit_keys' }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row m-t" ng-show="allSettings.online_payment_module === 'true'">
|
||||||
|
<h3 class="m-l" translate>{{ 'app.admin.invoices.payment.currency' }}</h3>
|
||||||
|
<p class="alert alert-warning m-h-md" ng-bind-html="'app.admin.invoices.payment.currency_info_html' | translate"></p>
|
||||||
|
<p class="alert alert-danger m-h-md" ng-bind-html="'app.admin.invoices.payment.currency_alert_html' | translate"></p>
|
||||||
|
<div class="col-md-4 m-l">
|
||||||
|
<text-setting name="stripe_currency"
|
||||||
|
settings="allSettings"
|
||||||
|
label="app.admin.invoices.payment.stripe_currency"
|
||||||
|
fa-icon="fa-money"
|
||||||
|
placeholder="XXX"
|
||||||
|
required="true"
|
||||||
|
min-length="3"
|
||||||
|
max-length="3"
|
||||||
|
read-only="onlinePaymentStatus">
|
||||||
|
</text-setting>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/ng-template" id="stripeKeys.html">
|
||||||
|
<div>
|
||||||
|
<div class="modal-header">
|
||||||
|
<h3 class="modal-title" translate>{{ 'app.admin.invoices.payment.stripe_keys' }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="alert alert-info" ng-bind-html="'app.admin.invoices.payment.stripe_keys_info_html' | translate"></div>
|
||||||
|
<form name="stripeKeysForm">
|
||||||
|
<div class="row m-md">
|
||||||
|
<label for="stripe_public_key" class="control-label">{{ 'app.admin.invoices.payment.public_key' | translate }} *</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-addon"><i class="fa fa-info"></i></span>
|
||||||
|
<input type="text"
|
||||||
|
class="form-control"
|
||||||
|
id="stripe_public_key"
|
||||||
|
ng-model="publicKey"
|
||||||
|
ng-model-options='{ debounce: 200 }'
|
||||||
|
ng-change='testPublicKey()'
|
||||||
|
required>
|
||||||
|
<span class="input-group-addon" ng-class="{'label-success': publicKeyStatus, 'label-danger text-white': !publicKeyStatus}" ng-show="publicKeyStatus !== undefined && publicKey">
|
||||||
|
<i class="fa fa-times" ng-show="!publicKeyStatus"></i>
|
||||||
|
<i class="fa fa-check" ng-show="publicKeyStatus"></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row m-md">
|
||||||
|
<label for="stripe_secret_key" class="control-label">{{ 'app.admin.invoices.payment.secret_key' | translate }} *</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-addon"><i class="fa fa-key"></i></span>
|
||||||
|
<input type="text"
|
||||||
|
class="form-control"
|
||||||
|
id="stripe_secret_key"
|
||||||
|
ng-model="secretKey"
|
||||||
|
ng-model-options='{ debounce: 200 }'
|
||||||
|
ng-change='testSecretKey()'
|
||||||
|
required>
|
||||||
|
<span class="input-group-addon" ng-class="{'label-success': secretKeyStatus, 'label-danger text-white': !secretKeyStatus}" ng-show="secretKeyStatus !== undefined && secretKey">
|
||||||
|
<i class="fa fa-times" ng-show="!secretKeyStatus"></i>
|
||||||
|
<i class="fa fa-check" ng-show="secretKeyStatus"></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button class="btn btn-warning" ng-click="ok()" ng-disabled="stripeKeysForm.$invalid" translate>{{ 'app.shared.buttons.confirm' }}</button>
|
||||||
|
<button class="btn btn-default" ng-click="cancel()" translate>{{ 'app.shared.buttons.cancel' }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</script>
|
@ -1,4 +1,4 @@
|
|||||||
<div class="alert alert-warning p-md m-t" role="alert" ng-show="fablabWithoutInvoices">
|
<div class="alert alert-warning p-md m-t" role="alert" ng-hide="modules.invoicing">
|
||||||
<i class="fa fa-warning m-r"></i>
|
<i class="fa fa-warning m-r"></i>
|
||||||
<span translate>{{ 'app.admin.invoices.warning_invoices_disabled' }}</span>
|
<span translate>{{ 'app.admin.invoices.warning_invoices_disabled' }}</span>
|
||||||
</div>
|
</div>
|
||||||
@ -87,6 +87,11 @@
|
|||||||
ng-blur="legalsEditEnd($event)">
|
ng-blur="legalsEditEnd($event)">
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
<div class="invoice-file">
|
||||||
|
<h3 class="m-l" translate>{{ 'app.admin.invoices.filename' }}</h3>
|
||||||
|
<i class="fa fa-file-pdf-o" aria-hidden="true"></i>
|
||||||
|
<span class="filename"><span class="prefix" ng-click="openEditPrefix()">{{file.prefix}}</span>-{{file.nextId}}_{{file.date}}.pdf</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<script type="text/ng-template" id="editReference.html">
|
<script type="text/ng-template" id="editReference.html">
|
||||||
@ -308,3 +313,27 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<script type="text/ng-template" id="editPrefix.html">
|
||||||
|
<div class="custom-invoice">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h3 class="modal-title" translate>{{ 'app.admin.invoices.filename' }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p class="alert alert-info m-h-md" translate>
|
||||||
|
{{ 'app.admin.invoices.prefix_info' }}
|
||||||
|
</p>
|
||||||
|
<div>
|
||||||
|
<div class="model">
|
||||||
|
<label for="prefix" translate>{{ 'app.admin.invoices.prefix' }}</label>
|
||||||
|
<input type="text" id="prefix" class="form-control" ng-model="model">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button class="btn btn-warning" ng-click="ok()" translate>{{ 'app.shared.buttons.confirm' }}</button>
|
||||||
|
<button class="btn btn-default" ng-click="cancel()" translate>{{ 'app.shared.buttons.cancel' }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
@ -60,7 +60,7 @@
|
|||||||
</form>
|
</form>
|
||||||
</uib-tab>
|
</uib-tab>
|
||||||
|
|
||||||
<uib-tab heading="{{ 'app.admin.members_edit.subscription' | translate }}" ng-if="!fablabWithoutPlans">
|
<uib-tab heading="{{ 'app.admin.members_edit.subscription' | translate }}" ng-if="modules.plans">
|
||||||
|
|
||||||
|
|
||||||
<section class="panel panel-default bg-light m-lg">
|
<section class="panel panel-default bg-light m-lg">
|
||||||
@ -192,7 +192,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</uib-tab>
|
</uib-tab>
|
||||||
|
|
||||||
<uib-tab heading="{{ 'app.admin.members_edit.invoices' | translate }}" ng-hide="fablabWithoutInvoices">
|
<uib-tab heading="{{ 'app.admin.members_edit.invoices' | translate }}" ng-show="modules.invoicing">
|
||||||
<div class="col-md-12 m m-t-lg">
|
<div class="col-md-12 m m-t-lg">
|
||||||
|
|
||||||
|
|
||||||
@ -229,7 +229,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</uib-tab>
|
</uib-tab>
|
||||||
|
|
||||||
<uib-tab heading="{{ 'app.admin.members_edit.wallet' | translate }}" ng-hide="fablabWithoutWallet">
|
<uib-tab heading="{{ 'app.admin.members_edit.wallet' | translate }}" ng-show="modules.wallet">
|
||||||
<div class="col-md-12 m m-t-lg">
|
<div class="col-md-12 m m-t-lg">
|
||||||
<ng-include src="'<%= asset_path "wallet/show.html" %>'"></ng-include>
|
<ng-include src="'<%= asset_path "wallet/show.html" %>'"></ng-include>
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
<a class="btn btn-default" ng-href="api/members/export_members.xlsx" target="export-frame" ng-click="alertExport('members')">
|
<a class="btn btn-default" ng-href="api/members/export_members.xlsx" target="export-frame" ng-click="alertExport('members')">
|
||||||
<i class="fa fa-file-excel-o"></i> {{ 'app.admin.members.members' | translate }}
|
<i class="fa fa-file-excel-o"></i> {{ 'app.admin.members.members' | translate }}
|
||||||
</a>
|
</a>
|
||||||
<a class="btn btn-default" ng-href="api/members/export_subscriptions.xlsx" target="export-frame" ng-if="!fablabWithoutPlans" ng-click="alertExport('subscriptions')">
|
<a class="btn btn-default" ng-href="api/members/export_subscriptions.xlsx" target="export-frame" ng-if="modules.plans" ng-click="alertExport('subscriptions')">
|
||||||
<i class="fa fa-file-excel-o"></i> {{ 'app.admin.members.subscriptions' | translate }}
|
<i class="fa fa-file-excel-o"></i> {{ 'app.admin.members.subscriptions' | translate }}
|
||||||
</a>
|
</a>
|
||||||
<a class="btn btn-default" ng-href="api/members/export_reservations.xlsx" target="export-frame" ng-click="alertExport('reservations')">
|
<a class="btn btn-default" ng-href="api/members/export_reservations.xlsx" target="export-frame" ng-click="alertExport('reservations')">
|
||||||
|
@ -130,7 +130,7 @@
|
|||||||
<span class="input-group-addon btn btn-default btn-file"><span class="fileinput-new" translate>{{ 'app.shared.plan.attach_an_information_sheet' }}</span>
|
<span class="input-group-addon btn btn-default btn-file"><span class="fileinput-new" translate>{{ 'app.shared.plan.attach_an_information_sheet' }}</span>
|
||||||
<span class="fileinput-exists" translate>{{ 'app.shared.buttons.change' }}</span><input type="file"
|
<span class="fileinput-exists" translate>{{ 'app.shared.buttons.change' }}</span><input type="file"
|
||||||
name="plan[plan_file_attributes][attachment]"
|
name="plan[plan_file_attributes][attachment]"
|
||||||
accept="image/*, application/pdf"></span>
|
accept="image/jpeg,image/gif,image/png,application/pdf"></span>
|
||||||
<a class="input-group-addon btn btn-danger fileinput-exists" data-dismiss="fileinput" ng-click="deleteFile(file || plan.plan_file_attributes)"><i class="fa fa-trash-o"></i></a>
|
<a class="input-group-addon btn btn-danger fileinput-exists" data-dismiss="fileinput" ng-click="deleteFile(file || plan.plan_file_attributes)"><i class="fa fa-trash-o"></i></a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -73,8 +73,8 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<h3 ng-hide="fablabWithoutSpaces" translate>{{ 'app.admin.plans.edit.spaces' }}</h3>
|
<h3 ng-show="modules.spaces" translate>{{ 'app.admin.plans.edit.spaces' }}</h3>
|
||||||
<table class="table" ng-hide="fablabWithoutSpaces">
|
<table class="table" ng-show="modules.spaces">
|
||||||
<thead>
|
<thead>
|
||||||
<th translate>{{ 'app.admin.plans.edit.space' }}</th>
|
<th translate>{{ 'app.admin.plans.edit.space' }}</th>
|
||||||
<th translate>{{ 'app.admin.plans.edit.hourly_rate' }}</th>
|
<th translate>{{ 'app.admin.plans.edit.hourly_rate' }}</th>
|
||||||
|
@ -96,11 +96,11 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<h2 ng-hide="fablabWithoutSpaces" class="m-t-lg" translate>{{ 'app.admin.pricing.spaces' }}</h2>
|
<h2 ng-show="modules.spaces" class="m-t-lg" translate>{{ 'app.admin.pricing.spaces' }}</h2>
|
||||||
<div ng-hide="fablabWithoutSpaces" class="btn-group m-t-md m-b-md">
|
<div ng-show="modules.spaces" class="btn-group m-t-md m-b-md">
|
||||||
<button type="button" class="btn btn-warning" ng-click="addSpaceCredit($event)" translate>{{ 'app.admin.pricing.add_a_space_credit' }}</button>
|
<button type="button" class="btn btn-warning" ng-click="addSpaceCredit($event)" translate>{{ 'app.admin.pricing.add_a_space_credit' }}</button>
|
||||||
</div>
|
</div>
|
||||||
<table ng-hide="fablabWithoutSpaces" class="table">
|
<table ng-show="modules.spaces" class="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="width:20%" translate>{{ 'app.admin.pricing.space' }}</th>
|
<th style="width:20%" translate>{{ 'app.admin.pricing.space' }}</th>
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
<ng-include src="'<%= asset_path "admin/pricing/machine_hours.html" %>'"></ng-include>
|
<ng-include src="'<%= asset_path "admin/pricing/machine_hours.html" %>'"></ng-include>
|
||||||
</uib-tab>
|
</uib-tab>
|
||||||
|
|
||||||
<uib-tab heading="{{ 'app.admin.pricing.spaces' | translate }}" ng-hide="fablabWithoutSpaces" index="3" class="spaces-tab">
|
<uib-tab heading="{{ 'app.admin.pricing.spaces' | translate }}" ng-show="modules.spaces" index="3" class="spaces-tab">
|
||||||
<ng-include src="'<%= asset_path "admin/pricing/spaces.html" %>'"></ng-include>
|
<ng-include src="'<%= asset_path "admin/pricing/spaces.html" %>'"></ng-include>
|
||||||
</uib-tab>
|
</uib-tab>
|
||||||
|
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
<h2 translate>{{ 'app.admin.pricing.list_of_the_subscription_plans' }}</h2>
|
<h2 translate>{{ 'app.admin.pricing.list_of_the_subscription_plans' }}</h2>
|
||||||
|
|
||||||
<div ng-show="fablabWithoutPlans" class="alert alert-warning m-t">
|
<div ng-hide="modules.plans"
|
||||||
{{ 'app.admin.pricing.beware_the_subscriptions_are_disabled_on_this_application' | translate }}
|
class="alert alert-warning m-t"
|
||||||
{{ 'app.admin.pricing.you_can_create_some_but_they_wont_be_available_until_the_project_is_redeployed_by_the_server_manager' | translate }}
|
ng-bind-html="'app.admin.pricing.disabled_plans_info_html' | translate">
|
||||||
<br>{{ 'app.admin.pricing.for_safety_reasons_please_dont_create_subscriptions_if_you_dont_want_intend_to_use_them_later' | translate }}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="m-t-lg">
|
<div class="m-t-lg">
|
||||||
|
@ -7,20 +7,20 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-xs-10 col-sm-10 col-md-8 b-l">
|
<div class="col-xs-10 col-sm-10 col-md-8 b-l">
|
||||||
<section class="heading-title">
|
<section class="heading-title">
|
||||||
<h1 translate>{{ 'app.admin.project_elements.projects_elements_management' }}</h1>
|
<h1 translate>{{ 'app.admin.projects.projects_settings' }}</h1>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-12 col-sm-12 col-md-3 b-t hide-b-md">
|
<div class="col-xs-12 col-sm-12 col-md-3 b-t hide-b-md">
|
||||||
<section class="heading-actions wrapper">
|
<section class="heading-actions wrapper">
|
||||||
<a class="btn btn-ng btn-warning b-2x rounded m-t-sm upper text-sm abuses-button" ui-sref="app.admin.manage_abuses" role="button" translate>{{ 'app.admin.project_elements.manage_abuses' }}</a>
|
<a class="btn btn-ng btn-warning b-2x rounded m-t-sm upper text-sm abuses-button" ui-sref="app.admin.manage_abuses" role="button" translate>{{ 'app.admin.projects.manage_abuses' }}</a>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
||||||
<section class="m-lg project-elements"
|
<section class="m-lg projects"
|
||||||
ui-tour="project-elements"
|
ui-tour="projects"
|
||||||
ui-tour-backdrop="true"
|
ui-tour-backdrop="true"
|
||||||
ui-tour-template-url="'<%= asset_path "shared/tour-step-template.html" %>'"
|
ui-tour-template-url="'<%= asset_path "shared/tour-step-template.html" %>'"
|
||||||
ui-tour-use-hotkeys="true"
|
ui-tour-use-hotkeys="true"
|
||||||
@ -29,15 +29,18 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<uib-tabset justified="true">
|
<uib-tabset justified="true" active="tabs.active">
|
||||||
<uib-tab heading="{{ 'app.admin.project_elements.materials' | translate }}">
|
<uib-tab heading="{{ 'app.admin.projects.materials' | translate }}" index="0">
|
||||||
<ng-include src="'<%= asset_path "admin/project_elements/materials.html" %>'"></ng-include>
|
<ng-include src="'<%= asset_path "admin/projects/materials.html" %>'"></ng-include>
|
||||||
</uib-tab>
|
</uib-tab>
|
||||||
<uib-tab heading="{{ 'app.admin.project_elements.themes' | translate }}">
|
<uib-tab heading="{{ 'app.admin.projects.themes' | translate }}" index="1">
|
||||||
<ng-include src="'<%= asset_path "admin/project_elements/themes.html" %>'"></ng-include>
|
<ng-include src="'<%= asset_path "admin/projects/themes.html" %>'"></ng-include>
|
||||||
</uib-tab>
|
</uib-tab>
|
||||||
<uib-tab heading="{{ 'app.admin.project_elements.licences' | translate }}">
|
<uib-tab heading="{{ 'app.admin.projects.licences' | translate }}" index="2">
|
||||||
<ng-include src="'<%= asset_path "admin/project_elements/licences.html" %>'"></ng-include>
|
<ng-include src="'<%= asset_path "admin/projects/licences.html" %>'"></ng-include>
|
||||||
|
</uib-tab>
|
||||||
|
<uib-tab heading="{{ 'app.admin.projects.settings.title' | translate }}" index="3" class="settings-tab">
|
||||||
|
<ng-include src="'<%= asset_path "admin/projects/settings.html" %>'"></ng-include>
|
||||||
</uib-tab>
|
</uib-tab>
|
||||||
</uib-tabset>
|
</uib-tabset>
|
||||||
</div>
|
</div>
|
@ -1,10 +1,10 @@
|
|||||||
<button type="button" class="btn btn-warning m-t m-b" ng-click="addLicence()" translate>{{ 'app.admin.project_elements.add_a_new_licence' }}</button>
|
<button type="button" class="btn btn-warning m-t m-b" ng-click="addLicence()" translate>{{ 'app.admin.projects.add_a_new_licence' }}</button>
|
||||||
|
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="width:30%" translate>{{ 'app.admin.project_elements.name' }}</th>
|
<th style="width:30%" translate>{{ 'app.admin.projects.name' }}</th>
|
||||||
<th style="width:50%" class="hidden-xs" translate>{{ 'app.admin.project_elements.description' }}</th>
|
<th style="width:50%" class="hidden-xs" translate>{{ 'app.admin.projects.description' }}</th>
|
||||||
<th style="width:20%"></th>
|
<th style="width:20%"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
@ -1,9 +1,9 @@
|
|||||||
<button type="button" class="btn btn-warning m-b m-t" ng-click="addComponent()" translate>{{ 'app.admin.project_elements.add_a_material' }}</button>
|
<button type="button" class="btn btn-warning m-b m-t" ng-click="addComponent()" translate>{{ 'app.admin.projects.add_a_material' }}</button>
|
||||||
|
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="width:80%" translate>{{ 'app.admin.project_elements.name' }}</th>
|
<th style="width:80%" translate>{{ 'app.admin.projects.name' }}</th>
|
||||||
<th style="width:20%"></th>
|
<th style="width:20%"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
98
app/assets/templates/admin/projects/settings.html.erb
Normal file
98
app/assets/templates/admin/projects/settings.html.erb
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
<div class="panel panel-default m-t-lg">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<span class="font-sbold" translate>{{ 'app.admin.projects.settings.comments' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="row">
|
||||||
|
<h3 class="m-l" translate>{{ 'app.admin.projects.settings.disqus' }}</h3>
|
||||||
|
<p class="alert alert-warning m-h-md" translate>{{ 'app.admin.projects.settings.disqus_info' }}</p>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<text-setting name="disqus_shortname"
|
||||||
|
settings="allSettings"
|
||||||
|
label="app.admin.projects.settings.shortname"
|
||||||
|
fa-icon="fa-comments"
|
||||||
|
placeholder="my-forum">
|
||||||
|
</text-setting>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel panel-default m-t-lg">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<span class="font-sbold" translate>{{ 'app.admin.projects.settings.cad_files' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="row">
|
||||||
|
<h3 class="m-l" translate>{{ 'app.admin.projects.settings.validation' }}</h3>
|
||||||
|
<p class="alert alert-warning m-h-md" translate>{{ 'app.admin.projects.settings.validation_info' }}</p>
|
||||||
|
<div class="col-md-5">
|
||||||
|
<select-multiple-setting name="allowed_cad_extensions"
|
||||||
|
settings="allSettings"
|
||||||
|
label="app.admin.projects.settings.extensions"
|
||||||
|
title-new="app.admin.projects.settings.new_extension"
|
||||||
|
description-new="app.admin.projects.settings.new_ext_info_html"
|
||||||
|
before-add="removeInitialDot">
|
||||||
|
</select-multiple-setting>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-5 col-md-offset-2">
|
||||||
|
<select-multiple-setting name="allowed_cad_mime_types"
|
||||||
|
settings="allSettings"
|
||||||
|
label="app.admin.projects.settings.mime_types"
|
||||||
|
title-new="app.admin.projects.settings.new_mime_type"
|
||||||
|
description-new="app.admin.projects.settings.new_type_info_html"
|
||||||
|
before-add="lower">
|
||||||
|
</select-multiple-setting>
|
||||||
|
</div>
|
||||||
|
<form name="mimeTestForm" class="col-md-6 m-t-lg" ng-upload="onTestFileComplete(content)" upload-options-enable-rails-csrf="true" action="/api/files/mime_type">
|
||||||
|
<label for="testFile" class="control-label" translate>{{ 'app.admin.projects.settings.test_file' }}</label>
|
||||||
|
<div class="fileinput input-group" data-provides="fileinput" ng-class="fileinputClass()">
|
||||||
|
<div class="form-control" data-trigger="fileinput">
|
||||||
|
<i class="glyphicon glyphicon-file fileinput-exists"></i> <span class="fileinput-filename">{{file.attachment}}</span>
|
||||||
|
</div>
|
||||||
|
<span class="input-group-addon btn btn-default btn-file">
|
||||||
|
<span class="fileinput-new" translate>{{ 'app.admin.projects.settings.set_a_file' }}</span>
|
||||||
|
<span class="fileinput-exists" translate>{{ 'app.shared.buttons.change' }}</span>
|
||||||
|
<input type="file" id="testFile" name="attachment" accept="*/*" required>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<input type="submit" class="btn btn-warning" ng-disabled="mimeTestForm.$invalid || $isUploading">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel panel-default m-t-lg">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<span class="font-sbold" translate>{{ 'app.admin.projects.settings.projects_sharing' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="row">
|
||||||
|
<h3 class="m-l" translate>{{ 'app.admin.projects.settings.open_lab_projects' }}</h3>
|
||||||
|
<p class="alert alert-warning m-h-md" ng-bind-html="'app.admin.projects.settings.open_lab_info_html' | translate"></p>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<text-setting name="openlab_app_id"
|
||||||
|
settings="allSettings"
|
||||||
|
label="app.admin.projects.settings.open_lab_app_id"
|
||||||
|
fa-icon="fa-info">
|
||||||
|
</text-setting>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 col-md-offset-2">
|
||||||
|
<text-setting name="openlab_app_secret"
|
||||||
|
settings="allSettings"
|
||||||
|
label="app.admin.projects.settings.open_lab_app_secret"
|
||||||
|
fa-icon="fa-key">
|
||||||
|
</text-setting>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row m-t" ng-show="allSettings.openlab_app_secret">
|
||||||
|
<p class="alert alert-warning m-h-md" ng-bind-html="'app.admin.projects.settings.openlab_default_info_html' | translate"></p>
|
||||||
|
<boolean-setting name="openlab_default"
|
||||||
|
settings="allSettings"
|
||||||
|
label="app.admin.projects.settings.default_to_openlab"
|
||||||
|
classes="m-l"
|
||||||
|
yes-label="app.shared.buttons.yes"
|
||||||
|
no-label="app.shared.buttons.no"></boolean-setting>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -1,9 +1,9 @@
|
|||||||
<button type="button" class="btn btn-warning m-t m-b" ng-click="addTheme()" translate>{{ 'app.admin.project_elements.add_a_new_theme' }}</button>
|
<button type="button" class="btn btn-warning m-t m-b" ng-click="addTheme()" translate>{{ 'app.admin.projects.add_a_new_theme' }}</button>
|
||||||
|
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="width:80%" translate>{{ 'app.admin.project_elements.name' }}</th>
|
<th style="width:80%" translate>{{ 'app.admin.projects.name' }}</th>
|
||||||
<th style="width:20%"></th>
|
<th style="width:20%"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
@ -4,16 +4,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<form role="form" novalidate>
|
<text-setting name="link_name"
|
||||||
<label for="linkName" class="control-label m-r" translate>{{ 'app.admin.settings.link_to_about' }}</label>
|
settings="allSettings"
|
||||||
<div class="form-group">
|
label="app.admin.settings.link_to_about"
|
||||||
<div class="input-group">
|
fa-icon="fa-link">
|
||||||
<div class="input-group-addon"><i class="fa fa-link"></i></div>
|
</text-setting>
|
||||||
<input type="text" id="linkName" ng-model="linkName.value" class="form-control" placeholder="{{ 'app.admin.settings.link_to_about' | translate }}"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button name="button" class="btn btn-warning" ng-click="save(linkName)" translate>{{ 'app.shared.buttons.save' }}</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
12
app/assets/templates/admin/settings/boolean.html
Normal file
12
app/assets/templates/admin/settings/boolean.html
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<div class="form-group {{classes}}">
|
||||||
|
<label for="setting-{{setting.name}}" class="control-label m-r" translate>{{ label }}</label>
|
||||||
|
<input bs-switch
|
||||||
|
ng-model="setting.value"
|
||||||
|
id="setting-{{setting.name}}"
|
||||||
|
type="checkbox"
|
||||||
|
class="form-control"
|
||||||
|
switch-on-text="{{ yesLabel | translate }}"
|
||||||
|
switch-off-text="{{ noLabel | translate }}"
|
||||||
|
switch-animate="true"/>
|
||||||
|
<button name="button" class="btn btn-warning m-l" ng-click="save(setting)" translate>{{ 'app.shared.buttons.save' }}</button>
|
||||||
|
</div>
|
@ -1,39 +1,34 @@
|
|||||||
<div class="panel panel-default m-t-md">
|
<div class="panel panel-default m-t-md">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<span class="font-sbold" translate>{{ 'app.admin.settings.title' }}</span>
|
<span class="font-sbold" translate>{{ 'app.admin.settings.general.title' }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<div class="row m-t-lg">
|
<div class="row m-t-lg">
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<form role="form" novalidate>
|
<text-setting name="fablab_name"
|
||||||
<label for="fablabName" class="control-label m-r" translate>{{ 'app.admin.settings.fablab_title' }}</label>
|
settings="allSettings"
|
||||||
<div class="form-group">
|
label="app.admin.settings.general.fablab_title"
|
||||||
<div class="input-group">
|
fa-icon="fa-font">
|
||||||
<div class="input-group-addon"><i class="fa fa-font"></i></div>
|
</text-setting>
|
||||||
<input type="text" id="fablabName" ng-model="fablabName.value" class="form-control" placeholder="{{ 'app.admin.settings.fablab_name' | translate }}"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button name="button" class="btn btn-warning" ng-click="save(fablabName)" translate>{{ 'app.shared.buttons.save' }}</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-4 col-md-offset-1">
|
<div class="col-md-4 col-md-offset-1">
|
||||||
<form role="form" novalidate>
|
<form role="form" novalidate>
|
||||||
<h4 class="control-label m-r" translate>{{ 'app.admin.settings.title_concordance' }}</h4>
|
<h4 class="control-label m-r" translate>{{ 'app.admin.settings.general.title_concordance' }}</h4>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="nameGenreMale">
|
<label for="nameGenreMale">
|
||||||
<input type="radio" name="nameGenre" id="nameGenreMale" ng-model="nameGenre.value" ng-value="'male'" />
|
<input type="radio" name="nameGenre" id="nameGenreMale" ng-model="nameGenre.value" ng-value="'male'" />
|
||||||
{{ 'app.admin.settings.male' | translate }} <span style="font-weight: normal">{{ 'app.admin.settings.eg' | translate }} <cite>{{ 'app.admin.settings.the_team' | translate }} <strong translate>{{ 'app.admin.settings.male_preposition' }}</strong> {{fablabName.value}}</cite></span>
|
{{ 'app.admin.settings.general.male' | translate }} <span style="font-weight: normal">{{ 'app.admin.settings.general.eg' | translate }} <cite>{{ 'app.admin.settings.general.the_team' | translate }} <strong translate>{{ 'app.admin.settings.general.male_preposition' }}</strong> {{allSettings.fablab_name}}</cite></span>
|
||||||
</label>
|
</label>
|
||||||
<br/>
|
<br/>
|
||||||
<label for="nameGenreFemale">
|
<label for="nameGenreFemale">
|
||||||
<input type="radio" name="nameGenre" id="nameGenreFemale" ng-model="nameGenre.value" ng-value="'female'" />
|
<input type="radio" name="nameGenre" id="nameGenreFemale" ng-model="nameGenre.value" ng-value="'female'" />
|
||||||
{{ 'app.admin.settings.female' | translate }} <span style="font-weight: normal">{{ 'app.admin.settings.eg' | translate }} <cite>{{ 'app.admin.settings.the_team' | translate }} <strong translate>{{ 'app.admin.settings.female_preposition' }}</strong> {{fablabName.value}}</cite></span>
|
{{ 'app.admin.settings.general.female' | translate }} <span style="font-weight: normal">{{ 'app.admin.settings.general.eg' | translate }} <cite>{{ 'app.admin.settings.general.the_team' | translate }} <strong translate>{{ 'app.admin.settings.general.female_preposition' }}</strong> {{allSettings.fablab_name}}</cite></span>
|
||||||
</label>
|
</label>
|
||||||
<br/>
|
<br/>
|
||||||
<label for="nameGenreNeutral">
|
<label for="nameGenreNeutral">
|
||||||
<input type="radio" name="nameGenre" id="nameGenreNeutral" ng-model="nameGenre.value" ng-value="'neutral'" />
|
<input type="radio" name="nameGenre" id="nameGenreNeutral" ng-model="nameGenre.value" ng-value="'neutral'" />
|
||||||
{{ 'app.admin.settings.neutral' | translate }} <span style="font-weight: normal">{{ 'app.admin.settings.eg' | translate }} <cite>{{ 'app.admin.settings.the_team' | translate }} <strong translate>{{ 'app.admin.settings.neutral_preposition' }}</strong> {{fablabName.value}}</cite></span>
|
{{ 'app.admin.settings.general.neutral' | translate }} <span style="font-weight: normal">{{ 'app.admin.settings.general.eg' | translate }} <cite>{{ 'app.admin.settings.general.the_team' | translate }} <strong translate>{{ 'app.admin.settings.general.neutral_preposition' }}</strong> {{allSettings.fablab_name}}</cite></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<button name="button" class="btn btn-warning" ng-click="save(nameGenre)" translate>{{ 'app.shared.buttons.save' }}</button>
|
<button name="button" class="btn btn-warning" ng-click="save(nameGenre)" translate>{{ 'app.shared.buttons.save' }}</button>
|
||||||
@ -94,7 +89,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<button name="button" class="btn btn-warning" ng-click="save(eventExplicationsAlert)" translate>{{ 'app.shared.buttons.save' }}</button>
|
<button name="button" class="btn btn-warning" ng-click="save(eventExplicationsAlert)" translate>{{ 'app.shared.buttons.save' }}</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3" ng-hide="fablabWithoutSpaces">
|
<div class="col-md-3" ng-show="modules.spaces">
|
||||||
<h4 translate>{{ 'app.admin.settings.message_of_the_spaces_page' }}</h4>
|
<h4 translate>{{ 'app.admin.settings.message_of_the_spaces_page' }}</h4>
|
||||||
<div ng-model="spaceExplicationsAlert.value" medium-editor options='{"placeholder": "{{ "app.admin.settings.type_the_message_content" | translate }}",
|
<div ng-model="spaceExplicationsAlert.value" medium-editor options='{"placeholder": "{{ "app.admin.settings.type_the_message_content" | translate }}",
|
||||||
"buttons": ["bold", "italic", "unorderedlist", "header2" ]
|
"buttons": ["bold", "italic", "unorderedlist", "header2" ]
|
||||||
@ -323,27 +318,172 @@
|
|||||||
|
|
||||||
<div class="panel panel-default m-t-lg">
|
<div class="panel panel-default m-t-lg">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<span class="font-sbold" translate>{{ 'app.admin.settings.elements_ordering' }}</span>
|
<span class="font-sbold" translate>{{ 'app.admin.settings.general.elements_ordering' }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<h3 class="m-l" translate>{{ 'app.admin.settings.machines_order' }}</h3>
|
<h3 class="m-l" translate>{{ 'app.admin.settings.general.machines_order' }}</h3>
|
||||||
<div class="form-group m-l">
|
<select-setting name="machines_sort_by"
|
||||||
<label for="machinesSortBy" class="control-label m-r" translate>{{ 'app.admin.settings.display_machines_sorted_by' }}</label>
|
settings="allSettings"
|
||||||
<select id="machinesSortBy"
|
classes="m-l"
|
||||||
class="form-control"
|
label="app.admin.settings.general.display_machines_sorted_by"
|
||||||
ng-model="machinesSortBy.value">
|
option-1="['default', 'app.admin.settings.general.sort_by.default']"
|
||||||
<option value="default" translate>{{ 'app.admin.settings.sort_by.default' }}</option>
|
option-2="['name', 'app.admin.settings.general.sort_by.name']"
|
||||||
<option value="name" translate>{{ 'app.admin.settings.sort_by.name' }}</option>
|
option-3="['created_at', 'app.admin.settings.general.sort_by.created_at']"
|
||||||
<option value="created_at" translate>{{ 'app.admin.settings.sort_by.created_at' }}</option>
|
option-4="['updated_at', 'app.admin.settings.general.sort_by.updated_at']">
|
||||||
<option value="updated_at" translate>{{ 'app.admin.settings.sort_by.updated_at' }}</option>
|
</select-setting>
|
||||||
</select>
|
|
||||||
<button name="button" class="btn btn-warning m-t" ng-click="save(machinesSortBy)" translate>{{ 'app.shared.buttons.save' }}</button>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-4">
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="panel panel-default m-t-lg">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<span class="font-sbold" translate>{{ 'app.admin.settings.general.help' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="row">
|
||||||
|
<h3 class="m-l" translate>{{ 'app.admin.settings.general.feature_tour' }}</h3>
|
||||||
|
<p class="alert alert-warning m-h-md" ng-bind-html="'app.admin.settings.general.feature_tour_info_html' | translate"></p>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<select-setting name="feature_tour_display"
|
||||||
|
settings="allSettings"
|
||||||
|
classes="m-l"
|
||||||
|
required="true"
|
||||||
|
label="app.admin.settings.general.feature_tour_display_mode"
|
||||||
|
option-1="['once', 'app.admin.settings.general.display_mode.once']"
|
||||||
|
option-2="['session', 'app.admin.settings.general.display_mode.session']"
|
||||||
|
option-3="['manual', 'app.admin.settings.general.display_mode.manual']">
|
||||||
|
</select-setting>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel panel-default m-t-lg">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<span class="font-sbold" translate>{{ 'app.admin.settings.general.notifications' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="row">
|
||||||
|
<h3 class="m-l" translate>{{ 'app.admin.settings.general.email' }}</h3>
|
||||||
|
<p class="alert alert-warning m-h-md" translate>{{ 'app.admin.settings.general.email_info' }}</p>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<text-setting name="email_from"
|
||||||
|
settings="allSettings"
|
||||||
|
label="app.admin.settings.general.email_from"
|
||||||
|
fa-icon="fa-paper-plane"
|
||||||
|
placeholder="noreply@example.com"
|
||||||
|
type="email"
|
||||||
|
required="true">
|
||||||
|
</text-setting>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel panel-default m-t-md">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<span class="font-sbold" translate>{{ 'app.admin.settings.account_creation' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="row">
|
||||||
|
<h3 class="m-l" translate>{{ 'app.admin.settings.phone' }}</h3>
|
||||||
|
<p class="alert alert-warning m-h-md" translate>
|
||||||
|
{{ 'app.admin.settings.phone_required_info' }}
|
||||||
|
</p>
|
||||||
|
<div class="col-md-10 col-md-offset-1">
|
||||||
|
<boolean-setting name="phone_required"
|
||||||
|
settings="allSettings"
|
||||||
|
label="app.admin.settings.phone_is_required"
|
||||||
|
yes-label="app.shared.buttons.yes"
|
||||||
|
no-label="app.shared.buttons.no">
|
||||||
|
</boolean-setting>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<h3 class="m-l" translate>{{ 'app.admin.settings.captcha' }}</h3>
|
||||||
|
<p class="alert alert-warning m-h-md" ng-bind-html="'app.admin.settings.captcha_info_html' | translate"></p>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<text-setting name="recaptcha_site_key"
|
||||||
|
settings="allSettings"
|
||||||
|
label="app.admin.settings.site_key"
|
||||||
|
fa-icon="fa-info"
|
||||||
|
placeholder="0000000000000000000000000000000000000000">
|
||||||
|
</text-setting>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<text-setting name="recaptcha_secret_key"
|
||||||
|
settings="allSettings"
|
||||||
|
label="app.admin.settings.secret_key"
|
||||||
|
fa-icon="fa-key"
|
||||||
|
placeholder="0000000000000000000000000000000000000000">
|
||||||
|
</text-setting>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<h3 class="m-l" translate>{{ 'app.admin.settings.account_confirmation' }}</h3>
|
||||||
|
<p class="alert alert-warning m-h-md" translate>
|
||||||
|
{{ 'app.admin.settings.confirmation_required_info' }}
|
||||||
|
</p>
|
||||||
|
<div class="col-md-10 col-md-offset-1">
|
||||||
|
<boolean-setting name="confirmation_required"
|
||||||
|
settings="allSettings"
|
||||||
|
label="app.admin.settings.confirmation_is_required"
|
||||||
|
yes-label="app.shared.buttons.yes"
|
||||||
|
no-label="app.shared.buttons.no">
|
||||||
|
</boolean-setting>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel panel-default m-t-lg">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<span class="font-sbold" translate>{{ 'app.admin.settings.modules' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<p class="alert alert-info"><i class="fa fa-info-circle m-r"></i><span translate>{{ 'app.admin.settings.remember_to_refresh_the_page_for_the_changes_to_take_effect' }}</span> </p>
|
||||||
|
<div class="row">
|
||||||
|
<h3 class="m-l" translate>{{ 'app.admin.settings.spaces' }}</h3>
|
||||||
|
<p class="alert alert-warning m-h-md" ng-bind-html="'app.admin.settings.spaces_info_html' | translate"></p>
|
||||||
|
<boolean-setting name="spaces_module"
|
||||||
|
settings="allSettings"
|
||||||
|
label="app.admin.settings.enable_spaces"
|
||||||
|
classes="m-l"
|
||||||
|
yes-label="app.shared.buttons.yes"
|
||||||
|
no-label="app.shared.buttons.no"></boolean-setting>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<h3 class="m-l" translate>{{ 'app.admin.settings.plans' }}</h3>
|
||||||
|
<p class="alert alert-warning m-h-md" ng-bind-html="'app.admin.settings.plans_info_html' | translate"></p>
|
||||||
|
<boolean-setting name="plans_module"
|
||||||
|
settings="allSettings"
|
||||||
|
label="app.admin.settings.enable_plans"
|
||||||
|
classes="m-l"
|
||||||
|
yes-label="app.shared.buttons.yes"
|
||||||
|
no-label="app.shared.buttons.no"></boolean-setting>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<h3 class="m-l" translate>{{ 'app.admin.settings.invoicing' }}</h3>
|
||||||
|
<p class="alert alert-warning m-h-md" ng-bind-html="'app.admin.settings.invoicing_info_html' | translate"></p>
|
||||||
|
<boolean-setting name="invoicing_module"
|
||||||
|
settings="allSettings"
|
||||||
|
label="app.admin.settings.enable_invoicing"
|
||||||
|
classes="m-l"
|
||||||
|
yes-label="app.shared.buttons.yes"
|
||||||
|
no-label="app.shared.buttons.no"></boolean-setting>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<h3 class="m-l" translate>{{ 'app.admin.settings.general.wallet' }}</h3>
|
||||||
|
<p class="alert alert-warning m-h-md" ng-bind-html="'app.admin.settings.general.wallet_info_html' | translate"></p>
|
||||||
|
<boolean-setting name="wallet_module"
|
||||||
|
settings="allSettings"
|
||||||
|
label="app.admin.settings.general.enable_wallet"
|
||||||
|
classes="m-l"
|
||||||
|
yes-label="app.shared.buttons.yes"
|
||||||
|
no-label="app.shared.buttons.no"></boolean-setting>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@ -20,20 +20,11 @@
|
|||||||
<button name="button" class="btn btn-warning" ng-click="save(homeBlogpostSetting)" translate>{{ 'app.shared.buttons.save' }}</button>
|
<button name="button" class="btn btn-warning" ng-click="save(homeBlogpostSetting)" translate>{{ 'app.shared.buttons.save' }}</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<h4 translate>{{ 'app.admin.settings.twitter_stream' }}</h4>
|
<text-setting name="twitter_name"
|
||||||
<form role="form" class="form-inline" name="twitterForm" novalidate>
|
settings="allSettings"
|
||||||
<div class="form-group">
|
label="app.admin.settings.twitter_stream"
|
||||||
<div class="input-group">
|
fa-icon="fa-twitter">
|
||||||
<div class="input-group-addon">
|
</text-setting>
|
||||||
<i class="fa fa-twitter"></i>
|
|
||||||
</div>
|
|
||||||
<input type="text" ng-model="twitterSetting.value" class="form-control" placeholder="{{ 'app.admin.settings.name_of_the_twitter_account' | translate }}"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<button name="button" class="btn btn-warning" ng-click="save(twitterSetting)" translate>{{ 'app.shared.buttons.save' }}</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row m-t-lg home-page-style">
|
<div class="row m-t-lg home-page-style">
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<uib-tabset justified="true" active="tabs.active">
|
<uib-tabset justified="true" active="tabs.active">
|
||||||
|
|
||||||
<uib-tab heading="{{ 'app.admin.settings.general' | translate }}" index="0">
|
<uib-tab heading="{{ 'app.admin.settings.general.general' | translate }}" index="0" class="general-page-tab">
|
||||||
<ng-include src="'<%= asset_path "admin/settings/general.html" %>'"></ng-include>
|
<ng-include src="'<%= asset_path "admin/settings/general.html" %>'"></ng-include>
|
||||||
</uib-tab>
|
</uib-tab>
|
||||||
|
|
||||||
@ -42,7 +42,7 @@
|
|||||||
<ng-include src="'<%= asset_path "admin/settings/privacy.html" %>'"></ng-include>
|
<ng-include src="'<%= asset_path "admin/settings/privacy.html" %>'"></ng-include>
|
||||||
</uib-tab>
|
</uib-tab>
|
||||||
|
|
||||||
<uib-tab heading="{{ 'app.admin.settings.reservations' | translate }}" index="4">
|
<uib-tab heading="{{ 'app.admin.settings.reservations' | translate }}" index="4" class="reservations-page-tab">
|
||||||
<ng-include src="'<%= asset_path "admin/settings/reservations.html" %>'"></ng-include>
|
<ng-include src="'<%= asset_path "admin/settings/reservations.html" %>'"></ng-include>
|
||||||
</uib-tab>
|
</uib-tab>
|
||||||
</uib-tabset>
|
</uib-tabset>
|
||||||
|
15
app/assets/templates/admin/settings/number.html
Normal file
15
app/assets/templates/admin/settings/number.html
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<form class="{{classes}}" name="settingNumberForm">
|
||||||
|
<label for="setting-{{setting.name}}" class="control-label m-r" translate>{{ label }}</label>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-addon">
|
||||||
|
<i class="fa {{faIcon}}"></i>
|
||||||
|
</div>
|
||||||
|
<input type="number" class="form-control" id="setting-{{setting.name}}" ng-model="setting.value" min="{{min}}" ng-required="required">
|
||||||
|
</div>
|
||||||
|
<span class="help-block text-info text-xs" ng-show="helperText">
|
||||||
|
<i class="fa fa-lightbulb-o"></i> {{ helperText | translate }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<button name="button" class="btn btn-warning" ng-click="save(setting)" ng-disabled="settingNumberForm.$invalid" translate>{{ 'app.shared.buttons.save' }}</button>
|
||||||
|
</form>
|
@ -1,11 +1,11 @@
|
|||||||
<div class="panel panel-default m-t-md">
|
<div class="panel panel-default m-t-md">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<span class="font-sbold" translate>{{ 'app.admin.settings.privacy.title' }}</span>
|
<span class="font-sbold" translate>{{ 'app.admin.settings.privacy.privacy_policy' }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-4 col-md-offset-1">
|
<div class="col-md-6 col-md-offset-1">
|
||||||
<select class="form-control m-b history-select" ng-options="d.id as d.name for d in privacyDraftsHistory" ng-model="privacyPolicy.version" ng-change="handlePolicyRevisionChange()">
|
<select class="form-control m-b history-select" ng-options="d.id as d.name for d in privacyDraftsHistory" ng-model="privacyPolicy.version" ng-change="handlePolicyRevisionChange()">
|
||||||
<option value="" translate>{{ 'app.admin.settings.privacy.current_policy' }}</option>
|
<option value="" translate>{{ 'app.admin.settings.privacy.current_policy' }}</option>
|
||||||
</select>
|
</select>
|
||||||
@ -17,7 +17,7 @@
|
|||||||
<span class="help-block text-info text-xs"><i class="fa fa-lightbulb-o"></i> {{ 'app.admin.settings.drag_and_drop_to_insert_images' | translate }}</span>
|
<span class="help-block text-info text-xs"><i class="fa fa-lightbulb-o"></i> {{ 'app.admin.settings.drag_and_drop_to_insert_images' | translate }}</span>
|
||||||
<button name="button" class="btn btn-warning" ng-click="savePrivacyPolicy()" translate>{{ 'app.shared.buttons.save' }}</button>
|
<button name="button" class="btn btn-warning" ng-click="savePrivacyPolicy()" translate>{{ 'app.shared.buttons.save' }}</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4 col-md-offset-2">
|
<div class="col-md-3 col-md-offset-1">
|
||||||
<div ng-model="privacyDpoSetting.value" medium-editor options='{"placeholder": "{{ "app.admin.settings.privacy.input_the_dpo" | translate }}",
|
<div ng-model="privacyDpoSetting.value" medium-editor options='{"placeholder": "{{ "app.admin.settings.privacy.input_the_dpo" | translate }}",
|
||||||
"buttons": ["bold", "italic", "anchor", "header1", "header2" ]
|
"buttons": ["bold", "italic", "anchor", "header1", "header2" ]
|
||||||
}'>
|
}'>
|
||||||
@ -38,22 +38,62 @@
|
|||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-10 col-md-offset-1">
|
<div class="col-md-10 col-md-offset-1">
|
||||||
<label for="is_recurrent" translate>{{ 'app.admin.settings.fab_analytics' }}</label>
|
<boolean-setting
|
||||||
<input bs-switch
|
name="fab_analytics"
|
||||||
ng-model="fabAnalytics.value"
|
settings="allSettings"
|
||||||
id="is_recurrent"
|
label="app.admin.settings.fab_analytics">
|
||||||
type="checkbox"
|
</boolean-setting>
|
||||||
class="form-control"
|
|
||||||
switch-on-text="{{ 'app.shared.buttons.yes' | translate }}"
|
|
||||||
switch-off-text="{{ 'app.shared.buttons.no' | translate }}"
|
|
||||||
switch-animate="true"/>
|
|
||||||
<p>
|
<p>
|
||||||
<span translate>{{ 'app.admin.settings.privacy.about_analytics' }}</span>
|
<span translate>{{ 'app.admin.settings.privacy.about_analytics' }}</span>
|
||||||
<a ng-click="analyticsModal()" class="pointer" translate>{{ 'app.admin.settings.privacy.read_more' }}</a>
|
<a ng-click="analyticsModal()" class="pointer" translate>{{ 'app.admin.settings.privacy.read_more' }}</a>
|
||||||
</p>
|
</p>
|
||||||
<button name="button" class="btn btn-warning" ng-click="save(fabAnalytics)" translate>{{ 'app.shared.buttons.save' }}</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="panel panel-default m-t-md">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<span class="font-sbold" translate>{{ 'app.admin.settings.privacy.statistics' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<p class="alert alert-info"><i class="fa fa-info-circle m-r"></i><span translate>{{ 'app.admin.settings.remember_to_refresh_the_page_for_the_changes_to_take_effect' }}</span> </p>
|
||||||
|
<div class="row">
|
||||||
|
<h3 class="m-l" translate>{{ 'app.admin.settings.privacy.google_analytics' }}</h3>
|
||||||
|
<p class="alert alert-warning m-h-md" ng-bind-html="'app.admin.settings.privacy.tracking_id_info_html' | translate"></p>
|
||||||
|
<div class="col-md-4 col-md-offset-1">
|
||||||
|
<text-setting name="tracking_id"
|
||||||
|
settings="allSettings"
|
||||||
|
label="app.admin.settings.privacy.tracking_id"
|
||||||
|
placeholder="UA-000000-2">
|
||||||
|
</text-setting>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<h3 class="m-l" translate>{{ 'app.admin.settings.privacy.facebook' }}</h3>
|
||||||
|
<p class="alert alert-warning m-h-md" ng-bind-html="'app.admin.settings.privacy.facebook_info_html' | translate"></p>
|
||||||
|
<div class="col-md-4 col-md-offset-1">
|
||||||
|
<text-setting name="facebook_app_id"
|
||||||
|
settings="allSettings"
|
||||||
|
label="app.admin.settings.privacy.app_id"
|
||||||
|
placeholder="000000000000000">
|
||||||
|
</text-setting>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<h3 class="m-l" translate>{{ 'app.admin.settings.privacy.twitter' }}</h3>
|
||||||
|
<p class="alert alert-warning m-h-md" ng-bind-html="'app.admin.settings.privacy.twitter_info_html' | translate"></p>
|
||||||
|
<div class="col-md-4 col-md-offset-1">
|
||||||
|
<text-setting name="twitter_analytics"
|
||||||
|
settings="allSettings"
|
||||||
|
label="app.admin.settings.privacy.twitter_analytics"
|
||||||
|
placeholder="@username">
|
||||||
|
</text-setting>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@ -21,90 +21,76 @@
|
|||||||
<button name="button" class="btn btn-warning m-l" ng-click="save(windowEnd)" translate>{{ 'app.shared.buttons.save' }}</button>
|
<button name="button" class="btn btn-warning m-l" ng-click="save(windowEnd)" translate>{{ 'app.shared.buttons.save' }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="section-separator"></div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<h3 class="m-l m-t-lg" translate>{{ 'app.admin.settings.max_visibility' }}</h3>
|
<h3 class="m-l m-t-lg" translate>{{ 'app.admin.settings.max_visibility' }}</h3>
|
||||||
<form class="col-md-4" name="visibilityYearlyForm">
|
<number-setting name="visibility_yearly"
|
||||||
<label for="yearlySubscribers" class="control-label m-r" translate>{{ 'app.admin.settings.visibility_for_yearly_members' }}</label>
|
settings="allSettings"
|
||||||
<div class="form-group">
|
label="app.admin.settings.visibility_for_yearly_members"
|
||||||
<div class="input-group">
|
classes="col-md-4"
|
||||||
<div class="input-group-addon">
|
fa-icon="fa-calendar"
|
||||||
<i class="fa fa-calendar"></i>
|
min="1"
|
||||||
</div>
|
required="required">
|
||||||
<input type="number" class="form-control" id="yearlySubscribers" ng-model="visibilityYearly.value" min="1" required>
|
</number-setting>
|
||||||
</div>
|
<number-setting name="visibility_others"
|
||||||
</div>
|
settings="allSettings"
|
||||||
<button name="button" class="btn btn-warning" ng-click="save(visibilityYearly)" ng-disabled="visibilityYearlyForm.$invalid" translate>{{ 'app.shared.buttons.save' }}</button>
|
label="app.admin.settings.visibility_for_other_members"
|
||||||
</form>
|
classes="col-md-4 col-md-offset-2"
|
||||||
<form class="col-md-4 col-md-offset-2" name="visibilityOthersForm">
|
fa-icon="fa-calendar"
|
||||||
<label for="others" class="control-label m-r" translate>{{ 'app.admin.settings.visibility_for_other_members' }}</label>
|
min="1"
|
||||||
<div class="form-group">
|
required="required">
|
||||||
<div class="input-group">
|
</number-setting>
|
||||||
<div class="input-group-addon">
|
|
||||||
<i class="fa fa-calendar"></i>
|
|
||||||
</div>
|
|
||||||
<input type="number" class="form-control" id="others" ng-model="visibilityOthers.value" min="1" required>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button name="button" class="btn btn-warning" ng-click="save(visibilityOthers)" ng-disabled="visibilityOthersForm.$invalid" translate>{{ 'app.shared.buttons.save' }}</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="section-separator"></div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<h3 class="m-l m-t-lg" translate>{{ 'app.admin.settings.ability_for_the_users_to_move_their_reservations' }}</h3>
|
<h3 class="m-l m-t-lg" translate>{{ 'app.admin.settings.ability_for_the_users_to_move_their_reservations' }}</h3>
|
||||||
<div class="form-group m-l">
|
<div class="col-md-6">
|
||||||
<label for="enableMove" class="control-label m-r" translate>{{ 'app.admin.settings.reservations_shifting' }}</label>
|
<boolean-setting name="booking_move_enable" settings="allSettings" label="app.admin.settings.reservations_shifting" classes="m-l"></boolean-setting>
|
||||||
<input bs-switch
|
</div>
|
||||||
ng-model="enableMove.value"
|
<div class="col-md-6" ng-show="allSettings.booking_move_enable === 'true'">
|
||||||
id="enableMove"
|
<number-setting name="booking_move_delay"
|
||||||
type="checkbox"
|
settings="allSettings"
|
||||||
class="form-control"
|
label="app.admin.settings.prior_period_hours"
|
||||||
switch-on-text="{{ 'app.admin.settings.enabled' | translate }}"
|
classes="col-md-8"
|
||||||
switch-off-text="{{ 'app.admin.settings.disabled' | translate }}"
|
fa-icon="fa-clock-o"
|
||||||
switch-animate="true"/>
|
min="0"
|
||||||
<button name="button" class="btn btn-warning m-l" ng-click="save(enableMove)" translate>{{ 'app.shared.buttons.save' }}</button>
|
required="allSettings.booking_move_enable === 'true'">
|
||||||
|
</number-setting>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="row" ng-show="enableMove.value">
|
|
||||||
<form class="col-md-4" name="moveDelayForm">
|
|
||||||
<label for="moveDelay" class="control-label m-r" translate>{{ 'app.admin.settings.prior_period_hours' }}</label>
|
|
||||||
<div class="form-group">
|
|
||||||
<div class="input-group">
|
|
||||||
<div class="input-group-addon">
|
|
||||||
<i class="fa fa-clock-o"></i>
|
|
||||||
</div>
|
|
||||||
<input type="number" class="form-control" id="moveDelay" ng-model="moveDelay.value" min="0" ng-required="enableMove.value">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button name="button" class="btn btn-warning" ng-click="save(moveDelay)" ng-disabled="moveDelayForm.$invalid" translate>{{ 'app.shared.buttons.save' }}</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<h3 class="m-l m-t-lg" translate>{{ 'app.admin.settings.ability_for_the_users_to_cancel_their_reservations' }}</h3>
|
<h3 class="m-l m-t-lg" translate>{{ 'app.admin.settings.ability_for_the_users_to_cancel_their_reservations' }}</h3>
|
||||||
<div class="form-group m-l">
|
<div class="col-md-6">
|
||||||
<label for="enableCancel" class="control-label m-r" translate>{{ 'app.admin.settings.reservations_cancelling' }}</label>
|
<boolean-setting name="booking_cancel_enable" settings="allSettings" label="app.admin.settings.reservations_cancelling" classes="m-l"></boolean-setting>
|
||||||
<input bs-switch
|
</div>
|
||||||
ng-model="enableCancel.value"
|
<div class="col-md-6" ng-show="allSettings.booking_cancel_enable === 'true'">
|
||||||
id="enableCancel"
|
<number-setting name="booking_cancel_delay"
|
||||||
type="checkbox"
|
settings="allSettings"
|
||||||
class="form-control"
|
label="app.admin.settings.prior_period_hours"
|
||||||
switch-on-text="{{ 'app.admin.settings.enabled' | translate }}"
|
classes="col-md-8"
|
||||||
switch-off-text="{{ 'app.admin.settings.disabled' | translate }}"
|
fa-icon="fa-clock-o"
|
||||||
switch-animate="true"/>
|
min="0"
|
||||||
<button name="button" class="btn btn-warning m-l" ng-click="save(enableCancel)" translate>{{ 'app.shared.buttons.save' }}</button>
|
required="allSettings.booking_cancel_enable === 'true'">
|
||||||
|
</number-setting>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row" ng-show="enableCancel.value">
|
<div class="section-separator"></div>
|
||||||
<form class="col-md-4" name="cancelDelayForm">
|
<div class="row">
|
||||||
<label for="cancelDelay" class="control-label m-r" translate>{{ 'app.admin.settings.prior_period_hours' }}</label>
|
<h3 class="m-l m-t-lg" translate>{{ 'app.admin.settings.book_overlapping_slots_info' }}</h3>
|
||||||
<div class="form-group">
|
<boolean-setting name="book_overlapping_slots" settings="allSettings" label="app.admin.settings.allow_booking" classes="m-l"></boolean-setting>
|
||||||
<div class="input-group">
|
</div>
|
||||||
<div class="input-group-addon">
|
<div class="section-separator"></div>
|
||||||
<i class="fa fa-clock-o"></i>
|
<div class="row">
|
||||||
</div>
|
<h3 class="m-l m-t-lg" translate>{{ 'app.admin.settings.default_slot_duration' }}</h3>
|
||||||
<input type="number" class="form-control" id="cancelDelay" ng-model="cancelDelay.value" min="0" ng-required="enableCancel.value">
|
<p class="alert alert-warning m-h-md" translate>{{ 'app.admin.settings.default_slot_duration_info' }}</p>
|
||||||
</div>
|
<number-setting name="slot_duration"
|
||||||
</div>
|
settings="allSettings"
|
||||||
<button name="button" class="btn btn-warning" ng-click="save(cancelDelay)" ng-disabled="cancelDelayForm.$invalid" translate>{{ 'app.shared.buttons.save' }}</button>
|
label="app.admin.settings.duration_minutes"
|
||||||
</form>
|
classes="col-md-4"
|
||||||
|
fa-icon="fa-clock-o"
|
||||||
|
min="1"
|
||||||
|
required="required">
|
||||||
|
</number-setting>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -117,35 +103,17 @@
|
|||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<h3 class="m-l" translate>{{ 'app.admin.settings.notification_sending_before_the_reservation_occurs' }}</h3>
|
<h3 class="m-l" translate>{{ 'app.admin.settings.notification_sending_before_the_reservation_occurs' }}</h3>
|
||||||
<div class="form-group m-l">
|
<boolean-setting name="reminder_enable" settings="allSettings" label="app.admin.settings.reservations_reminders" classes="m-l"></boolean-setting>
|
||||||
<label for="enableReminder" class="control-label m-r" translate>{{ 'app.admin.settings.reservations_reminders' }}</label>
|
|
||||||
<input bs-switch
|
|
||||||
ng-model="enableReminder.value"
|
|
||||||
id="enableReminder"
|
|
||||||
type="checkbox"
|
|
||||||
class="form-control"
|
|
||||||
switch-on-text="{{ 'app.admin.settings.enabled' | translate }}"
|
|
||||||
switch-off-text="{{ 'app.admin.settings.disabled' | translate }}"
|
|
||||||
switch-animate="true"/>
|
|
||||||
<button name="button" class="btn btn-warning m-l" ng-click="save(enableReminder)" translate>{{ 'app.shared.buttons.save' }}</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="row" ng-show="enableReminder.value">
|
<div class="row" ng-show="allSettings.reminder_enable === 'true'">
|
||||||
<form class="col-md-4" name="reminderDelayForm">
|
<number-setting name="reminder_delay"
|
||||||
<label for="reminderDelay" class="control-label m-r" translate>{{ 'app.admin.settings.prior_period_hours' }}</label>
|
settings="allSettings"
|
||||||
<div class="form-group">
|
label="app.admin.settings.prior_period_hours"
|
||||||
<div class="input-group">
|
classes="col-md-4"
|
||||||
<div class="input-group-addon">
|
fa-icon="fa-clock-o"
|
||||||
<i class="fa fa-clock-o"></i>
|
helper-text="app.admin.settings.default_value_is_24_hours"
|
||||||
</div>
|
min="0">
|
||||||
<input type="number" class="form-control" id="reminderDelay" ng-model="reminderDelay.value" min="0">
|
</number-setting>
|
||||||
</div>
|
|
||||||
<span class="help-block text-info text-xs">
|
|
||||||
<i class="fa fa-lightbulb-o"></i> {{ 'app.admin.settings.default_value_is_24_hours' | translate }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<button name="button" class="btn btn-warning" ng-click="save(reminderDelay)" ng-disabled="reminderDelayForm.$invalid" translate>{{ 'app.shared.buttons.save' }}</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -153,23 +121,18 @@
|
|||||||
|
|
||||||
<div class="panel panel-default m-t-lg">
|
<div class="panel panel-default m-t-lg">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<span class="font-sbold" translate>{{ 'app.admin.settings.confidentiality' }}</span>
|
<span class="font-sbold" translate>{{ 'app.admin.settings.display' }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<h3 class="m-l" translate>{{ 'app.admin.settings.display_machine_reservation_user_name' }}</h3>
|
<h3 class="m-l" translate>{{ 'app.admin.settings.display_machine_reservation_user_name' }}</h3>
|
||||||
<div class="form-group m-l">
|
<p class="alert alert-warning m-h-md" ng-bind-html="'app.admin.settings.display_name_info_html' | translate"></p>
|
||||||
<label for="displayNameEnable" class="control-label m-r" translate>{{ 'app.admin.settings.display_name' }}</label>
|
<boolean-setting name="display_name_enable" settings="allSettings" label="app.admin.settings.display_name" classes="m-l"></boolean-setting>
|
||||||
<input bs-switch
|
|
||||||
ng-model="displayNameEnable.value"
|
|
||||||
id="displayNameEnable"
|
|
||||||
type="checkbox"
|
|
||||||
class="form-control"
|
|
||||||
switch-on-text="{{ 'app.admin.settings.enabled' | translate }}"
|
|
||||||
switch-off-text="{{ 'app.admin.settings.disabled' | translate }}"
|
|
||||||
switch-animate="true"/>
|
|
||||||
<button name="button" class="btn btn-warning m-l" ng-click="save(displayNameEnable)" translate>{{ 'app.shared.buttons.save' }}</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<h3 class="m-l" translate>{{ 'app.admin.settings.events_in_the_calendar' }}</h3>
|
||||||
|
<p class="alert alert-warning m-h-md" translate>{{ 'app.admin.settings.events_in_calendar_info' }}</p>
|
||||||
|
<boolean-setting name="events_in_calendar" settings="allSettings" label="app.admin.settings.show_event" classes="m-l"></boolean-setting>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
35
app/assets/templates/admin/settings/select-multiple.html
Normal file
35
app/assets/templates/admin/settings/select-multiple.html
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<form class="{{classes}}" name="settingSelectMultipleForm">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="setting-{{setting.name}}" class="control-label m-r" translate>{{ label }}</label>
|
||||||
|
<select class="form-control"
|
||||||
|
id="setting-{{setting.name}}"
|
||||||
|
ng-model="selection"
|
||||||
|
ng-required="required"
|
||||||
|
ng-options="opt for opt in options"
|
||||||
|
multiple>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button ng-click="removeItem()" class="btn btn-default"><i class="fa fa-trash"></i></button>
|
||||||
|
<button ng-click="addItem()" class="btn btn-default"><i class="fa fa-plus"></i></button>
|
||||||
|
</div>
|
||||||
|
<button name="button" class="btn btn-warning m-t" ng-click="save(setting)" ng-disabled="settingSelectMultipleForm.$invalid" translate>{{ 'app.shared.buttons.save' }}</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<script type="text/ng-template" id="newSelectOption.html">
|
||||||
|
<div>
|
||||||
|
<div class="modal-header">
|
||||||
|
<h3 class="modal-title" translate>{{ titleNew }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p class="alert alert-info" ng-show="descriptionNew" ng-bind-html="descriptionNew | translate"></p>
|
||||||
|
<form class="row m-md" name="newSelectOptionForm">
|
||||||
|
<input type="text" class="form-control" ng-model="value" required>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button class="btn btn-warning" ng-disabled="newSelectOptionForm.$invalid" ng-click="ok()" translate>{{ 'app.shared.buttons.confirm' }}</button>
|
||||||
|
<button class="btn btn-default" ng-click="dismiss()" translate>{{ 'app.shared.buttons.cancel' }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</script>
|
16
app/assets/templates/admin/settings/select.html
Normal file
16
app/assets/templates/admin/settings/select.html
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<form class="{{classes}}" name="settingSelectForm">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="setting-{{setting.name}}" class="control-label m-r" translate>{{ label }}</label>
|
||||||
|
<select class="form-control"
|
||||||
|
id="setting-{{setting.name}}"
|
||||||
|
ng-model="setting.value"
|
||||||
|
ng-required="required">
|
||||||
|
<option ng-if="option1" ng-value="option1[0]" translate>{{ option1[1] }}</option>
|
||||||
|
<option ng-if="option2" ng-value="option2[0]" translate>{{ option2[1] }}</option>
|
||||||
|
<option ng-if="option2" ng-value="option3[0]" translate>{{ option3[1] }}</option>
|
||||||
|
<option ng-if="option4" ng-value="option4[0]" translate>{{ option4[1] }}</option>
|
||||||
|
<option ng-if="option5" ng-value="option5[0]" translate>{{ option5[1] }}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<button name="button" class="btn btn-warning m-t" ng-click="save(setting)" ng-disabled="settingSelectForm.$invalid" translate>{{ 'app.shared.buttons.save' }}</button>
|
||||||
|
</form>
|
20
app/assets/templates/admin/settings/text.html
Normal file
20
app/assets/templates/admin/settings/text.html
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<form class="{{classes}}" name="settingTextForm">
|
||||||
|
<label for="setting-{{setting.name}}" class="control-label m-r" translate>{{ label }}</label>
|
||||||
|
<div ng-class="{'form-group': faIcon}">
|
||||||
|
<div ng-class="{'input-group': faIcon}">
|
||||||
|
<div class="input-group-addon" ng-if="faIcon">
|
||||||
|
<i class="fa {{faIcon}}"></i>
|
||||||
|
</div>
|
||||||
|
<input type="{{type}}"
|
||||||
|
class="form-control"
|
||||||
|
id="setting-{{setting.name}}"
|
||||||
|
placeholder="{{placeholder}}"
|
||||||
|
ng-model="setting.value"
|
||||||
|
ng-required="required"
|
||||||
|
ng-minlength="minLength"
|
||||||
|
ng-maxlength="maxLength"
|
||||||
|
ng-readonly="readOnly">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button name="button" class="btn btn-warning m-t" ng-click="save(setting)" ng-disabled="settingTextForm.$invalid || readOnly" translate>{{ 'app.shared.buttons.save' }}</button>
|
||||||
|
</form>
|
@ -102,7 +102,7 @@
|
|||||||
</form>
|
</form>
|
||||||
|
|
||||||
<uib-tabset justified="true">
|
<uib-tabset justified="true">
|
||||||
<uib-tab ng-repeat="stat in statistics" heading="{{stat.label}}" select="setActiveTab(stat)" ng-if="stat.graph && !(stat.es_type_key == 'subscription' && fablabWithoutPlans)" class="row">
|
<uib-tab ng-repeat="stat in statistics" heading="{{stat.label}}" select="setActiveTab(stat)" ng-if="stat.graph && !(stat.es_type_key == 'subscription' && modules.plans)" class="row">
|
||||||
|
|
||||||
<div ng-if="stat.graph.chart_type == 'discreteBarChart'">
|
<div ng-if="stat.graph.chart_type == 'discreteBarChart'">
|
||||||
<div id="rankingFilters">
|
<div id="rankingFilters">
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
<input class="col-md-1 col-sm-1 col-xs-1" type="checkbox" ng-model="m.checked" ng-change="filterAvailabilities(filter)">
|
<input class="col-md-1 col-sm-1 col-xs-1" type="checkbox" ng-model="m.checked" ng-change="filterAvailabilities(filter)">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="m-t" ng-hide="fablabWithoutSpaces">
|
<div class="m-t" ng-show="modules.spaces">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<h3 class="col-md-11 col-sm-11 col-xs-11 text-cyan" translate>{{ 'app.public.calendar.spaces' }}</h3>
|
<h3 class="col-md-11 col-sm-11 col-xs-11 text-cyan" translate>{{ 'app.public.calendar.spaces' }}</h3>
|
||||||
<input class="col-md-1 col-sm-1 col-xs-1" type="checkbox" ng-model="filter.spaces" ng-change="toggleFilter('spaces', filter)">
|
<input class="col-md-1 col-sm-1 col-xs-1" type="checkbox" ng-model="filter.spaces" ng-change="toggleFilter('spaces', filter)">
|
||||||
|
@ -15,8 +15,8 @@
|
|||||||
<li ui-sref-active="active"><a class="text-black" href="#" ui-sref="app.logged.dashboard.projects" translate>{{ 'app.public.common.my_projects' }}</a></li>
|
<li ui-sref-active="active"><a class="text-black" href="#" ui-sref="app.logged.dashboard.projects" translate>{{ 'app.public.common.my_projects' }}</a></li>
|
||||||
<li ui-sref-active="active"><a class="text-black" href="#" ui-sref="app.logged.dashboard.trainings" translate>{{ 'app.public.common.my_trainings' }}</a></li>
|
<li ui-sref-active="active"><a class="text-black" href="#" ui-sref="app.logged.dashboard.trainings" translate>{{ 'app.public.common.my_trainings' }}</a></li>
|
||||||
<li ui-sref-active="active"><a class="text-black" href="#" ui-sref="app.logged.dashboard.events" translate>{{ 'app.public.common.my_events' }}</a></li>
|
<li ui-sref-active="active"><a class="text-black" href="#" ui-sref="app.logged.dashboard.events" translate>{{ 'app.public.common.my_events' }}</a></li>
|
||||||
<li ui-sref-active="active" ng-hide="fablabWithoutInvoices"><a class="text-black" href="#" ui-sref="app.logged.dashboard.invoices" translate>{{ 'app.public.common.my_invoices' }}</a></li>
|
<li ui-sref-active="active" ng-show="modules.invoicing"><a class="text-black" href="#" ui-sref="app.logged.dashboard.invoices" translate>{{ 'app.public.common.my_invoices' }}</a></li>
|
||||||
<li ng-hide="fablabWithoutWallet" ui-sref-active="active"><a class="text-black" href="#" ui-sref="app.logged.dashboard.wallet" translate>{{ 'app.public.common.my_wallet' }}</a></li>
|
<li ng-show="modules.wallet" ui-sref-active="active"><a class="text-black" href="#" ui-sref="app.logged.dashboard.wallet" translate>{{ 'app.public.common.my_wallet' }}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
<button class="btn btn-success m-t" ng-click="selectGroup()">Changer mon groupe</button>
|
<button class="btn btn-success m-t" ng-click="selectGroup()">Changer mon groupe</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div ng-hide="fablabWithoutPlans">
|
<div ng-show="modules.plans">
|
||||||
<h3 class="text-u-c" translate>{{ 'app.logged.dashboard.settings.subscription' }}</h3>
|
<h3 class="text-u-c" translate>{{ 'app.logged.dashboard.settings.subscription' }}</h3>
|
||||||
<div ng-show="user.subscribed_plan">
|
<div ng-show="user.subscribed_plan">
|
||||||
<uib-alert type="warning">
|
<uib-alert type="warning">
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span class="btn btn-default btn-file"><span class="fileinput-new">{{ 'app.shared.event.choose_a_picture' | translate }} <i class="fa fa-upload fa-fw"></i></span><span class="fileinput-exists" translate>{{ 'app.shared.buttons.change' }}</span>
|
<span class="btn btn-default btn-file"><span class="fileinput-new">{{ 'app.shared.event.choose_a_picture' | translate }} <i class="fa fa-upload fa-fw"></i></span><span class="fileinput-exists" translate>{{ 'app.shared.buttons.change' }}</span>
|
||||||
<input type="file" name="event[event_image_attributes][attachment]"></span>
|
<input type="file" name="event[event_image_attributes][attachment]" accept="image/jpeg,image/gif,image/png"></span>
|
||||||
<a class="btn btn-danger fileinput-exists" data-dismiss="fileinput"><i class="fa fa-trash-o"></i></a>
|
<a class="btn btn-danger fileinput-exists" data-dismiss="fileinput"><i class="fa fa-trash-o"></i></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -66,7 +66,7 @@
|
|||||||
<i class="glyphicon glyphicon-file fileinput-exists"></i> <span class="fileinput-filename">{{file.attachment}}</span>
|
<i class="glyphicon glyphicon-file fileinput-exists"></i> <span class="fileinput-filename">{{file.attachment}}</span>
|
||||||
</div>
|
</div>
|
||||||
<span class="input-group-addon btn btn-default btn-file"><span class="fileinput-new" translate>{{ 'app.shared.buttons.browse' }}</span>
|
<span class="input-group-addon btn btn-default btn-file"><span class="fileinput-new" translate>{{ 'app.shared.buttons.browse' }}</span>
|
||||||
<span class="fileinput-exists" translate>{{ 'app.shared.buttons.change' }}</span><input type="file" name="event[event_files_attributes][][attachment]"></span>
|
<span class="fileinput-exists" translate>{{ 'app.shared.buttons.change' }}</span><input type="file" name="event[event_files_attributes][][attachment]" accept="application/pdf"></span>
|
||||||
<a class="input-group-addon btn btn-danger fileinput-exists" data-dismiss="fileinput" ng-click="deleteFile(file)"><i class="fa fa-trash-o"></i></a>
|
<a class="input-group-addon btn btn-danger fileinput-exists" data-dismiss="fileinput" ng-click="deleteFile(file)"><i class="fa fa-trash-o"></i></a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
<input type="file"
|
<input type="file"
|
||||||
ng-model="machine.machine_image"
|
ng-model="machine.machine_image"
|
||||||
name="machine[machine_image_attributes][attachment]"
|
name="machine[machine_image_attributes][attachment]"
|
||||||
accept="image/*"
|
accept="image/jpeg,image/gif,image/png"
|
||||||
required
|
required
|
||||||
bs-jasny-fileinput>
|
bs-jasny-fileinput>
|
||||||
</span>
|
</span>
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
<div class="row no-gutter machine-reserve">
|
<div class="row no-gutter machine-reserve">
|
||||||
<div class="col-sm-12 col-md-12 col-lg-9">
|
<div class="col-sm-12 col-md-12 col-lg-9">
|
||||||
<div ui-calendar="calendarConfig" ng-model="eventSources" calendar="calendar" class="wrapper-lg" ng-show="!plansAreShown"></div>
|
<div ui-calendar="calendarConfig" ng-model="eventSources" calendar="calendar" class="wrapper-lg" ng-show="!plansAreShown"></div>
|
||||||
<ng-include ng-if="!fablabWithoutPlans" src="'<%= asset_path "plans/_plan.html" %>'"></ng-include>
|
<ng-include ng-if="modules.plans" src="'<%= asset_path "plans/_plan.html" %>'"></ng-include>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,7 +30,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span class="btn btn-default btn-file"><span class="fileinput-new">{{ 'app.shared.project.add_an_illustration' | translate }} <i class="fa fa-upload fa-fw"></i></span><span class="fileinput-exists" translate>{{ 'app.shared.buttons.change' }}</span>
|
<span class="btn btn-default btn-file"><span class="fileinput-new">{{ 'app.shared.project.add_an_illustration' | translate }} <i class="fa fa-upload fa-fw"></i></span><span class="fileinput-exists" translate>{{ 'app.shared.buttons.change' }}</span>
|
||||||
<input type="file" name="project[project_image_attributes][attachment]"></span>
|
<input type="file"
|
||||||
|
name="project[project_image_attributes][attachment]"
|
||||||
|
accept="image/jpeg,image/gif,image/png"></span>
|
||||||
<a class="btn btn-danger fileinput-exists" data-dismiss="fileinput" translate>{{ 'app.shared.buttons.delete' }}</a>
|
<a class="btn btn-danger fileinput-exists" data-dismiss="fileinput" translate>{{ 'app.shared.buttons.delete' }}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -51,7 +53,9 @@
|
|||||||
<i class="glyphicon glyphicon-file fileinput-exists"></i> <span class="fileinput-filename">{{file.attachment}}</span>
|
<i class="glyphicon glyphicon-file fileinput-exists"></i> <span class="fileinput-filename">{{file.attachment}}</span>
|
||||||
</div>
|
</div>
|
||||||
<span class="input-group-addon btn btn-default btn-file"><span class="fileinput-new" translate>{{ 'app.shared.buttons.browse' }}</span>
|
<span class="input-group-addon btn btn-default btn-file"><span class="fileinput-new" translate>{{ 'app.shared.buttons.browse' }}</span>
|
||||||
<span class="fileinput-exists" translate>{{ 'app.shared.buttons.change' }}</span><input type="file" name="project[project_caos_attributes][][attachment]"></span>
|
<span class="fileinput-exists" translate>{{ 'app.shared.buttons.change' }}</span>
|
||||||
|
<input type="file" name="project[project_caos_attributes][][attachment]" accept="{{'.'+allowedExtensions.join(',.')}}">
|
||||||
|
</span>
|
||||||
<a class="input-group-addon btn btn-danger fileinput-exists" data-dismiss="fileinput" ng-click="deleteFile(file)"><i class="fa fa-trash-o"></i></a>
|
<a class="input-group-addon btn btn-danger fileinput-exists" data-dismiss="fileinput" ng-click="deleteFile(file)"><i class="fa fa-trash-o"></i></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -115,7 +119,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span class="btn btn-default btn-file"><span class="fileinput-new">{{ 'app.shared.buttons.browse' | translate }} <i class="fa fa-upload fa-fw"></i></span><span class="fileinput-exists" translate>{{ 'app.shared.buttons.change' }}</span>
|
<span class="btn btn-default btn-file"><span class="fileinput-new">{{ 'app.shared.buttons.browse' | translate }} <i class="fa fa-upload fa-fw"></i></span><span class="fileinput-exists" translate>{{ 'app.shared.buttons.change' }}</span>
|
||||||
<input type="file" name="project[project_steps_attributes][][project_step_images_attributes][][attachment]"></span>
|
<input type="file"
|
||||||
|
name="project[project_steps_attributes][][project_step_images_attributes][][attachment]"
|
||||||
|
accept="image/jpeg,image/gif,image/png">
|
||||||
|
</span>
|
||||||
<a class="btn btn-danger fileinput-exists" data-dismiss="fileinput" ng-click="deleteProjectStepImage(step, image)" translate>{{ 'app.shared.buttons.delete' }}</a>
|
<a class="btn btn-danger fileinput-exists" data-dismiss="fileinput" ng-click="deleteProjectStepImage(step, image)" translate>{{ 'app.shared.buttons.delete' }}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -52,7 +52,7 @@
|
|||||||
|
|
||||||
<coupon show="isSlotsValid() && (!modePlans || selectedPlan)" coupon="coupon.applied" total="totalNoCoupon" user-id="{{user.id}}"></coupon>
|
<coupon show="isSlotsValid() && (!modePlans || selectedPlan)" coupon="coupon.applied" total="totalNoCoupon" user-id="{{user.id}}"></coupon>
|
||||||
|
|
||||||
<div ng-hide="fablabWithoutPlans">
|
<div ng-show="modules.plans">
|
||||||
<div ng-if="isSlotsValid() && !user.subscribed_plan" ng-show="!modePlans">
|
<div ng-if="isSlotsValid() && !user.subscribed_plan" ng-show="!modePlans">
|
||||||
<p class="font-sbold text-base l-h-2x" translate>{{ 'app.shared.cart.to_benefit_from_attractive_prices' }}</p>
|
<p class="font-sbold text-base l-h-2x" translate>{{ 'app.shared.cart.to_benefit_from_attractive_prices' }}</p>
|
||||||
<div><button class="btn btn-warning-full rounded btn-block text-xs" ng-click="showPlans()" translate>{{ 'app.shared.cart.view_our_subscriptions' }}</button></div>
|
<div><button class="btn btn-warning-full rounded btn-block text-xs" ng-click="showPlans()" translate>{{ 'app.shared.cart.view_our_subscriptions' }}</button></div>
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
ng-hide="preventField['profile.avatar'] && user.profile.user_avatar.attachment_url && !userForm['user[profile_attributes][user_avatar_attributes]'].$dirty">
|
ng-hide="preventField['profile.avatar'] && user.profile.user_avatar.attachment_url && !userForm['user[profile_attributes][user_avatar_attributes]'].$dirty">
|
||||||
<span class="fileinput-new" translate>{{ 'app.shared.user.add_an_avatar' }}</span>
|
<span class="fileinput-new" translate>{{ 'app.shared.user.add_an_avatar' }}</span>
|
||||||
<span class="fileinput-exists" translate>{{ 'app.shared.buttons.change' }}</span>
|
<span class="fileinput-exists" translate>{{ 'app.shared.buttons.change' }}</span>
|
||||||
<input type="file" name="user[profile_attributes][user_avatar_attributes][attachment]">
|
<input type="file" name="user[profile_attributes][user_avatar_attributes][attachment]" accept="image/jpeg,image/gif,image/png">
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<button class="btn btn-danger fileinput-exists"
|
<button class="btn btn-danger fileinput-exists"
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
ng-minlength="8"/>
|
ng-minlength="8"/>
|
||||||
</div>
|
</div>
|
||||||
<a href="#" ng-click="openResetPassword($event)" class="text-xs">{{ 'app.public.common.password_forgotten' | translate }}</a>
|
<a href="#" ng-click="openResetPassword($event)" class="text-xs">{{ 'app.public.common.password_forgotten' | translate }}</a>
|
||||||
<span ng-if="userConfirmationNeededToSignIn">
|
<span ng-if="confirmationRequired">
|
||||||
<br><a href="#" ng-click="openConfirmationNewModal($event)" class="text-xs">{{ 'app.public.common.confirm_my_account' | translate }}</a>
|
<br><a href="#" ng-click="openConfirmationNewModal($event)" class="text-xs">{{ 'app.public.common.confirm_my_account' | translate }}</a>
|
||||||
</span>
|
</span>
|
||||||
<div class="alert alert-warning m-t-sm m-b-none text-xs p-sm" ng-show='isCapsLockOn' role="alert">
|
<div class="alert alert-warning m-t-sm m-b-none text-xs p-sm" ng-show='isCapsLockOn' role="alert">
|
||||||
|
@ -38,8 +38,8 @@
|
|||||||
<li><a ui-sref="app.logged.dashboard.projects" translate>{{ 'app.public.common.my_projects' }}</a></li>
|
<li><a ui-sref="app.logged.dashboard.projects" translate>{{ 'app.public.common.my_projects' }}</a></li>
|
||||||
<li><a ui-sref="app.logged.dashboard.trainings" translate>{{ 'app.public.common.my_trainings' }}</a></li>
|
<li><a ui-sref="app.logged.dashboard.trainings" translate>{{ 'app.public.common.my_trainings' }}</a></li>
|
||||||
<li><a ui-sref="app.logged.dashboard.events" translate>{{ 'app.public.common.my_events' }}</a></li>
|
<li><a ui-sref="app.logged.dashboard.events" translate>{{ 'app.public.common.my_events' }}</a></li>
|
||||||
<li><a ui-sref="app.logged.dashboard.invoices" ng-hide="fablabWithoutInvoices" translate>{{ 'app.public.common.my_invoices' }}</a></li>
|
<li><a ui-sref="app.logged.dashboard.invoices" ng-show="modules.invoicing" translate>{{ 'app.public.common.my_invoices' }}</a></li>
|
||||||
<li ng-hide="fablabWithoutWallet"><a ui-sref="app.logged.dashboard.wallet" translate>{{ 'app.public.common.my_wallet' }}</a></li>
|
<li ng-show="modules.wallet"><a ui-sref="app.logged.dashboard.wallet" translate>{{ 'app.public.common.my_wallet' }}</a></li>
|
||||||
<li class="divider" ng-if="isAuthorized(['admin', 'manager'])"></li>
|
<li class="divider" ng-if="isAuthorized(['admin', 'manager'])"></li>
|
||||||
<li><a class="text-black pointer" ng-click="help($event)" ng-if="isAuthorized(['admin', 'manager'])"><i class="fa fa-question-circle"></i> <span translate>{{ 'app.public.common.help' }}</span> </a></li>
|
<li><a class="text-black pointer" ng-click="help($event)" ng-if="isAuthorized(['admin', 'manager'])"><i class="fa fa-question-circle"></i> <span translate>{{ 'app.public.common.help' }}</span> </a></li>
|
||||||
<li class="divider"></li>
|
<li class="divider"></li>
|
||||||
|
@ -56,7 +56,7 @@
|
|||||||
<i class="fa fa-calendar-o"></i> <span translate>{{ 'app.public.common.my_events' }}</span>
|
<i class="fa fa-calendar-o"></i> <span translate>{{ 'app.public.common.my_events' }}</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="hidden-sm hidden-md hidden-lg" ng-hide="fablabWithoutInvoices" ng-if-end>
|
<li class="hidden-sm hidden-md hidden-lg" ng-show="modules.invoicing" ng-if-end>
|
||||||
<a ui-sref="app.logged.dashboard.invoices">
|
<a ui-sref="app.logged.dashboard.invoices">
|
||||||
<i class="fa fa-file-pdf-o"></i> <span translate>{{ 'app.public.common.my_invoices' }}</span>
|
<i class="fa fa-file-pdf-o"></i> <span translate>{{ 'app.public.common.my_invoices' }}</span>
|
||||||
</a>
|
</a>
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
id="space_image"
|
id="space_image"
|
||||||
ng-model="space.space_image"
|
ng-model="space.space_image"
|
||||||
name="space[space_image_attributes][attachment]"
|
name="space[space_image_attributes][attachment]"
|
||||||
accept="image/*"
|
accept="image/jpeg,image/gif,image/png"
|
||||||
required
|
required
|
||||||
bs-jasny-fileinput>
|
bs-jasny-fileinput>
|
||||||
</span>
|
</span>
|
||||||
@ -98,8 +98,11 @@
|
|||||||
<div class="form-control" data-trigger="fileinput">
|
<div class="form-control" data-trigger="fileinput">
|
||||||
<i class="glyphicon glyphicon-file fileinput-exists"></i> <span class="fileinput-filename">{{file.attachment}}</span>
|
<i class="glyphicon glyphicon-file fileinput-exists"></i> <span class="fileinput-filename">{{file.attachment}}</span>
|
||||||
</div>
|
</div>
|
||||||
<span class="input-group-addon btn btn-default btn-file"><span class="fileinput-new" translate>{{ 'app.shared.space.attach_a_file' }}</span>
|
<span class="input-group-addon btn btn-default btn-file">
|
||||||
<span class="fileinput-exists" translate>{{ 'app.shared.buttons.change' }}</span><input type="file" name="space[space_files_attributes][][attachment]" accept=".pdf"></span>
|
<span class="fileinput-new" translate>{{ 'app.shared.space.attach_a_file' }}</span>
|
||||||
|
<span class="fileinput-exists" translate>{{ 'app.shared.buttons.change' }}</span>
|
||||||
|
<input type="file" name="space[space_files_attributes][][attachment]" accept="application/pdf">
|
||||||
|
</span>
|
||||||
<a class="input-group-addon btn btn-danger fileinput-exists" data-dismiss="fileinput" ng-click="deleteFile(file)"><i class="fa fa-trash-o"></i></a>
|
<a class="input-group-addon btn btn-danger fileinput-exists" data-dismiss="fileinput" ng-click="deleteFile(file)"><i class="fa fa-trash-o"></i></a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
<div class="row no-gutter training-reserve">
|
<div class="row no-gutter training-reserve">
|
||||||
<div class="col-sm-12 col-md-12 col-lg-9">
|
<div class="col-sm-12 col-md-12 col-lg-9">
|
||||||
<div ui-calendar="calendarConfig" ng-model="eventSources" calendar="calendar" class="wrapper-lg" ng-show="!plansAreShown"></div>
|
<div ui-calendar="calendarConfig" ng-model="eventSources" calendar="calendar" class="wrapper-lg" ng-show="!plansAreShown"></div>
|
||||||
<ng-include ng-if="!fablabWithoutPlans" src="'<%= asset_path "plans/_plan.html" %>'"></ng-include>
|
<ng-include ng-if="modules.plans" src="'<%= asset_path "plans/_plan.html" %>'"></ng-include>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<uib-alert ng-repeat="alert in alerts" type="{{alert.type}}" close="closeAlert($index)">{{alert.msg}}</uib-alert>
|
<uib-alert ng-repeat="alert in alerts" type="{{alert.type}}" close="closeAlert($index)">{{alert.msg}}</uib-alert>
|
||||||
|
|
||||||
<div class="panel panel-default bg-light m-n">
|
<div class="panel panel-default bg-light m-n">
|
||||||
<form name="stripeForm" stripe:form cart-items="cartItems" on-payment-success="onPaymentSuccess" class="form-horizontal">
|
<form name="stripeForm" stripe:form cart-items="cartItems" on-payment-success="onPaymentSuccess" stripe-key="{{stripeKey}}" class="form-horizontal">
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
|
|
||||||
<h3 class="m-t-xs" ng-if="walletAmount" ng-bind-html="'app.shared.wallet.you_have_amount_in_wallet' | translate:{ amount: numberFilter(walletAmount, 2), currency: currencySymbol }"></h3>
|
<h3 class="m-t-xs" ng-if="walletAmount" ng-bind-html="'app.shared.wallet.you_have_amount_in_wallet' | translate:{ amount: numberFilter(walletAmount, 2), currency: currencySymbol }"></h3>
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
<div class="row no-gutter training-reserve">
|
<div class="row no-gutter training-reserve">
|
||||||
<div class="col-sm-12 col-md-12 col-lg-9">
|
<div class="col-sm-12 col-md-12 col-lg-9">
|
||||||
<div ui-calendar="calendarConfig" ng-model="eventSources" calendar="calendar" class="wrapper-lg" ng-show="!plansAreShown"></div>
|
<div ui-calendar="calendarConfig" ng-model="eventSources" calendar="calendar" class="wrapper-lg" ng-show="!plansAreShown"></div>
|
||||||
<ng-include ng-if="!fablabWithoutPlans" src="'<%= asset_path "plans/_plan.html" %>'"></ng-include>
|
<ng-include ng-if="modules.plans" src="'<%= asset_path "plans/_plan.html" %>'"></ng-include>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr/>
|
<hr/>
|
||||||
<div class="text-right m-t" ng-hide="fablabWithoutInvoices">
|
<div class="text-right m-t" ng-show="modules.invoicing">
|
||||||
<label for="generate_avoir" translate>{{ 'app.shared.wallet.generate_a_refund_invoice' }}</label>
|
<label for="generate_avoir" translate>{{ 'app.shared.wallet.generate_a_refund_invoice' }}</label>
|
||||||
<div class="inline m-l">
|
<div class="inline m-l">
|
||||||
<input bs-switch
|
<input bs-switch
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
# API Controller for resources of type Availability
|
# API Controller for resources of type Availability
|
||||||
class API::AvailabilitiesController < API::ApiController
|
class API::AvailabilitiesController < API::ApiController
|
||||||
include FablabConfiguration
|
|
||||||
|
|
||||||
before_action :authenticate_user!, except: [:public]
|
before_action :authenticate_user!, except: [:public]
|
||||||
before_action :set_availability, only: %i[show update reservations lock]
|
before_action :set_availability, only: %i[show update reservations lock]
|
||||||
before_action :define_max_visibility, only: %i[machine trainings spaces]
|
before_action :define_max_visibility, only: %i[machine trainings spaces]
|
||||||
@ -16,9 +14,9 @@ class API::AvailabilitiesController < API::ApiController
|
|||||||
@availabilities = Availability.includes(:machines, :tags, :trainings, :spaces)
|
@availabilities = Availability.includes(:machines, :tags, :trainings, :spaces)
|
||||||
.where('start_at >= ? AND end_at <= ?', start_date, end_date)
|
.where('start_at >= ? AND end_at <= ?', start_date, end_date)
|
||||||
|
|
||||||
@availabilities = @availabilities.where.not(available_type: 'event') unless Rails.application.secrets.events_in_calendar
|
@availabilities = @availabilities.where.not(available_type: 'event') unless Setting.get('events_in_calendar')
|
||||||
|
|
||||||
@availabilities = @availabilities.where.not(available_type: 'space') if fablab_spaces_deactivated?
|
@availabilities = @availabilities.where.not(available_type: 'space') unless Setting.get('spaces_module')
|
||||||
end
|
end
|
||||||
|
|
||||||
def public
|
def public
|
||||||
@ -193,7 +191,7 @@ class API::AvailabilitiesController < API::ApiController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def define_max_visibility
|
def define_max_visibility
|
||||||
@visi_max_year = Setting.find_by(name: 'visibility_yearly').value.to_i.months.since
|
@visi_max_year = Setting.get('visibility_yearly').to_i.months.since
|
||||||
@visi_max_other = Setting.find_by(name: 'visibility_others').value.to_i.months.since
|
@visi_max_other = Setting.get('visibility_others').to_i.months.since
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
20
app/controllers/api/files_controller.rb
Normal file
20
app/controllers/api/files_controller.rb
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# API Controller for handling special actions on files
|
||||||
|
class API::FilesController < API::ApiController
|
||||||
|
before_action :authenticate_user!
|
||||||
|
|
||||||
|
# test the mime type of the uploaded file
|
||||||
|
def mime
|
||||||
|
authorize :file
|
||||||
|
|
||||||
|
content_type = Marcel::MimeType.for Pathname.new(file_params.path)
|
||||||
|
render json: { type: content_type }
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def file_params
|
||||||
|
params.require(:attachment)
|
||||||
|
end
|
||||||
|
end
|
@ -7,7 +7,7 @@ class API::MachinesController < API::ApiController
|
|||||||
respond_to :json
|
respond_to :json
|
||||||
|
|
||||||
def index
|
def index
|
||||||
sort_by = Setting.find_by(name: 'machines_sort_by').value || 'default'
|
sort_by = Setting.get('machines_sort_by') || 'default'
|
||||||
@machines = if sort_by == 'default'
|
@machines = if sort_by == 'default'
|
||||||
Machine.includes(:machine_image, :plans)
|
Machine.includes(:machine_image, :plans)
|
||||||
else
|
else
|
||||||
|
@ -56,7 +56,7 @@ class API::MembersController < API::ApiController
|
|||||||
|
|
||||||
if members_service.update(user_params)
|
if members_service.update(user_params)
|
||||||
# Update password without logging out
|
# Update password without logging out
|
||||||
sign_in(@member, bypass: true) unless current_user.id != params[:id].to_i
|
bypass_sign_in(@member) unless current_user.id != params[:id].to_i
|
||||||
render :show, status: :ok, location: member_path(@member)
|
render :show, status: :ok, location: member_path(@member)
|
||||||
else
|
else
|
||||||
render json: @member.errors, status: :unprocessable_entity
|
render json: @member.errors, status: :unprocessable_entity
|
||||||
@ -192,7 +192,7 @@ class API::MembersController < API::ApiController
|
|||||||
def complete_tour
|
def complete_tour
|
||||||
authorize @member
|
authorize @member
|
||||||
|
|
||||||
if Rails.application.secrets.feature_tour_display == 'session'
|
if Setting.get('feature_tour_display') == 'session'
|
||||||
render json: { tours: [params[:tour]] }
|
render json: { tours: [params[:tour]] }
|
||||||
else
|
else
|
||||||
tours = "#{@member.profile.tours} #{params[:tour]}"
|
tours = "#{@member.profile.tours} #{params[:tour]}"
|
||||||
|
@ -3,11 +3,18 @@
|
|||||||
# API Controller for resources of type Openlab::Projects
|
# API Controller for resources of type Openlab::Projects
|
||||||
# Openlab::Projects are Projects shared between different instances
|
# Openlab::Projects are Projects shared between different instances
|
||||||
class API::OpenlabProjectsController < API::ApiController
|
class API::OpenlabProjectsController < API::ApiController
|
||||||
PROJECTS = Openlab::Projects.new
|
before_action :init_openlab
|
||||||
|
|
||||||
def index
|
def index
|
||||||
render json: PROJECTS.search(params[:q], page: params[:page], per_page: params[:per_page]).response.body
|
render json: @projets.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
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def init_openlab
|
||||||
|
client = Openlab::Client.new(app_secret: Setting.get('openlab_app_secret'))
|
||||||
|
@projets = Openlab::Projects.new(client)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -10,7 +10,7 @@ class API::PaymentsController < API::ApiController
|
|||||||
# was successfully made. After the payment was made, the reservation/subscription will be created
|
# was successfully made. After the payment was made, the reservation/subscription will be created
|
||||||
##
|
##
|
||||||
def confirm_payment
|
def confirm_payment
|
||||||
render(json: { error: 'Online payment is disabled' }, status: :unauthorized) and return if Rails.application.secrets.fablab_without_online_payments
|
render(json: { error: 'Online payment is disabled' }, status: :unauthorized) and return unless Setting.get('online_payment_module')
|
||||||
|
|
||||||
amount = nil # will contains the amount and the details of each invoice lines
|
amount = nil # will contains the amount and the details of each invoice lines
|
||||||
intent = nil # stripe's payment intent
|
intent = nil # stripe's payment intent
|
||||||
@ -24,15 +24,17 @@ class API::PaymentsController < API::ApiController
|
|||||||
|
|
||||||
# Create the PaymentIntent
|
# Create the PaymentIntent
|
||||||
intent = Stripe::PaymentIntent.create(
|
intent = Stripe::PaymentIntent.create(
|
||||||
payment_method: params[:payment_method_id],
|
{
|
||||||
amount: amount[:amount],
|
payment_method: params[:payment_method_id],
|
||||||
currency: Rails.application.secrets.stripe_currency,
|
amount: amount[:amount],
|
||||||
confirmation_method: 'manual',
|
currency: Setting.get('stripe_currency'),
|
||||||
confirm: true,
|
confirmation_method: 'manual',
|
||||||
customer: current_user.stp_customer_id
|
confirm: true,
|
||||||
|
customer: current_user.stp_customer_id
|
||||||
|
}, { api_key: Setting.get('stripe_secret_key') }
|
||||||
)
|
)
|
||||||
elsif params[:payment_intent_id].present?
|
elsif params[:payment_intent_id].present?
|
||||||
intent = Stripe::PaymentIntent.confirm(params[:payment_intent_id])
|
intent = Stripe::PaymentIntent.confirm(params[:payment_intent_id], api_key: Setting.get('stripe_secret_key'))
|
||||||
end
|
end
|
||||||
rescue Stripe::CardError => e
|
rescue Stripe::CardError => e
|
||||||
# Display error on client
|
# Display error on client
|
||||||
@ -54,6 +56,16 @@ class API::PaymentsController < API::ApiController
|
|||||||
render generate_payment_response(intent, res)
|
render generate_payment_response(intent, res)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def online_payment_status
|
||||||
|
authorize :payment
|
||||||
|
|
||||||
|
key = Setting.get('stripe_secret_key')
|
||||||
|
render json: { status: false } and return unless key
|
||||||
|
|
||||||
|
charges = Stripe::Charge.list({ limit: 1 }, { api_key: key })
|
||||||
|
render json: { status: charges.data.length.positive? }
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def on_reservation_success(intent, details)
|
def on_reservation_success(intent, details)
|
||||||
@ -62,7 +74,8 @@ class API::PaymentsController < API::ApiController
|
|||||||
.pay_and_save(@reservation, payment_details: details, payment_intent_id: intent.id)
|
.pay_and_save(@reservation, payment_details: details, payment_intent_id: intent.id)
|
||||||
Stripe::PaymentIntent.update(
|
Stripe::PaymentIntent.update(
|
||||||
intent.id,
|
intent.id,
|
||||||
description: "Invoice reference: #{@reservation.invoice.reference}"
|
{ description: "Invoice reference: #{@reservation.invoice.reference}" },
|
||||||
|
{ api_key: Setting.get('stripe_secret_key') }
|
||||||
)
|
)
|
||||||
|
|
||||||
if is_reserve
|
if is_reserve
|
||||||
@ -81,7 +94,8 @@ class API::PaymentsController < API::ApiController
|
|||||||
|
|
||||||
Stripe::PaymentIntent.update(
|
Stripe::PaymentIntent.update(
|
||||||
intent.id,
|
intent.id,
|
||||||
description: "Invoice reference: #{@subscription.invoices.first.reference}"
|
{ description: "Invoice reference: #{@subscription.invoices.first.reference}" },
|
||||||
|
{ api_key: Setting.get('stripe_secret_key') }
|
||||||
)
|
)
|
||||||
|
|
||||||
if is_subscribe
|
if is_subscribe
|
||||||
|
@ -60,10 +60,6 @@ class API::ProjectsController < API::ApiController
|
|||||||
render :index
|
render :index
|
||||||
end
|
end
|
||||||
|
|
||||||
def allowed_extensions
|
|
||||||
render json: ENV['ALLOWED_EXTENSIONS'].split(' '), status: :ok
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_project
|
def set_project
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user