mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-01-17 06:52:27 +01:00
Merge branch 'dev' into dependabot/bundler/puma-3.12.3
This commit is contained in:
commit
cd61826b6a
10
.github/ISSUE_TEMPLATE.md
vendored
10
.github/ISSUE_TEMPLATE.md
vendored
@ -1,8 +1,14 @@
|
||||
This issue tracker is **reserved** for bug reports and feature requests.
|
||||
This issue tracker is **reserved** for bug reports.
|
||||
|
||||
The place to ask a question or call for help is at Fab-manager forums at https://forum.fab-manager.com/.
|
||||
The place to ask a question or call for help is at [Fab-manager forums](https://forum.fab-manager.com)
|
||||
|
||||
The place to request or vote for new feature is on the [feedback website](https://feedback.fab-manager.com)
|
||||
|
||||
To report a bug, please describe:
|
||||
- Expected behavior and actual behavior.
|
||||
- Steps to reproduce the problem.
|
||||
- Specifications like the version of the project, operating system, or hardware.
|
||||
|
||||
The following elements may help to quickly resolve your issue:
|
||||
- Server logs `tail -f /apps/fabmanager/log/app-stdout.log` on the server
|
||||
- Client logs `Ctrl`+`Maj`+`i` > `Console` in the browser
|
||||
|
34
CHANGELOG.md
34
CHANGELOG.md
@ -1,5 +1,39 @@
|
||||
# Changelog Fab Manager
|
||||
|
||||
- Ability to create and delete periodic calendar availabilities (recurrence)
|
||||
- An administrator can delete a member
|
||||
- An event can be cancelled, if reservation cancellation is enabled
|
||||
- Ability to import iCalendar agendas in the public calendar, through URLs to ICS files (RFC 5545)
|
||||
- Ability to configure the duration of a reservation slot, using `SLOT_DURATION`. Previously, only 60 minutes slots were allowed
|
||||
- Display the scheduled events in the admin calendar, depending on `EVENTS_IN_CALENDAR` configuration.
|
||||
- Display indications on required fields in new administrator form
|
||||
- Configuration of phone number in members registration forms: can be required or optional, depending on `PHONE_REQUIRED` configuration
|
||||
- Improved user experience in defining slots in the calendar management
|
||||
- Improved notification email to the member when a rolling subscription is taken
|
||||
- Notify all admins on the creation of a refund invoice
|
||||
- Calendar management: improved legend display and visual behavior
|
||||
- Prevent event reservation in the past [Taiga#127]
|
||||
- Handle Ctrl^C in upgrade scripts
|
||||
- Updated moment-timezone
|
||||
- Added freeCAD files as default allowed extensions
|
||||
- Rake task to sync local users with Stripe
|
||||
- Unified translations syntax to use ICU MessageFormat
|
||||
- Refactored front-end translations keys with unified paths
|
||||
- Updated and refactored README and documentations
|
||||
- Updated setup script and instructions
|
||||
- Fix a bug: unable to remove the picture from a training
|
||||
- Fix a bug: no alerts on errors during admin creation
|
||||
- Fix a bug: replaces all Time.now by DateTime.current to prevent time zones issues [Taiga#134]
|
||||
- Fix a bug: logs are not printed in staging environment
|
||||
- Fix a security issue: updated loofah to fix [CVE-2019-15587](https://github.com/advisories/GHSA-c3gv-9cxf-6f57)
|
||||
- Fix a security issue: updated angular to 1.7.9 to fix [CVE-2019-10768](https://github.com/advisories/GHSA-89mq-4x47-5v83)
|
||||
- Fix a security issue: updated puma to 3.12.2 to fix [GHSA-7xx3-m584-x994](https://github.com/advisories/GHSA-7xx3-m584-x994)
|
||||
- [TODO DEPLOY] add the `SLOT_DURATION` environment variable (see [doc/environment.md](doc/environment.md#SLOT_DURATION) for configuration details)
|
||||
- [TODO DEPLOY] add the `PHONE_REQUIRED` environment variable (see [doc/environment.md](doc/environment.md#PHONE_REQUIRED) for configuration details)
|
||||
- [TODO DEPLOY] add the `EVENTS_IN_CALENDAR` environment variable (see [doc/environment.md](doc/environment.md#EVENTS_IN_CALENDAR) for configuration details)
|
||||
- [TODO DEPLOY] -> (only dev) `bundle install && yarn install`
|
||||
- [TODO DEPLOY] `rake db:migrate`
|
||||
|
||||
## v4.2.4 2019 October 30
|
||||
|
||||
- Fix a bug: in some cases, the invoices were not generated after deploying v4.2.0+. This can occurs if VAT was changed/enabled during the application life (#156)
|
||||
|
4
Gemfile
4
Gemfile
@ -61,7 +61,7 @@ group :test do
|
||||
gem 'webmock'
|
||||
end
|
||||
|
||||
group :production do
|
||||
group :production, :staging do
|
||||
gem 'rails_12factor'
|
||||
end
|
||||
|
||||
@ -152,3 +152,5 @@ gem 'sys-filesystem'
|
||||
gem 'sha3'
|
||||
|
||||
gem 'repost'
|
||||
|
||||
gem 'icalendar'
|
||||
|
10
Gemfile.lock
10
Gemfile.lock
@ -191,6 +191,9 @@ GEM
|
||||
multi_xml (>= 0.5.2)
|
||||
i18n (0.9.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
icalendar (2.5.3)
|
||||
ice_cube (~> 0.16)
|
||||
ice_cube (0.16.3)
|
||||
ice_nine (0.11.2)
|
||||
jaro_winkler (1.5.1)
|
||||
jbuilder (2.5.0)
|
||||
@ -208,7 +211,7 @@ GEM
|
||||
actionpack (>= 3.0.0)
|
||||
activesupport (>= 3.0.0)
|
||||
libv8 (3.16.14.19)
|
||||
loofah (2.3.0)
|
||||
loofah (2.3.1)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.5.9)
|
||||
mail (2.7.1)
|
||||
@ -240,7 +243,7 @@ GEM
|
||||
multi_xml (0.6.0)
|
||||
multipart-post (2.1.1)
|
||||
naught (1.1.0)
|
||||
nokogiri (1.10.4)
|
||||
nokogiri (1.10.8)
|
||||
mini_portile2 (~> 2.4.0)
|
||||
notify_with (0.0.2)
|
||||
jbuilder (~> 2.0)
|
||||
@ -288,7 +291,7 @@ GEM
|
||||
pundit (1.0.0)
|
||||
activesupport (>= 3.0.0)
|
||||
raabro (1.1.6)
|
||||
rack (1.6.11)
|
||||
rack (1.6.12)
|
||||
rack-protection (1.5.5)
|
||||
rack
|
||||
rack-test (0.6.3)
|
||||
@ -497,6 +500,7 @@ DEPENDENCIES
|
||||
forgery
|
||||
friendly_id (~> 5.1.0)
|
||||
has_secure_token
|
||||
icalendar
|
||||
jbuilder (~> 2.5)
|
||||
jbuilder_cache_multi
|
||||
jquery-rails
|
||||
|
355
README.md
355
README.md
@ -5,31 +5,19 @@ FabManager is the Fab Lab management solution. It provides a comprehensive, web-
|
||||
[![Coverage Status](https://coveralls.io/repos/github/sleede/fab-manager/badge.svg)](https://coveralls.io/github/sleede/fab-manager)
|
||||
[![Docker pulls](https://img.shields.io/docker/pulls/sleede/fab-manager.svg)](https://hub.docker.com/r/sleede/fab-manager/)
|
||||
[![Docker Build Status](https://img.shields.io/docker/build/sleede/fab-manager.svg)](https://hub.docker.com/r/sleede/fab-manager/builds)
|
||||
[![Crowdin](https://badges.crowdin.net/fab-manager/localized.svg)](https://crowdin.com/project/fab-manager)
|
||||
|
||||
##### Table of Contents
|
||||
1. [Software stack](#software-stack)
|
||||
2. [Contributing](#contributing)
|
||||
3. [Setup a production environment](#setup-a-production-environment)
|
||||
4. [Setup a development environment](#setup-a-development-environment)<br/>
|
||||
4.1. [General Guidelines](#general-guidelines)<br/>
|
||||
5. [PostgreSQL](#postgresql)<br/>
|
||||
5.1. [Install PostgreSQL 9.6](#setup-postgresql)
|
||||
6. [ElasticSearch](#elasticsearch)<br/>
|
||||
6.1. [Install ElasticSearch](#setup-elasticsearch)<br/>
|
||||
6.2. [Rebuild statistics](#rebuild-stats)<br/>
|
||||
6.3. [Backup and Restore](#backup-and-restore-elasticsearch)
|
||||
7. [Internationalization (i18n)](#i18n)<br/>
|
||||
7.1. [Translation](#i18n-translation)<br/>
|
||||
7.1.1. [Front-end translations](#i18n-translation-front)<br/>
|
||||
7.1.2. [Back-end translations](#i18n-translation-back)<br/>
|
||||
7.2. [Configuration](#i18n-configuration)<br/>
|
||||
7.2.1. [Settings](#i18n-settings)<br/>
|
||||
7.2.2. [Applying changes](#i18n-apply)
|
||||
8. [Open Projects](#open-projects)
|
||||
9. [Plugins](#plugins)
|
||||
10. [Single Sign-On](#sso)
|
||||
11. [Known issues](#known-issues)
|
||||
12. [Related Documentation](#related-documentation)
|
||||
4. [Setup a development environment](#setup-a-development-environment)
|
||||
5. [Internationalization (i18n)](#i18n)
|
||||
6. [Open Projects](#open-projects)
|
||||
7. [Plugins](#plugins)
|
||||
8. [Single Sign-On](#sso)
|
||||
9. [Known issues](#known-issues)
|
||||
10. [Related Documentation](#related-documentation)
|
||||
|
||||
|
||||
|
||||
@ -54,293 +42,22 @@ Contributions are welcome. Please read [the contribution guidelines](CONTRIBUTIN
|
||||
## Setup a production environment
|
||||
|
||||
To run fab-manager as a production application, this is highly recommended to use [Docker-compose](https://docs.docker.com/compose/overview/).
|
||||
The procedure to follow is described in the [docker-compose readme](docker/README.md).
|
||||
The procedure to follow is described in the [docker-compose readme](doc/docker-compose_readme.md).
|
||||
|
||||
<a name="setup-a-development-environment"></a>
|
||||
## Setup a development environment
|
||||
|
||||
In you intend to run fab-manager on your local machine to contribute to the project development, you can set it up with the following procedure.
|
||||
In you intend to run fab-manager on your local machine to contribute to the project development, you can set it up by following the [development readme](doc/development_readme.md).
|
||||
This procedure relies on docker to set-up the dependencies.
|
||||
|
||||
This procedure is not easy to follow so if you don't need to write some code for Fab-manager, please prefer the [docker-compose installation method](docker/README.md).
|
||||
|
||||
Optionally, you can use a virtual development environment that relies on Vagrant and Virtual Box by following the [virtual machine instructions](doc/virtual-machine.md).
|
||||
|
||||
<a name="general-guidelines"></a>
|
||||
### General Guidelines
|
||||
|
||||
1. Install RVM, with the ruby version specified in the [.ruby-version file](.ruby-version).
|
||||
For more details about the process, please read the [official RVM documentation](http://rvm.io/rvm/install).
|
||||
If you're using ArchLinux, you may have to [read this](doc/archlinux_readme.md) before.
|
||||
|
||||
2. Install NVM, with the node.js version specified in the [.nvmrc file](.nvmrc).
|
||||
For instructions about installing NVM, please refer to [the NVM readme](https://github.com/creationix/nvm#installation).
|
||||
|
||||
3. Install Yarn, the front-end package manager.
|
||||
Depending on your system, the installation process may differ, please read the [official Yarn documentation](https://yarnpkg.com/en/docs/install#debian-stable).
|
||||
|
||||
4. Install docker.
|
||||
Your system may provide a pre-packaged version of docker in its repositories, but this version may be outdated.
|
||||
Please refer to [ubuntu](https://docs.docker.com/install/linux/docker-ce/ubuntu/), [debian](https://docs.docker.com/install/linux/docker-ce/debian/) or [MacOS](https://docs.docker.com/docker-for-mac/install/) documentation to setup a recent version of docker.
|
||||
|
||||
5. Add your current user to the docker group, to allow using docker without `sudo`.
|
||||
```bash
|
||||
# add the docker group if it doesn't already exist
|
||||
sudo groupadd docker
|
||||
# add the current user to the docker group
|
||||
sudo usermod -aG docker $(whoami)
|
||||
# restart to validate changes
|
||||
sudo reboot
|
||||
```
|
||||
|
||||
6. Create a docker network for fab-manager.
|
||||
You may have to change the network address if it is already in use.
|
||||
```bash
|
||||
docker network create --subnet=172.18.0.0/16 fabmanager
|
||||
```
|
||||
|
||||
7. Retrieve the project from Git
|
||||
|
||||
```bash
|
||||
git clone https://github.com/sleede/fab-manager.git
|
||||
```
|
||||
|
||||
8. Install the software dependencies.
|
||||
First install [PostgreSQL](#postgresql) and [ElasticSearch](#elasticsearch) as specified in their respective documentations.
|
||||
Then install the other dependencies:
|
||||
- For Ubuntu/Debian:
|
||||
|
||||
```bash
|
||||
# on Ubuntu 18.04 server, you may have to enable the "universe" repository
|
||||
sudo add-apt-repository universe
|
||||
# then, install the dependencies
|
||||
sudo apt-get install libpq-dev redis-server imagemagick
|
||||
```
|
||||
- For MacOS X:
|
||||
|
||||
```bash
|
||||
brew install redis imagemagick
|
||||
```
|
||||
|
||||
9. Init the RVM and NVM instances and check they were correctly configured
|
||||
|
||||
```bash
|
||||
cd fab-manager
|
||||
rvm current | grep -q `cat .ruby-version`@fab-manager && echo "ok"
|
||||
# Must print ok
|
||||
nvm use
|
||||
node --version | grep -q `cat .nvmrc` && echo "ok"
|
||||
# Must print ok
|
||||
```
|
||||
|
||||
10. Install bundler in the current RVM gemset
|
||||
|
||||
```bash
|
||||
gem install bundler --version=1.17.3
|
||||
```
|
||||
|
||||
11. Install the required ruby gems and javascript plugins
|
||||
|
||||
```bash
|
||||
bundle install
|
||||
yarn install
|
||||
```
|
||||
|
||||
12. Create the default configuration files **and configure them!** (see the [environment configuration documentation](doc/environment.md))
|
||||
|
||||
```bash
|
||||
cp config/database.yml.default config/database.yml
|
||||
cp config/application.yml.default config/application.yml
|
||||
vi config/application.yml
|
||||
# or use your favorite text editor instead of vi (nano, ne...)
|
||||
```
|
||||
|
||||
13. Build the databases.
|
||||
- **Warning**: **DO NOT** run `rake db:setup` instead of these commands, as this will not run some required raw SQL instructions.
|
||||
- **Please note**: Your password length must be between 8 and 128 characters, otherwise db:seed will be rejected. This is configured in [config/initializers/devise.rb](config/initializers/devise.rb)
|
||||
|
||||
```bash
|
||||
# for dev
|
||||
rake db:create
|
||||
rake db:migrate
|
||||
ADMIN_EMAIL='youradminemail' ADMIN_PASSWORD='youradminpassword' rake db:seed
|
||||
rake fablab:es:build_stats
|
||||
# for tests
|
||||
RAILS_ENV=test rake db:create
|
||||
RAILS_ENV=test rake db:migrate
|
||||
```
|
||||
|
||||
14. Create the pids folder used by Sidekiq. If you want to use a different location, you can configure it in `config/sidekiq.yml`
|
||||
|
||||
```bash
|
||||
mkdir -p tmp/pids
|
||||
```
|
||||
|
||||
15. Start the development web server
|
||||
|
||||
```bash
|
||||
foreman s -p 3000
|
||||
```
|
||||
|
||||
16. You should now be able to access your local development FabManager instance by accessing `http://localhost:3000` in your web browser.
|
||||
|
||||
17. You can login as the default administrator using the credentials defined previously.
|
||||
|
||||
18. Email notifications will be caught by MailCatcher.
|
||||
To see the emails sent by the platform, open your web browser at `http://localhost:1080` to access the MailCatcher interface.
|
||||
|
||||
|
||||
<a name="postgresql"></a>
|
||||
## PostgreSQL
|
||||
|
||||
<a name="setup-postgresql"></a>
|
||||
### Install PostgreSQL 9.6
|
||||
|
||||
We will use docker to easily install the required version of PostgreSQL.
|
||||
|
||||
1. Create the docker binding folder
|
||||
```bash
|
||||
mkdir -p .docker/postgresql
|
||||
```
|
||||
|
||||
2. Start the PostgreSQL container.
|
||||
```bash
|
||||
docker run --restart=always -d --name fabmanager-postgres \
|
||||
-v $(pwd)/.docker/postgresql:/var/lib/postgresql/data \
|
||||
--network fabmanager --ip 172.18.0.2 \
|
||||
-p 5432:5432 \
|
||||
postgres:9.6
|
||||
```
|
||||
|
||||
3. Configure fab-manager to use it.
|
||||
On linux systems, PostgreSQL will be available at 172.18.0.2.
|
||||
On MacOS, you'll have to set the host to 127.0.0.1 (or localhost).
|
||||
See [environment.md](doc/environment.md) for more details.
|
||||
|
||||
4 . Finally, you may want to have a look at detailed informations about PostgreSQL usage in fab-manager.
|
||||
Some information about that is available in the [PostgreSQL Readme](doc/postgresql_readme.md).
|
||||
|
||||
<a name="elasticsearch"></a>
|
||||
## ElasticSearch
|
||||
|
||||
ElasticSearch is a powerful search engine based on Apache Lucene combined with a NoSQL database used as a cache to index data and quickly process complex requests on it.
|
||||
|
||||
In FabManager, it is used for the admin's statistics module and to perform searches in projects.
|
||||
|
||||
<a name="setup-elasticsearch"></a>
|
||||
### Install ElasticSearch
|
||||
|
||||
1. Create the docker binding folders
|
||||
```bash
|
||||
mkdir -p .docker/elasticsearch/config
|
||||
mkdir -p .docker/elasticsearch/plugins
|
||||
mkdir -p .docker/elasticsearch/backups
|
||||
```
|
||||
|
||||
2. Copy the default configuration files
|
||||
```bash
|
||||
cp docker/elasticsearch.yml .docker/elasticsearch/config
|
||||
cp docker/log4j2.properties .docker/elasticsearch/config
|
||||
```
|
||||
|
||||
3. Start the ElasticSearch container.
|
||||
```bash
|
||||
docker run --restart=always -d --name fabmanager-elastic \
|
||||
-v $(pwd)/.docker/elasticsearch/config:/usr/share/elasticsearch/config \
|
||||
-v $(pwd)/.docker/elasticsearch:/usr/share/elasticsearch/data \
|
||||
-v $(pwd)/.docker/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
|
||||
-v $(pwd)/.docker/elasticsearch/backups:/usr/share/elasticsearch/backups \
|
||||
--network fabmanager --ip 172.18.0.3 \
|
||||
-p 9200:9200 -p 9300:9300 \
|
||||
elasticsearch:5.6
|
||||
```
|
||||
|
||||
4. Configure fab-manager to use it.
|
||||
On linux systems, ElasticSearch will be available at 172.18.0.3.
|
||||
On MacOS, you'll have to set the host to 127.0.0.1 (or localhost).
|
||||
See [environment.md](doc/environment.md) for more details.
|
||||
|
||||
<a name="rebuild-stats"></a>
|
||||
### Rebuild statistics
|
||||
|
||||
Every nights, the statistics for the day that just ended are built automatically at 01:00 (AM) and stored in ElastricSearch.
|
||||
See [schedule.yml](config/schedule.yml) to modify this behavior.
|
||||
If the scheduled task wasn't executed for any reason (eg. you are in a dev environment and your computer was turned off at 1 AM), you can force the statistics data generation in ElasticSearch, running the following command.
|
||||
|
||||
```bash
|
||||
# Here for the 50 last days
|
||||
rake fablab:es:generate_stats[50]
|
||||
```
|
||||
|
||||
<a name="backup-and-restore-elasticsearch"></a>
|
||||
### Backup and Restore
|
||||
|
||||
To backup and restore the ElasticSearch database, use the [elasticsearch-dump](https://github.com/taskrabbit/elasticsearch-dump) tool.
|
||||
|
||||
Dump the database with: `elasticdump --input=http://localhost:9200/stats --output=fablab_stats.json`.
|
||||
Restore it with: `elasticdump --input=fablab_stats.json --output=http://localhost:9200/stats`.
|
||||
Optionally, you can use a virtual development environment that relies on Vagrant and Virtual Box by following the [virtual machine instructions](virtual-machine.md).
|
||||
|
||||
<a name="i18n"></a>
|
||||
## Internationalization (i18n)
|
||||
|
||||
The FabManager application can only run in a single language but this language can easily be changed.
|
||||
|
||||
<a name="i18n-translation"></a>
|
||||
### Translation
|
||||
|
||||
Check the files located in `config/locales`:
|
||||
|
||||
- Front app translations (angular.js) are located in `config/locales/app.scope.XX.yml`.
|
||||
Where scope has one the following meaning :
|
||||
- admin: translations of the administrator views (manage and configure the FabLab).
|
||||
- logged: translations of the end-user's views accessible only to connected users.
|
||||
- public: translation of end-user's views publicly accessible to anyone.
|
||||
- shared: translations shared by many views (like forms or buttons).
|
||||
- Back app translations (Ruby on Rails) are located in `config/locales/XX.yml`.
|
||||
- Emails translations are located in `config/locales/mails.XX.yml`.
|
||||
- Messages related to the authentication system are located in `config/locales/devise.XX.yml`.
|
||||
|
||||
If you plan to translate the application to a new locale, please consider that the reference translation is French.
|
||||
Indeed, in some cases, the English texts/sentences can seems confuse or lack of context as they were originally translated from French.
|
||||
|
||||
To prevent syntax mistakes while translating locale files, we **STRONGLY advise** you to use a text editor which support syntax coloration for YML and Ruby.
|
||||
|
||||
<a name="i18n-translation-front"></a>
|
||||
#### Front-end translations
|
||||
|
||||
Front-end translations uses [angular-translate](http://angular-translate.github.io) with some interpolations interpreted by angular.js and other interpreted by [MessageFormat](https://github.com/SlexAxton/messageformat.js/).
|
||||
**These two kinds of interpolation use a near but different syntax witch SHOULD NOT be confused.**
|
||||
Please refer to the official [angular-translate documentation](http://angular-translate.github.io/docs/#/guide/14_pluralization) before translating.
|
||||
|
||||
<a name="i18n-translation-back"></a>
|
||||
#### Back-end translations
|
||||
|
||||
Back-end translations uses the [Ruby on Rails syntax](http://guides.rubyonrails.org/i18n.html) but some complex interpolations are interpreted by [MessageFormat](https://github.com/format-message/message-format-rb) and are marked as it in comments.
|
||||
**DO NOT confuse the syntaxes.**
|
||||
|
||||
In each cases, some inline comments are included in the localisation files.
|
||||
They can be recognized as they start with the sharp character (#).
|
||||
These comments are not required to be translated, they are intended to help the translator to have some context information about the sentence to translate.
|
||||
|
||||
You will also need to translate the invoice watermark, located in `app/pdfs/data/`.
|
||||
You'll find there the [GIMP source of the image](app/pdfs/data/watermark.xcf), which is using [Rubik Mono One](https://fonts.google.com/specimen/Rubik+Mono+One) as font.
|
||||
Use it to generate a similar localised PNG image which keep the default image size, as PDF are not responsive.
|
||||
|
||||
|
||||
<a name="i18n-configuration"></a>
|
||||
### Configuration
|
||||
|
||||
Locales configurations are made in `config/application.yml`.
|
||||
If you are in a development environment, your can keep the default values, otherwise, in production, values must be configured carefully.
|
||||
|
||||
<a name="i18n-settings"></a>
|
||||
#### Settings
|
||||
|
||||
Please refer to the [environment configuration documentation](doc/environment.md#internationalization-settings)
|
||||
|
||||
<a name="i18n-apply"></a>
|
||||
#### Applying changes
|
||||
|
||||
After modifying any values concerning the localisation, restart the application (ie. web server) to apply these changes in the i18n configuration.
|
||||
Please refer to the [translation readme](doc/translation_readme.md) for instructions about configuring the language or to contribute to the translation.
|
||||
|
||||
<a name="open-projects"></a>
|
||||
## Open Projects
|
||||
@ -390,51 +107,7 @@ Developers may find information on how to implement their own authentication pro
|
||||
<a name="known-issues"></a>
|
||||
## Known issues
|
||||
|
||||
- When browsing a machine page, you may encounter an "InterceptError" in the console and the loading bar will stop loading before reaching its ending.
|
||||
This may happen if the machine was created through a seed file without any image.
|
||||
To solve this, simply add an image to the machine's profile and refresh the web page.
|
||||
|
||||
- When starting the Ruby on Rails server (eg. `foreman s`) you may receive the following error:
|
||||
|
||||
worker.1 | invalid url: redis::6379
|
||||
web.1 | Exiting
|
||||
worker.1 | ...lib/redis/client.rb...:in `_parse_options'
|
||||
|
||||
This may happen when the `application.yml` file is missing.
|
||||
To solve this issue copy `config/application.yml.default` to `config/application.yml`.
|
||||
This is required before the first start.
|
||||
|
||||
- Due to a stripe limitation, you won't be able to create plans longer than one year.
|
||||
|
||||
- When running the tests suite with `rake test`, all tests may fail with errors similar to the following:
|
||||
|
||||
Error:
|
||||
...
|
||||
ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation: ERROR: insert or update on table "..." violates foreign key constraint "fk_rails_..."
|
||||
DETAIL: Key (group_id)=(1) is not present in table "...".
|
||||
: ...
|
||||
test_after_commit (1.0.0) lib/test_after_commit/database_statements.rb:11:in `block in transaction'
|
||||
test_after_commit (1.0.0) lib/test_after_commit/database_statements.rb:5:in `transaction'
|
||||
|
||||
This is due to an ActiveRecord behavior witch disable referential integrity in PostgreSQL to load the fixtures.
|
||||
PostgreSQL will prevent any users to disable referential integrity on the fly if they doesn't have the `SUPERUSER` role.
|
||||
To fix that, logon as the `postgres` user and run the PostgreSQL shell (see [the dedicated section](#run-postgresql-cli) for instructions).
|
||||
Then, run the following command (replace `sleede` with your test database user, as specified in your database.yml):
|
||||
|
||||
ALTER ROLE sleede WITH SUPERUSER;
|
||||
|
||||
DO NOT do this in a production environment, unless you know what you're doing: this could lead to a serious security issue.
|
||||
|
||||
- With Ubuntu 16.04, ElasticSearch may refuse to start even after having configured the service with systemd.
|
||||
To solve this issue, you may have to set `START_DAEMON` to `true` in `/etc/default/elasticsearch`.
|
||||
Then reload ElasticSearch with:
|
||||
|
||||
```bash
|
||||
sudo systemctl restart elasticsearch.service
|
||||
```
|
||||
- In some cases, the invoices won't be generated. This can be due to the image included in the invoice header not being supported.
|
||||
To fix this issue, change the image in the administrator interface (manage the invoices / invoices settings).
|
||||
See [this thread](https://forum.fab-manager.com/t/resolu-erreur-generation-facture/428) for more info.
|
||||
Before reporting an issue, please check if your issue is not listed in the [know issues](doc/known-issues.md) with its solution.
|
||||
|
||||
<a name="related-documentation"></a>
|
||||
## Related Documentation
|
||||
|
@ -59,8 +59,8 @@ angular.module('application', ['ngCookies', 'ngResource', 'ngSanitize', 'ui.rout
|
||||
$translateProvider.useLoaderCache(true);
|
||||
// Secure i18n module against XSS attacks by escaping the output
|
||||
$translateProvider.useSanitizeValueStrategy('escapeParameters');
|
||||
// Enable the MessageFormat interpolation (used for pluralization)
|
||||
$translateProvider.addInterpolation('$translateMessageFormatInterpolation');
|
||||
// Use the MessageFormat interpolation by default (used for pluralization)
|
||||
$translateProvider.useMessageFormatInterpolation();
|
||||
// Set the langage of the instance (from ruby configuration)
|
||||
$translateProvider.preferredLanguage(Fablab.locale);
|
||||
}]).run(['$rootScope', '$log', 'AuthService', 'Auth', 'amMoment', '$state', 'editableOptions', 'Analytics',
|
||||
@ -86,6 +86,12 @@ angular.module('application', ['ngCookies', 'ngResource', 'ngSanitize', 'ui.rout
|
||||
$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 function to allow the user to navigate to the previous screen (ie. $state).
|
||||
// If no previous $state were recorded, navigate to the home page
|
||||
|
@ -17,21 +17,21 @@ Application.Controllers.controller('AbusesController', ['$scope', '$state', 'Abu
|
||||
resolve: {
|
||||
object () {
|
||||
return {
|
||||
title: _t('manage_abuses.confirmation_required'),
|
||||
msg: _t('manage_abuses.report_will_be_destroyed')
|
||||
title: _t('app.admin.manage_abuses.confirmation_required'),
|
||||
msg: _t('app.admin.manage_abuses.report_will_be_destroyed')
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
function () { // cancel confirmed
|
||||
Abuse.remove({ id: abuseId }, function () { // successfully canceled
|
||||
growl.success(_t('manage_abuses.report_removed'));
|
||||
growl.success(_t('app.admin.manage_abuses.report_removed'));
|
||||
Abuse.query({}, function (abuses) {
|
||||
$scope.abuses = abuses.abuses.filter(a => a.signaled_type === 'Project');
|
||||
});
|
||||
}
|
||||
, function () { // error while canceling
|
||||
growl.error(_t('manage_abuses.failed_to_remove'));
|
||||
growl.error(_t('app.admin.manage_abuses.failed_to_remove'));
|
||||
});
|
||||
}
|
||||
);
|
||||
|
@ -54,14 +54,16 @@ const check_oauth2_id_is_mapped = function (mappings) {
|
||||
* - $scope.authMethods
|
||||
* - $scope.mappingFields
|
||||
* - $scope.cancel()
|
||||
* - $scope.methodName()
|
||||
* - $scope.defineDataMapping(mapping)
|
||||
*
|
||||
* Requires :
|
||||
* - mappingFieldsPromise: retrieved by AuthProvider.mapping_fields()
|
||||
* - $state (Ui-Router) [ 'app.admin.members' ]
|
||||
* - _t : translation method
|
||||
*/
|
||||
class AuthenticationController {
|
||||
constructor ($scope, $state, $uibModal, mappingFieldsPromise) {
|
||||
constructor ($scope, $state, $uibModal, _t, mappingFieldsPromise) {
|
||||
// list of supported authentication methods
|
||||
$scope.authMethods = METHODS;
|
||||
|
||||
@ -73,6 +75,13 @@ class AuthenticationController {
|
||||
*/
|
||||
$scope.cancel = function () { $state.go('app.admin.members'); };
|
||||
|
||||
/**
|
||||
* Return a localized string for the provided method
|
||||
*/
|
||||
$scope.methodName = function(method) {
|
||||
return _t('app.shared.authentication.' + METHODS[method]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a modal allowing to specify the data mapping for the given field
|
||||
*/
|
||||
@ -137,9 +146,9 @@ class AuthenticationController {
|
||||
$scope.ok = function () { $uibModalInstance.close($scope.transformation.rules); };
|
||||
|
||||
// do not save the modifications
|
||||
return $scope.cancel = function () { $uibModalInstance.dismiss(); };
|
||||
}
|
||||
] })
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss(); };
|
||||
}]
|
||||
})
|
||||
.result['finally'](null).then(function (transfo_rules) { mapping.transformation = transfo_rules; });
|
||||
};
|
||||
}
|
||||
@ -163,9 +172,9 @@ Application.Controllers.controller('AuthentificationController', ['$scope', '$st
|
||||
$scope.getType = function (type) {
|
||||
const text = METHODS[type];
|
||||
if (typeof text !== 'undefined') {
|
||||
return _t(text);
|
||||
return _t(`app.admin.members.authentication_form.${text}`);
|
||||
} else {
|
||||
return _t('unknown') + type;
|
||||
return _t('app.admin.members.authentication_form.unknown') + type;
|
||||
}
|
||||
};
|
||||
|
||||
@ -176,10 +185,10 @@ Application.Controllers.controller('AuthentificationController', ['$scope', '$st
|
||||
*/
|
||||
$scope.getState = function (status) {
|
||||
switch (status) {
|
||||
case 'active': return _t('active');
|
||||
case 'pending': return _t('pending');
|
||||
case 'previous': return _t('previous_provider');
|
||||
default: return _t('unknown') + status;
|
||||
case 'active': return _t('app.admin.members.authentication_form.active');
|
||||
case 'pending': return _t('app.admin.members.authentication_form.pending');
|
||||
case 'previous': return _t('app.admin.members.authentication_form.previous_provider');
|
||||
default: return _t('app.admin.members.authentication_form.unknown') + status;
|
||||
}
|
||||
};
|
||||
|
||||
@ -194,8 +203,8 @@ Application.Controllers.controller('AuthentificationController', ['$scope', '$st
|
||||
resolve: {
|
||||
object () {
|
||||
return {
|
||||
title: _t('confirmation_required'),
|
||||
msg: _t('do_you_really_want_to_delete_the_TYPE_authentication_provider_NAME', { TYPE: $scope.getType(provider.providable_type), NAME: provider.name })
|
||||
title: _t('app.admin.members.authentication_form.confirmation_required'),
|
||||
msg: _t('app.admin.members.authentication_form.do_you_really_want_to_delete_the_TYPE_authentication_provider_NAME', { TYPE: $scope.getType(provider.providable_type), NAME: provider.name })
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -206,9 +215,9 @@ Application.Controllers.controller('AuthentificationController', ['$scope', '$st
|
||||
{ id: provider.id },
|
||||
function () {
|
||||
providers.splice(findIdxById(providers, provider.id), 1);
|
||||
growl.success(_t('authentication_provider_successfully_deleted'));
|
||||
growl.success(_t('app.admin.members.authentication_form.authentication_provider_successfully_deleted'));
|
||||
},
|
||||
function () { growl.error(_t('an_error_occurred_unable_to_delete_the_specified_provider')); }
|
||||
function () { growl.error(_t('app.admin.members.authentication_form.an_error_occurred_unable_to_delete_the_specified_provider')); }
|
||||
);
|
||||
}
|
||||
);
|
||||
@ -254,19 +263,19 @@ Application.Controllers.controller('NewAuthenticationController', ['$scope', '$s
|
||||
// prevent from adding mode than 1
|
||||
for (provider of Array.from(authProvidersPromise)) {
|
||||
if (provider.providable_type === 'DatabaseProvider') {
|
||||
growl.error(_t('a_local_database_provider_already_exists_unable_to_create_another'));
|
||||
growl.error(_t('app.admin.authentication_new.a_local_database_provider_already_exists_unable_to_create_another'));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return AuthProvider.save({ auth_provider: $scope.provider }, function (provider) {
|
||||
growl.success(_t('local_provider_successfully_saved'));
|
||||
growl.success(_t('app.admin.authentication_new.local_provider_successfully_saved'));
|
||||
return $state.go('app.admin.members');
|
||||
});
|
||||
// === OAuth2Provider ===
|
||||
} else if ($scope.provider.providable_type === 'OAuth2Provider') {
|
||||
// check the ID mapping
|
||||
if (!check_oauth2_id_is_mapped($scope.provider.providable_attributes.o_auth2_mappings_attributes)) {
|
||||
growl.error(_t('it_is_required_to_set_the_matching_between_User.uid_and_the_API_to_add_this_provider'));
|
||||
growl.error(_t('app.admin.authentication_new.it_is_required_to_set_the_matching_between_User.uid_and_the_API_to_add_this_provider'));
|
||||
return false;
|
||||
}
|
||||
// discourage the use of unsecure SSO
|
||||
@ -277,24 +286,24 @@ Application.Controllers.controller('NewAuthenticationController', ['$scope', '$s
|
||||
resolve: {
|
||||
object () {
|
||||
return {
|
||||
title: _t('security_issue_detected'),
|
||||
msg: _t('beware_the_oauth2_authenticatoin_provider_you_are_about_to_add_isnt_using_HTTPS') +
|
||||
_t('this_is_a_serious_security_issue_on_internet_and_should_never_be_used_except_for_testing_purposes') +
|
||||
_t('do_you_really_want_to_continue')
|
||||
title: _t('app.admin.authentication_new.security_issue_detected'),
|
||||
msg: _t('app.admin.authentication_new.beware_the_oauth2_authenticatoin_provider_you_are_about_to_add_isnt_using_HTTPS') +
|
||||
_t('app.admin.authentication_new.this_is_a_serious_security_issue_on_internet_and_should_never_be_used_except_for_testing_purposes') +
|
||||
_t('app.admin.authentication_new.do_you_really_want_to_continue')
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
function () { // unsecured http confirmed
|
||||
AuthProvider.save({ auth_provider: $scope.provider }, function (provider) {
|
||||
growl.success(_t('unsecured_oauth2_provider_successfully_added'));
|
||||
growl.success(_t('app.admin.authentication_new.unsecured_oauth2_provider_successfully_added'));
|
||||
return $state.go('app.admin.members');
|
||||
});
|
||||
}
|
||||
);
|
||||
} else {
|
||||
AuthProvider.save({ auth_provider: $scope.provider }, function (provider) {
|
||||
growl.success(_t('oauth2_provider_successfully_added'));
|
||||
growl.success(_t('app.admin.authentication_new.oauth2_provider_successfully_added'));
|
||||
return $state.go('app.admin.members');
|
||||
});
|
||||
}
|
||||
@ -302,7 +311,7 @@ Application.Controllers.controller('NewAuthenticationController', ['$scope', '$s
|
||||
};
|
||||
|
||||
// Using the AuthenticationController
|
||||
return new AuthenticationController($scope, $state, $uibModal, mappingFieldsPromise);
|
||||
return new AuthenticationController($scope, $state, $uibModal, _t, mappingFieldsPromise);
|
||||
}
|
||||
]);
|
||||
|
||||
@ -322,21 +331,21 @@ Application.Controllers.controller('EditAuthenticationController', ['$scope', '$
|
||||
$scope.updateProvider = function () {
|
||||
// check the ID mapping
|
||||
if (!check_oauth2_id_is_mapped($scope.provider.providable_attributes.o_auth2_mappings_attributes)) {
|
||||
growl.error(_t('it_is_required_to_set_the_matching_between_User.uid_and_the_API_to_add_this_provider'));
|
||||
growl.error(_t('app.admin.authentication_edit.it_is_required_to_set_the_matching_between_User.uid_and_the_API_to_add_this_provider'));
|
||||
return false;
|
||||
}
|
||||
return AuthProvider.update(
|
||||
{ id: $scope.provider.id },
|
||||
{ auth_provider: $scope.provider },
|
||||
function (provider) {
|
||||
growl.success(_t('provider_successfully_updated'));
|
||||
growl.success(_t('app.admin.authentication_edit.provider_successfully_updated'));
|
||||
$state.go('app.admin.members');
|
||||
},
|
||||
function () { growl.error(_t('an_error_occurred_unable_to_update_the_provider')); }
|
||||
function () { growl.error(_t('app.admin.authentication_edit.an_error_occurred_unable_to_update_the_provider')); }
|
||||
);
|
||||
};
|
||||
|
||||
// Using the AuthenticationController
|
||||
return new AuthenticationController($scope, $state, $uibModal, mappingFieldsPromise);
|
||||
return new AuthenticationController($scope, $state, $uibModal, _t, mappingFieldsPromise);
|
||||
}
|
||||
]);
|
||||
|
@ -23,14 +23,13 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
/* PRIVATE STATIC CONSTANTS */
|
||||
|
||||
// The calendar is divided in slots of 30 minutes
|
||||
let loadingCb;
|
||||
const BASE_SLOT = '00:30:00';
|
||||
|
||||
// The bookings can be positioned every half hours
|
||||
const BOOKING_SNAP = '00:30:00';
|
||||
|
||||
// We do not allow the creation of slots that are not a multiple of 60 minutes
|
||||
const SLOT_MULTIPLE = 60;
|
||||
const SLOT_MULTIPLE = Fablab.slotDuration;
|
||||
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
@ -40,6 +39,9 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
// currently selected availability
|
||||
$scope.availability = null;
|
||||
|
||||
// corresponding fullCalendar item in the DOM
|
||||
$scope.availabilityDom = null;
|
||||
|
||||
// bind the availabilities slots with full-Calendar events
|
||||
$scope.eventSources = [];
|
||||
$scope.eventSources.push({
|
||||
@ -62,7 +64,10 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
return calendarEventClickCb(event, jsEvent, view);
|
||||
},
|
||||
eventRender (event, element, view) {
|
||||
return eventRenderCb(event, element);
|
||||
return eventRenderCb(event, element, view);
|
||||
},
|
||||
viewRender(view, element) {
|
||||
return viewRenderCb(view, element);
|
||||
},
|
||||
loading (isLoading, view) {
|
||||
return loadingCb(isLoading, view);
|
||||
@ -80,10 +85,9 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
resolve: {
|
||||
object () {
|
||||
return {
|
||||
title: _t('admin_calendar.confirmation_required'),
|
||||
msg: _t('admin_calendar.do_you_really_want_to_cancel_the_USER_s_reservation_the_DATE_at_TIME_concerning_RESERVATION'
|
||||
, { GENDER: getGender($scope.currentUser), USER: slot.user.name, DATE: moment(slot.start_at).format('L'), TIME: moment(slot.start_at).format('LT'), RESERVATION: slot.reservable.name }
|
||||
, 'messageformat')
|
||||
title: _t('app.admin.calendar.confirmation_required'),
|
||||
msg: _t('app.admin.calendar.do_you_really_want_to_cancel_the_USER_s_reservation_the_DATE_at_TIME_concerning_RESERVATION'
|
||||
, { GENDER: getGender($scope.currentUser), USER: slot.user.name, DATE: moment(slot.start_at).format('L'), TIME: moment(slot.start_at).format('LT'), RESERVATION: slot.reservable.name })
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -101,10 +105,10 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
}
|
||||
}
|
||||
// notify the admin
|
||||
return growl.success(_t('admin_calendar.reservation_was_successfully_cancelled'));
|
||||
return growl.success(_t('app.admin.calendar.reservation_was_successfully_cancelled'));
|
||||
},
|
||||
function (data, status) { // failed
|
||||
growl.error(_t('admin_calendar.reservation_cancellation_failed'));
|
||||
growl.error(_t('app.admin.calendar.reservation_cancellation_failed'));
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -118,17 +122,17 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
*/
|
||||
$scope.removeMachine = function (machine) {
|
||||
if ($scope.availability.machine_ids.length === 1) {
|
||||
return growl.error(_t('admin_calendar.unable_to_remove_the_last_machine_of_the_slot_delete_the_slot_rather'));
|
||||
return growl.error(_t('app.admin.calendar.unable_to_remove_the_last_machine_of_the_slot_delete_the_slot_rather'));
|
||||
} else {
|
||||
// open a confirmation dialog
|
||||
return dialogs.confirm({
|
||||
resolve: {
|
||||
object () {
|
||||
return {
|
||||
title: _t('admin_calendar.confirmation_required'),
|
||||
msg: _t('admin_calendar.do_you_really_want_to_remove_MACHINE_from_this_slot', { GENDER: getGender($scope.currentUser), MACHINE: machine.name }, 'messageformat') + ' ' +
|
||||
_t('admin_calendar.this_will_prevent_any_new_reservation_on_this_slot_but_wont_cancel_those_existing') + ' ' +
|
||||
_t('admin_calendar.beware_this_cannot_be_reverted')
|
||||
title: _t('app.admin.calendar.confirmation_required'),
|
||||
msg: _t('app.admin.calendar.do_you_really_want_to_remove_MACHINE_from_this_slot', { GENDER: getGender($scope.currentUser), MACHINE: machine.name }) + ' ' +
|
||||
_t('app.admin.calendar.this_will_prevent_any_new_reservation_on_this_slot_but_wont_cancel_those_existing') + '<br><strong>' +
|
||||
_t('app.admin.calendar.beware_this_cannot_be_reverted') + '</strong>'
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -150,10 +154,10 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
$scope.availability.title = data.title;
|
||||
uiCalendarConfig.calendars.calendar.fullCalendar('rerenderEvents');
|
||||
// notify the admin
|
||||
return growl.success(_t('admin_calendar.the_machine_was_successfully_removed_from_the_slot'));
|
||||
return growl.success(_t('app.admin.calendar.the_machine_was_successfully_removed_from_the_slot'));
|
||||
}
|
||||
, function (data, status) { // failed
|
||||
growl.error(_t('admin_calendar.deletion_failed'));
|
||||
growl.error(_t('app.admin.calendar.deletion_failed'));
|
||||
}
|
||||
);
|
||||
});
|
||||
@ -167,7 +171,7 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
$scope.alertExport = function (type) {
|
||||
Export.status({ category: 'availabilities', type }).then(function (res) {
|
||||
if (!res.data.exists) {
|
||||
return growl.success(_t('admin_calendar.export_is_running_you_ll_be_notified_when_its_ready'));
|
||||
return growl.success(_t('app.admin.calendar.export_is_running_you_ll_be_notified_when_its_ready'));
|
||||
}
|
||||
});
|
||||
};
|
||||
@ -195,8 +199,8 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
resolve: {
|
||||
object () {
|
||||
return {
|
||||
title: _t('admin_calendar.confirmation_required'),
|
||||
msg: locked ? _t('admin_calendar.do_you_really_want_to_allow_reservations') : _t('admin_calendar.do_you_really_want_to_block_this_slot')
|
||||
title: _t('app.admin.calendar.confirmation_required'),
|
||||
msg: locked ? _t('app.admin.calendar.do_you_really_want_to_allow_reservations') : _t('app.admin.calendar.do_you_really_want_to_block_this_slot')
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -208,18 +212,18 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
{ lock: !locked },
|
||||
function (data) { // success
|
||||
$scope.availability = data;
|
||||
growl.success(locked ? _t('admin_calendar.unlocking_success') : _t('admin_calendar.locking_success'));
|
||||
growl.success(locked ? _t('app.admin.calendar.unlocking_success') : _t('app.admin.calendar.locking_success'));
|
||||
uiCalendarConfig.calendars.calendar.fullCalendar('refetchEvents');
|
||||
},
|
||||
function (error) { // failed
|
||||
growl.error(locked ? _t('admin_calendar.unlocking_failed') : _t('admin_calendar.locking_failed'));
|
||||
growl.error(locked ? _t('app.admin.calendar.unlocking_failed') : _t('app.admin.calendar.locking_failed'));
|
||||
console.error(error);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
return growl.error(_t('admin_calendar.unlockable_because_reservations'));
|
||||
return growl.error(_t('app.admin.calendar.unlockable_because_reservations'));
|
||||
}
|
||||
};
|
||||
|
||||
@ -228,32 +232,24 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
*/
|
||||
$scope.removeSlot = function () {
|
||||
// open a confirmation dialog
|
||||
dialogs.confirm(
|
||||
{
|
||||
const modalInstance = $uibModal.open({
|
||||
animation: true,
|
||||
templateUrl: '<%= asset_path "admin/calendar/deleteRecurrent.html" %>',
|
||||
size: 'md',
|
||||
controller: 'DeleteRecurrentAvailabilityController',
|
||||
resolve: {
|
||||
object () {
|
||||
return {
|
||||
title: _t('admin_calendar.confirmation_required'),
|
||||
msg: _t('admin_calendar.do_you_really_want_to_delete_this_slot')
|
||||
};
|
||||
availabilityPromise: ['Availability', function (Availability) { return Availability.get({ id: $scope.availability.id }).$promise; }]
|
||||
}
|
||||
}
|
||||
},
|
||||
function () {
|
||||
// the admin has confirmed, delete the slot
|
||||
Availability.delete(
|
||||
{ id: $scope.availability.id },
|
||||
function () {
|
||||
uiCalendarConfig.calendars.calendar.fullCalendar('removeEvents', $scope.availability.id);
|
||||
|
||||
growl.success(_t('admin_calendar.the_slot_START-END_has_been_successfully_deleted', { START: moment(event.start).format('LL LT'), END: moment(event.end).format('LT') }));
|
||||
$scope.availability = null;
|
||||
},
|
||||
function () {
|
||||
growl.error(_t('admin_calendar.unable_to_delete_the_slot_START-END_because_it_s_already_reserved_by_a_member', { START: moment(event.start).format('LL LT'), END: moment(event.end).format('LT') }));
|
||||
});
|
||||
// once the dialog was closed, do things depending on the result
|
||||
modalInstance.result.then(function (res) {
|
||||
if (res.status == 'success') {
|
||||
$scope.availability = null;
|
||||
}
|
||||
);
|
||||
for (const availability of res.availabilities) {
|
||||
uiCalendarConfig.calendars.calendar.fullCalendar('removeEvents', availability);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
@ -275,10 +271,22 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
var calendarSelectCb = function (start, end, jsEvent, view) {
|
||||
start = moment.tz(start.toISOString(), Fablab.timezone);
|
||||
end = moment.tz(end.toISOString(), Fablab.timezone);
|
||||
// first we check that the selected slot is an N-hours multiple (ie. not decimal)
|
||||
if (Number.isInteger(parseInt((end.valueOf() - start.valueOf()) / (SLOT_MULTIPLE * 1000), 10) / SLOT_MULTIPLE)) {
|
||||
|
||||
// check if slot is not in the past
|
||||
const today = new Date();
|
||||
if (parseInt((start.valueOf() - today) / (60 * 1000), 10) >= 0) {
|
||||
if (Math.trunc((start.valueOf() - today) / (60 * 1000)) < 0) {
|
||||
growl.warning(_t('app.admin.calendar.event_in_the_past'));
|
||||
return uiCalendarConfig.calendars.calendar.fullCalendar('unselect');
|
||||
}
|
||||
|
||||
// check that the selected slot is an multiple of SLOT_MULTIPLE (ie. not decimal)
|
||||
const slots = Math.trunc((end.valueOf() - start.valueOf()) / (60 * 1000)) / SLOT_MULTIPLE;
|
||||
if (!Number.isInteger(slots)) {
|
||||
// otherwise, round it to upper decimal
|
||||
const upper = Math.ceil(slots) * SLOT_MULTIPLE;
|
||||
end = moment(start).add(upper, 'minutes');
|
||||
}
|
||||
|
||||
// then we open a modal window to let the admin specify the slot type
|
||||
const modalInstance = $uibModal.open({
|
||||
templateUrl: '<%= asset_path "admin/calendar/eventModal.html" %>',
|
||||
@ -288,7 +296,8 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
end () { return end; },
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }],
|
||||
trainingsPromise: ['Training', function (Training) { return Training.query().$promise; }],
|
||||
spacesPromise: ['Space', function (Space) { return Space.query().$promise; }]
|
||||
spacesPromise: ['Space', function (Space) { return Space.query().$promise; }],
|
||||
tagsPromise: ['Tag', function (Tag) { return Tag.query().$promise; }]
|
||||
} });
|
||||
// when the modal is closed, we send the slot to the server for saving
|
||||
modalInstance.result.then(
|
||||
@ -312,8 +321,6 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
},
|
||||
function () { uiCalendarConfig.calendars.calendar.fullCalendar('unselect'); }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return uiCalendarConfig.calendars.calendar.fullCalendar('unselect');
|
||||
};
|
||||
@ -325,6 +332,12 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
var calendarEventClickCb = function (event, jsEvent, view) {
|
||||
$scope.availability = event;
|
||||
|
||||
if ($scope.availabilityDom) {
|
||||
$scope.availabilityDom.classList.remove("fc-selected")
|
||||
}
|
||||
$scope.availabilityDom = jsEvent.target.closest('.fc-event');
|
||||
$scope.availabilityDom.classList.add("fc-selected")
|
||||
|
||||
// if the user has clicked on the delete event button, delete the event
|
||||
if ($(jsEvent.target).hasClass('remove-event')) {
|
||||
return $scope.removeSlot();
|
||||
@ -340,7 +353,9 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
* @see http://fullcalendar.io/docs/event_rendering/eventRender/
|
||||
*/
|
||||
var eventRenderCb = function (event, element) {
|
||||
if (event.available_type !== 'event') {
|
||||
element.find('.fc-content').prepend('<span class="remove-event">x </span>');
|
||||
}
|
||||
if (event.tags.length > 0) {
|
||||
let html = '';
|
||||
for (let tag of Array.from(event.tags)) {
|
||||
@ -355,12 +370,23 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
* Triggered when resource fetching starts/stops.
|
||||
* @see https://fullcalendar.io/docs/resource_data/loading/
|
||||
*/
|
||||
return loadingCb = function (isLoading, view) {
|
||||
const loadingCb = function (isLoading, view) {
|
||||
if (isLoading) {
|
||||
// we remove existing events when fetching starts to prevent duplicates
|
||||
return uiCalendarConfig.calendars.calendar.fullCalendar('removeEvents');
|
||||
uiCalendarConfig.calendars.calendar.fullCalendar('removeEvents');
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Triggered when the view is changed
|
||||
* @see https://fullcalendar.io/docs/v3/viewRender#v2
|
||||
*/
|
||||
const viewRenderCb = function(view, element) {
|
||||
// we unselect the current event to keep consistency
|
||||
$scope.availability = null;
|
||||
$scope.availabilityDom = null;
|
||||
};
|
||||
}
|
||||
|
||||
]);
|
||||
@ -368,8 +394,8 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
/**
|
||||
* Controller used in the slot creation modal window
|
||||
*/
|
||||
Application.Controllers.controller('CreateEventModalController', ['$scope', '$uibModalInstance', 'moment', 'start', 'end', 'machinesPromise', 'Availability', 'trainingsPromise', 'spacesPromise', 'Tag', 'growl', '_t',
|
||||
function ($scope, $uibModalInstance, moment, start, end, machinesPromise, Availability, trainingsPromise, spacesPromise, Tag, growl, _t) {
|
||||
Application.Controllers.controller('CreateEventModalController', ['$scope', '$uibModalInstance', '$sce', 'moment', 'start', 'end', 'machinesPromise', 'Availability', 'trainingsPromise', 'spacesPromise', 'tagsPromise', 'growl', '_t',
|
||||
function ($scope, $uibModalInstance, $sce, moment, start, end, machinesPromise, Availability, trainingsPromise, spacesPromise, tagsPromise, growl, _t) {
|
||||
// $uibModal parameter
|
||||
$scope.start = start;
|
||||
|
||||
@ -385,6 +411,9 @@ Application.Controllers.controller('CreateEventModalController', ['$scope', '$ui
|
||||
// spaces list
|
||||
$scope.spaces = spacesPromise.filter(function (s) { return !s.disabled; });
|
||||
|
||||
// all tags list
|
||||
$scope.tags = tagsPromise;
|
||||
|
||||
// machines associated with the created slot
|
||||
$scope.selectedMachines = [];
|
||||
|
||||
@ -416,9 +445,23 @@ Application.Controllers.controller('CreateEventModalController', ['$scope', '$ui
|
||||
$scope.availability = {
|
||||
start_at: start,
|
||||
end_at: end,
|
||||
available_type: 'machines' // default
|
||||
available_type: 'machines', // default
|
||||
tag_ids: [],
|
||||
is_recurrent: false,
|
||||
period: 'week',
|
||||
nb_periods: 1,
|
||||
end_date: undefined // recurrence end
|
||||
};
|
||||
|
||||
// recurrent slots
|
||||
$scope.occurrences = [];
|
||||
|
||||
// localized name(s) of the reservable item(s)
|
||||
$scope.reservableName = '';
|
||||
|
||||
// localized name(s) of the selected tag(s)
|
||||
$scope.tagsName = '';
|
||||
|
||||
/**
|
||||
* Adds or removes the provided machine from the current slot
|
||||
* @param machine {Object}
|
||||
@ -440,7 +483,7 @@ Application.Controllers.controller('CreateEventModalController', ['$scope', '$ui
|
||||
if ($scope.selectedMachines.length > 0) {
|
||||
$scope.availability.machine_ids = $scope.selectedMachines.map(function (m) { return m.id; });
|
||||
} else {
|
||||
growl.error(_t('admin_calendar.you_should_select_at_least_a_machine'));
|
||||
growl.error(_t('app.admin.calendar.you_should_select_at_least_a_machine'));
|
||||
return;
|
||||
}
|
||||
} else if ($scope.availability.available_type === 'training') {
|
||||
@ -448,9 +491,13 @@ Application.Controllers.controller('CreateEventModalController', ['$scope', '$ui
|
||||
} else if ($scope.availability.available_type === 'space') {
|
||||
$scope.availability.space_ids = [$scope.selectedSpace.id];
|
||||
}
|
||||
if ($scope.availability.is_recurrent) {
|
||||
$scope.availability.occurrences = $scope.occurrences;
|
||||
}
|
||||
return Availability.save(
|
||||
{ availability: $scope.availability }
|
||||
, function (availability) { $uibModalInstance.close(availability); });
|
||||
{ availability: $scope.availability },
|
||||
function (availability) { $uibModalInstance.close(availability); }
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -458,6 +505,8 @@ Application.Controllers.controller('CreateEventModalController', ['$scope', '$ui
|
||||
*/
|
||||
$scope.next = function () {
|
||||
if ($scope.step === 1) { $scope.setNbTotalPlaces(); }
|
||||
if ($scope.step === 2) { return validateSelection(); }
|
||||
if ($scope.step === 4) { return validateRecurrence(); }
|
||||
return $scope.step++;
|
||||
};
|
||||
|
||||
@ -495,23 +544,25 @@ Application.Controllers.controller('CreateEventModalController', ['$scope', '$ui
|
||||
$scope.selectedSpace = $scope.spaces[0];
|
||||
}
|
||||
|
||||
Tag.query().$promise.then(function (data) { $scope.tags = data; });
|
||||
|
||||
// When we configure a machine availability, do not let the user change the end time, as the total
|
||||
// time must be dividable by 60 minutes (base slot duration). For training availabilities, the user
|
||||
// When we configure a machine/space availability, do not let the user change the end time, as the total
|
||||
// time must be dividable by Fablab.slotDuration minutes (base slot duration). For training availabilities, the user
|
||||
// can configure any duration as it does not matters.
|
||||
$scope.$watch('availability.available_type', function (newValue, oldValue, scope) {
|
||||
if ((newValue === 'machines') || (newValue === 'space')) {
|
||||
$scope.endDateReadOnly = true;
|
||||
const diff = moment($scope.end).diff($scope.start, 'hours'); // the result is rounded down by moment.js
|
||||
$scope.end = moment($scope.start).add(diff, 'hours').toDate();
|
||||
const slots = Math.trunc(($scope.end.valueOf() - $scope.start.valueOf()) / (60 * 1000)) / Fablab.slotDuration;
|
||||
if (!Number.isInteger(slots)) {
|
||||
// otherwise, round it to upper decimal
|
||||
const upper = Math.ceil(slots) * Fablab.slotDuration;
|
||||
$scope.end = moment($scope.start).add(upper, 'minutes').toDate();
|
||||
}
|
||||
return $scope.availability.end_at = $scope.end;
|
||||
} else {
|
||||
return $scope.endDateReadOnly = false;
|
||||
}
|
||||
});
|
||||
|
||||
// When the start date is changed, if we are configuring a machine availability,
|
||||
// When the start date is changed, if we are configuring a machine/space availability,
|
||||
// maintain the relative length of the slot (ie. change the end time accordingly)
|
||||
$scope.$watch('start', function (newValue, oldValue, scope) {
|
||||
// for machine or space availabilities, adjust the end time
|
||||
@ -520,8 +571,8 @@ Application.Controllers.controller('CreateEventModalController', ['$scope', '$ui
|
||||
end.add(moment(newValue).diff(oldValue), 'milliseconds');
|
||||
$scope.end = end.toDate();
|
||||
} else { // for training availabilities
|
||||
// prevent the admin from setting the begining after the and
|
||||
if (moment(newValue).add(1, 'hour').isAfter($scope.end)) {
|
||||
// prevent the admin from setting the beginning after the end
|
||||
if (moment(newValue).add(Fablab.slotDuration, 'minutes').isAfter($scope.end)) {
|
||||
$scope.start = oldValue;
|
||||
}
|
||||
}
|
||||
@ -531,8 +582,8 @@ Application.Controllers.controller('CreateEventModalController', ['$scope', '$ui
|
||||
|
||||
// Maintain consistency between the end time and the date object in the availability object
|
||||
return $scope.$watch('end', function (newValue, oldValue, scope) {
|
||||
// we prevent the admin from setting the end of the availability before its begining
|
||||
if (moment($scope.start).add(1, 'hour').isAfter(newValue)) {
|
||||
// we prevent the admin from setting the end of the availability before its beginning
|
||||
if (moment($scope.start).add(Fablab.slotDuration, 'minutes').isAfter(newValue)) {
|
||||
$scope.end = oldValue;
|
||||
}
|
||||
// update availability object
|
||||
@ -540,7 +591,270 @@ Application.Controllers.controller('CreateEventModalController', ['$scope', '$ui
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Validates that a machine or more was/were selected before continuing to step 3 (adjust time + tags)
|
||||
*/
|
||||
const validateSelection = function () {
|
||||
if ($scope.availability.available_type === 'machines') {
|
||||
if ($scope.selectedMachines.length === 0) {
|
||||
return growl.error(_t('app.admin.calendar.you_should_select_at_least_a_machine'));
|
||||
}
|
||||
}
|
||||
$scope.step++;
|
||||
};
|
||||
|
||||
/**
|
||||
* Validates that the recurrence parameters were correctly set before continuing to step 5 (summary)
|
||||
*/
|
||||
const validateRecurrence = function () {
|
||||
if ($scope.availability.is_recurrent) {
|
||||
if (!$scope.availability.period) {
|
||||
return growl.error(_t('app.admin.calendar.select_period'));
|
||||
}
|
||||
if (!$scope.availability.nb_periods) {
|
||||
return growl.error(_t('app.admin.calendar.select_nb_period'));
|
||||
}
|
||||
if (!$scope.availability.end_date) {
|
||||
return growl.error(_t('app.admin.calendar.select_end_date'));
|
||||
}
|
||||
}
|
||||
// settings are ok
|
||||
computeOccurrences();
|
||||
computeNames();
|
||||
$scope.step++;
|
||||
};
|
||||
|
||||
/**
|
||||
* Compute the various occurrences of the availability, according to the recurrence settings
|
||||
*/
|
||||
const computeOccurrences = function () {
|
||||
$scope.occurrences = [];
|
||||
|
||||
if ($scope.availability.is_recurrent) {
|
||||
const date = moment($scope.availability.start_at);
|
||||
const diff = moment($scope.availability.end_at).diff($scope.availability.start_at);
|
||||
const end = moment($scope.availability.end_date).endOf('day');
|
||||
while (date.isBefore(end)) {
|
||||
const occur_end = moment(date).add(diff, 'ms');
|
||||
$scope.occurrences.push({
|
||||
start_at: date.toDate(),
|
||||
end_at: occur_end.toDate()
|
||||
});
|
||||
date.add($scope.availability.nb_periods, $scope.availability.period);
|
||||
}
|
||||
} else {
|
||||
$scope.occurrences.push({
|
||||
start_at: $scope.availability.start_at,
|
||||
end_at: $scope.availability.end_at
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const computeNames = function () {
|
||||
$scope.reservableName = '';
|
||||
switch ($scope.availability.available_type) {
|
||||
case 'machines':
|
||||
$scope.reservableName = localizedList($scope.selectedMachines)
|
||||
break;
|
||||
case 'training':
|
||||
$scope.reservableName = `<strong>${$scope.selectedTraining.name}</strong>`;
|
||||
break;
|
||||
case 'space':
|
||||
$scope.reservableName = `<strong>${$scope.selectedSpace.name}</strong>`;
|
||||
break;
|
||||
default:
|
||||
$scope.reservableName = `<span class="warning">${_t("app.admin.calendar.none")}</span>`;
|
||||
}
|
||||
const tags = $scope.tags.filter(function (t) {
|
||||
return $scope.availability.tag_ids.indexOf(t.id) > -1;
|
||||
})
|
||||
$scope.tagsName = localizedList(tags);
|
||||
}
|
||||
|
||||
const localizedList = function (items) {
|
||||
if (items.length === 0) return `<span class="text-gray text-italic">${_t("app.admin.calendar.none")}</span>`;
|
||||
|
||||
const names = items.map(function (i) { return $sce.trustAsHtml(`<strong>${i.name}</strong>`); });
|
||||
if (items.length > 1) return names.slice(0, -1).join(', ') + ` ${_t('app.admin.calendar.and')} ` + names[names.length - 1];
|
||||
|
||||
return names[0];
|
||||
}
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize();
|
||||
}
|
||||
]);
|
||||
|
||||
/**
|
||||
* Controller used in the slot deletion modal window
|
||||
*/
|
||||
Application.Controllers.controller('DeleteRecurrentAvailabilityController', ['$scope', '$uibModalInstance', 'Availability', 'availabilityPromise', 'growl', '_t',
|
||||
function ($scope, $uibModalInstance, Availability, availabilityPromise, growl, _t) {
|
||||
|
||||
// is the current slot (to be deleted) recurrent?
|
||||
$scope.isRecurrent = availabilityPromise.is_recurrent;
|
||||
|
||||
// with recurrent slots: how many slots should we delete?
|
||||
$scope.deleteMode = 'single';
|
||||
|
||||
/**
|
||||
* Confirmation callback
|
||||
*/
|
||||
$scope.ok = function () {
|
||||
const { id, start_at, end_at } = availabilityPromise;
|
||||
// the admin has confirmed, delete the slot
|
||||
Availability.delete(
|
||||
{ id, mode: $scope.deleteMode },
|
||||
function (res) {
|
||||
// delete success
|
||||
if (res.deleted > 1) {
|
||||
growl.success(_t(
|
||||
'app.admin.calendar.slots_deleted',
|
||||
{START: moment(start_at).format('LL LT'), COUNT: res.deleted - 1}
|
||||
));
|
||||
} else {
|
||||
growl.success(_t(
|
||||
'app.admin.calendar.slot_successfully_deleted',
|
||||
{START: moment(start_at).format('LL LT'), END: moment(end_at).format('LT')}
|
||||
));
|
||||
}
|
||||
$uibModalInstance.close({
|
||||
status: 'success',
|
||||
availabilities: res.details.map(function (d) { return d.availability.id })
|
||||
});
|
||||
},
|
||||
function (res) {
|
||||
// not everything was deleted
|
||||
const { data } = res;
|
||||
if (data.total > 1) {
|
||||
growl.warning(_t(
|
||||
'app.admin.calendar.slots_not_deleted',
|
||||
{TOTAL: data.total, COUNT: data.total - data.deleted}
|
||||
));
|
||||
} else {
|
||||
growl.error(_t(
|
||||
'app.admin.calendar.unable_to_delete_the_slot',
|
||||
{START: moment(start_at).format('LL LT'), END: moment(end_at).format('LT')}
|
||||
));
|
||||
}
|
||||
$uibModalInstance.close({
|
||||
status: 'failed',
|
||||
availabilities: data.details.filter(function (d) { return d.status }).map(function (d) { return d.availability.id })
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancellation callback
|
||||
*/
|
||||
$scope.cancel = function () {
|
||||
$uibModalInstance.dismiss('cancel');
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Controller used in the iCalendar (ICS) imports management page
|
||||
*/
|
||||
|
||||
Application.Controllers.controller('AdminICalendarController', ['$scope', 'iCalendars', 'ICalendar', 'dialogs', 'growl', '_t',
|
||||
function ($scope, iCalendars, ICalendar, dialogs, growl, _t) {
|
||||
// list of ICS sources
|
||||
$scope.calendars = iCalendars;
|
||||
|
||||
// configuration of a new ICS source
|
||||
$scope.newCalendar = {
|
||||
color: undefined,
|
||||
text_color: undefined,
|
||||
url: undefined,
|
||||
name: undefined,
|
||||
text_hidden: false
|
||||
};
|
||||
|
||||
/**
|
||||
* Save the new iCalendar in database
|
||||
*/
|
||||
$scope.save = function () {
|
||||
ICalendar.save({}, { i_calendar: $scope.newCalendar }, function (data) {
|
||||
// success
|
||||
$scope.calendars.push(data);
|
||||
$scope.newCalendar.url = undefined;
|
||||
$scope.newCalendar.name = undefined;
|
||||
$scope.newCalendar.color = null;
|
||||
$scope.newCalendar.text_color = null;
|
||||
$scope.newCalendar.text_hidden = false;
|
||||
}, function (error) {
|
||||
// failed
|
||||
growl.error(_t('app.admin.icalendar.create_error'));
|
||||
console.error(error);
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a CSS-like style of the given calendar configuration
|
||||
* @param calendar
|
||||
*/
|
||||
$scope.calendarStyle = function (calendar) {
|
||||
return {
|
||||
'border-color': calendar.color,
|
||||
'color': calendar.text_color,
|
||||
'width': calendar.text_hidden ? '50px' : 'auto',
|
||||
'height': calendar.text_hidden ? '21px' : 'auto'
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the given calendar from the database
|
||||
* @param calendar
|
||||
*/
|
||||
$scope.delete = function (calendar) {
|
||||
dialogs.confirm(
|
||||
{
|
||||
resolve: {
|
||||
object () {
|
||||
return {
|
||||
title: _t('app.admin.icalendar.confirmation_required'),
|
||||
msg: _t('app.admin.icalendar.confirm_delete_import')
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
function () {
|
||||
ICalendar.delete(
|
||||
{ id: calendar.id },
|
||||
function () {
|
||||
// success
|
||||
const idx = $scope.calendars.indexOf(calendar);
|
||||
$scope.calendars.splice(idx, 1);
|
||||
growl.info(_t('app.admin.icalendar.delete_success'));
|
||||
}, function (error) {
|
||||
// failed
|
||||
growl.error(_t('app.admin.icalendar.delete_failed'));
|
||||
console.error(error);
|
||||
}
|
||||
);
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously re-fetches the events from the given calendar
|
||||
* @param calendar
|
||||
*/
|
||||
$scope.sync = function (calendar) {
|
||||
ICalendar.sync(
|
||||
{ id: calendar.id },
|
||||
function () {
|
||||
// success
|
||||
growl.info(_t('app.admin.icalendar.refresh'));
|
||||
}, function (error) {
|
||||
// failed
|
||||
growl.error(_t('app.admin.icalendar.sync_failed'));
|
||||
console.error(error);
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
@ -1,19 +1,8 @@
|
||||
/* eslint-disable
|
||||
no-return-assign,
|
||||
no-undef,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
// Fix any style issues and re-enable lint.
|
||||
/*
|
||||
* decaffeinate suggestions:
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
/* COMMON CODE */
|
||||
|
||||
// The validity per user defines how many time a user may ba able to use the same coupon
|
||||
// Here are the various options for this parameter
|
||||
const userValidities = ['once', 'forever'];
|
||||
const VALIDITIES = ['once', 'forever'];
|
||||
|
||||
/**
|
||||
* Controller used in the coupon creation page
|
||||
@ -27,7 +16,7 @@ Application.Controllers.controller('NewCouponController', ['$scope', '$state', '
|
||||
};
|
||||
|
||||
// Options for the validity per user
|
||||
$scope.validities = userValidities;
|
||||
$scope.validities = VALIDITIES;
|
||||
|
||||
// Default parameters for AngularUI-Bootstrap datepicker (used for coupon validity limit selection)
|
||||
$scope.datePicker = {
|
||||
@ -39,6 +28,13 @@ Application.Controllers.controller('NewCouponController', ['$scope', '$state', '
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a localized human-readable name for the provided validity
|
||||
*/
|
||||
$scope.validityName = function (validity) {
|
||||
return _t(`app.shared.coupon.${validity}`);
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows/hides the validity limit datepicker
|
||||
* @param $event {Object} jQuery event object
|
||||
@ -46,17 +42,17 @@ Application.Controllers.controller('NewCouponController', ['$scope', '$state', '
|
||||
$scope.toggleDatePicker = function ($event) {
|
||||
$event.preventDefault();
|
||||
$event.stopPropagation();
|
||||
return $scope.datePicker.opened = !$scope.datePicker.opened;
|
||||
$scope.datePicker.opened = !$scope.datePicker.opened;
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to save the new coupon in $scope.coupon and redirect the user to the listing page
|
||||
*/
|
||||
return $scope.saveCoupon = () =>
|
||||
$scope.saveCoupon = () =>
|
||||
Coupon.save({ coupon: $scope.coupon }, coupon => $state.go('app.admin.pricing')
|
||||
, function (err) {
|
||||
growl.error(_t('unable_to_create_the_coupon_check_code_already_used'));
|
||||
return console.error(err);
|
||||
growl.error(_t('app.admin.coupons_new.unable_to_create_the_coupon_check_code_already_used'));
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
]);
|
||||
@ -75,7 +71,7 @@ Application.Controllers.controller('EditCouponController', ['$scope', '$state',
|
||||
$scope.coupon = couponPromise;
|
||||
|
||||
// Options for the validity per user
|
||||
$scope.validities = userValidities;
|
||||
$scope.validities = VALIDITIES;
|
||||
|
||||
// Mapping for validation errors
|
||||
$scope.errors = {};
|
||||
@ -90,6 +86,13 @@ Application.Controllers.controller('EditCouponController', ['$scope', '$state',
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a localized human-readable name for the provided validity
|
||||
*/
|
||||
$scope.validityName = function (validity) {
|
||||
return _t(`app.shared.coupon.${validity}`);
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows/hides the validity limit datepicker
|
||||
* @param $event {Object} jQuery event object
|
||||
@ -97,7 +100,7 @@ Application.Controllers.controller('EditCouponController', ['$scope', '$state',
|
||||
$scope.toggleDatePicker = function ($event) {
|
||||
$event.preventDefault();
|
||||
$event.stopPropagation();
|
||||
return $scope.datePicker.opened = !$scope.datePicker.opened;
|
||||
$scope.datePicker.opened = !$scope.datePicker.opened;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -105,10 +108,10 @@ Application.Controllers.controller('EditCouponController', ['$scope', '$state',
|
||||
*/
|
||||
$scope.updateCoupon = function () {
|
||||
$scope.errors = {};
|
||||
return Coupon.update({ id: $scope.coupon.id }, { coupon: $scope.coupon }, coupon => $state.go('app.admin.pricing')
|
||||
Coupon.update({ id: $scope.coupon.id }, { coupon: $scope.coupon }, coupon => $state.go('app.admin.pricing')
|
||||
, function (err) {
|
||||
growl.error(_t('unable_to_update_the_coupon_an_error_occurred'));
|
||||
return $scope.errors = err.data;
|
||||
growl.error(_t('app.admin.coupons_edit.unable_to_update_the_coupon_an_error_occurred'));
|
||||
$scope.errors = err.data;
|
||||
});
|
||||
};
|
||||
|
||||
@ -120,7 +123,7 @@ Application.Controllers.controller('EditCouponController', ['$scope', '$state',
|
||||
const initialize = function () {
|
||||
// parse the date if any
|
||||
if (couponPromise.valid_until) {
|
||||
return $scope.coupon.valid_until = moment(couponPromise.valid_until).toDate();
|
||||
$scope.coupon.valid_until = moment(couponPromise.valid_until).toDate();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -228,26 +228,26 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
*/
|
||||
$scope.removeElement = function (model, index) {
|
||||
if ((model === 'category') && (getModel(model)[1].length === 1)) {
|
||||
growl.error(_t('at_least_one_category_is_required') + ' ' + _t('unable_to_delete_the_last_one'));
|
||||
growl.error(_t('app.admin.events.at_least_one_category_is_required') + ' ' + _t('app.admin.events.unable_to_delete_the_last_one'));
|
||||
return false;
|
||||
}
|
||||
if (getModel(model)[1][index].related_to > 0) {
|
||||
growl.error(_t('unable_to_delete_ELEMENT_already_in_use_NUMBER_times', { ELEMENT: model, NUMBER: getModel(model)[1][index].related_to }, 'messageformat'));
|
||||
growl.error(_t('app.admin.events.unable_to_delete_ELEMENT_already_in_use_NUMBER_times', { ELEMENT: model, NUMBER: getModel(model)[1][index].related_to }));
|
||||
return false;
|
||||
}
|
||||
return dialogs.confirm({
|
||||
resolve: {
|
||||
object () {
|
||||
return {
|
||||
title: _t('confirmation_required'),
|
||||
msg: _t('do_you_really_want_to_delete_this_ELEMENT', { ELEMENT: model }, 'messageformat')
|
||||
title: _t('app.admin.events.confirmation_required'),
|
||||
msg: _t('app.admin.events.do_you_really_want_to_delete_this_ELEMENT', { ELEMENT: model })
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
, function () { // delete confirmed
|
||||
getModel(model)[0].delete(getModel(model)[1][index], null, function () { getModel(model)[1].splice(index, 1); }
|
||||
, function () { growl.error(_t('unable_to_delete_an_error_occured')); });
|
||||
, function () { growl.error(_t('app.admin.events.unable_to_delete_an_error_occured')); });
|
||||
});
|
||||
};
|
||||
|
||||
@ -292,10 +292,10 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
// save the price category to the API
|
||||
PriceCategory.save(p_cat, function (cat) {
|
||||
$scope.priceCategories.push(cat);
|
||||
return growl.success(_t('price_category_successfully_created'));
|
||||
return growl.success(_t('app.admin.events.price_category_successfully_created'));
|
||||
}
|
||||
, function (err) {
|
||||
growl.error(_t('unable_to_add_the_price_category_check_name_already_used'));
|
||||
growl.error(_t('app.admin.events.unable_to_add_the_price_category_check_name_already_used'));
|
||||
return console.error(err);
|
||||
});
|
||||
});
|
||||
@ -308,7 +308,7 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
*/
|
||||
$scope.editPriceCategory = function (id, index) {
|
||||
if ($scope.priceCategories[index].id !== id) {
|
||||
return growl.error(_t('unexpected_error_occurred_please_refresh'));
|
||||
return growl.error(_t('app.admin.events.unexpected_error_occurred_please_refresh'));
|
||||
} else {
|
||||
return $uibModal.open({
|
||||
templateUrl: '<%= asset_path "admin/events/price_form.html" %>',
|
||||
@ -320,10 +320,10 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
// update the price category to the API
|
||||
PriceCategory.update({ id }, { price_category: p_cat }, function (cat) {
|
||||
$scope.priceCategories[index] = cat;
|
||||
return growl.success(_t('price_category_successfully_updated'));
|
||||
return growl.success(_t('app.admin.events.price_category_successfully_updated'));
|
||||
}
|
||||
, function (err) {
|
||||
growl.error(_t('unable_to_update_the_price_category'));
|
||||
growl.error(_t('app.admin.events.unable_to_update_the_price_category'));
|
||||
return console.error(err);
|
||||
});
|
||||
});
|
||||
@ -337,17 +337,17 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
*/
|
||||
$scope.removePriceCategory = function (id, index) {
|
||||
if ($scope.priceCategories[index].id !== id) {
|
||||
return growl.error(_t('unexpected_error_occurred_please_refresh'));
|
||||
return growl.error(_t('app.admin.events.unexpected_error_occurred_please_refresh'));
|
||||
} else if ($scope.priceCategories[index].events > 0) {
|
||||
return growl.error(_t('unable_to_delete_this_price_category_because_it_is_already_used'));
|
||||
return growl.error(_t('app.admin.events.unable_to_delete_this_price_category_because_it_is_already_used'));
|
||||
} else {
|
||||
return dialogs.confirm(
|
||||
{
|
||||
resolve: {
|
||||
object () {
|
||||
return {
|
||||
title: _t('confirmation_required'),
|
||||
msg: _t('do_you_really_want_to_delete_this_price_category')
|
||||
title: _t('app.admin.events.confirmation_required'),
|
||||
msg: _t('app.admin.events.do_you_really_want_to_delete_this_price_category')
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -356,10 +356,10 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
PriceCategory.remove(
|
||||
{ id },
|
||||
function () { // successfully deleted
|
||||
growl.success(_t('price_category_successfully_deleted'));
|
||||
growl.success(_t('app.admin.events.price_category_successfully_deleted'));
|
||||
$scope.priceCategories.splice(index, 1);
|
||||
},
|
||||
function () { growl.error(_t('price_category_deletion_failed')); }
|
||||
function () { growl.error(_t('app.admin.events.price_category_deletion_failed')); }
|
||||
);
|
||||
}
|
||||
);
|
||||
@ -431,7 +431,16 @@ Application.Controllers.controller('ShowEventReservationsController', ['$scope',
|
||||
$scope.event = eventPromise;
|
||||
|
||||
// list of reservations for the current event
|
||||
return $scope.reservations = reservationsPromise;
|
||||
$scope.reservations = reservationsPromise;
|
||||
|
||||
/**
|
||||
* Test if the provided reservation has been cancelled
|
||||
* @param reservation {Reservation}
|
||||
* @returns {boolean}
|
||||
*/
|
||||
$scope.isCancelled = function(reservation) {
|
||||
return !!(reservation.slots[0].canceled_at);
|
||||
}
|
||||
}]);
|
||||
|
||||
/**
|
||||
@ -474,11 +483,11 @@ Application.Controllers.controller('NewEventController', ['$scope', '$state', 'C
|
||||
|
||||
// Possible types of recurrences for an event
|
||||
$scope.recurrenceTypes = [
|
||||
{ label: _t('none'), value: 'none' },
|
||||
{ label: _t('every_days'), value: 'day' },
|
||||
{ label: _t('every_week'), value: 'week' },
|
||||
{ label: _t('every_month'), value: 'month' },
|
||||
{ label: _t('every_year'), value: 'year' }
|
||||
{ label: _t('app.admin.events_new.none'), value: 'none' },
|
||||
{ label: _t('app.admin.events_new.every_days'), value: 'day' },
|
||||
{ label: _t('app.admin.events_new.every_week'), value: 'week' },
|
||||
{ label: _t('app.admin.events_new.every_month'), value: 'month' },
|
||||
{ label: _t('app.admin.events_new.every_year'), value: 'year' }
|
||||
];
|
||||
|
||||
// Using the EventsController
|
||||
|
@ -25,10 +25,10 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
|
||||
const CHART_HEIGHT = 500;
|
||||
|
||||
// Label of the charts' horizontal axes
|
||||
const X_AXIS_LABEL = _t('date');
|
||||
const X_AXIS_LABEL = _t('app.admin.stats_graphs.date');
|
||||
|
||||
// Label of the charts' vertical axes
|
||||
const Y_AXIS_LABEL = _t('number');
|
||||
const Y_AXIS_LABEL = _t('app.admin.stats_graphs.number');
|
||||
|
||||
// Colors for the line charts. Each new line uses the next color in this array
|
||||
const CHART_COLORS = ['#b35a94', '#1c5794', '#00b49e', '#6fac48', '#ebcf4a', '#fd7e33', '#ca3436', '#a26e3a'];
|
||||
@ -193,9 +193,9 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
|
||||
}
|
||||
} else if ($scope.display.interval === 'week') {
|
||||
if ((typeof x === 'number') || d instanceof Date) {
|
||||
return d3.time.format(_t('week_short') + ' %U')(moment(d).toDate());
|
||||
return d3.time.format(_t('app.admin.stats_graphs.week_short') + ' %U')(moment(d).toDate());
|
||||
} else if (typeof d === 'number') {
|
||||
return _t('week_of_START_to_END', { START: moment(d).format('L'), END: moment(d).add(6, 'days').format('L') });
|
||||
return _t('app.admin.stats_graphs.week_of_START_to_END', { START: moment(d).format('L'), END: moment(d).add(6, 'days').format('L') });
|
||||
} else { // typeof d == 'string'
|
||||
return d;
|
||||
}
|
||||
@ -653,7 +653,7 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
|
||||
|
||||
// common for each charts
|
||||
chart.margin({ left: 100, right: 100 });
|
||||
chart.noData(_t('no_data_for_this_period'));
|
||||
chart.noData(_t('app.admin.stats_graphs.no_data_for_this_period'));
|
||||
chart.height(CHART_HEIGHT);
|
||||
|
||||
// add new chart to the page
|
||||
|
@ -54,15 +54,15 @@ Application.Controllers.controller('GroupsController', ['$scope', 'groupsPromise
|
||||
*/
|
||||
$scope.saveGroup = function (data, id) {
|
||||
if (id != null) {
|
||||
return Group.update({ id }, { group: data }, response => growl.success(_t('group_form.changes_successfully_saved'))
|
||||
, error => growl.error(_t('group_form.an_error_occurred_while_saving_changes')));
|
||||
return Group.update({ id }, { group: data }, response => growl.success(_t('app.admin.members.group_form.changes_successfully_saved'))
|
||||
, error => growl.error(_t('app.admin.members.group_form.an_error_occurred_while_saving_changes')));
|
||||
} else {
|
||||
return Group.save({ group: data }, function (resp) {
|
||||
growl.success(_t('group_form.new_group_successfully_saved'));
|
||||
growl.success(_t('app.admin.members.group_form.new_group_successfully_saved'));
|
||||
return $scope.groups[$scope.groups.length - 1].id = resp.id;
|
||||
}
|
||||
, function (error) {
|
||||
growl.error(_t('.group_forman_error_occurred_when_saving_the_new_group'));
|
||||
growl.error(_t('app.admin.members.group_form.an_error_occurred_when_saving_the_new_group'));
|
||||
return $scope.groups.splice($scope.groups.length - 1, 1);
|
||||
});
|
||||
}
|
||||
@ -74,10 +74,10 @@ Application.Controllers.controller('GroupsController', ['$scope', 'groupsPromise
|
||||
*/
|
||||
$scope.removeGroup = index =>
|
||||
Group.delete({ id: $scope.groups[index].id }, function (resp) {
|
||||
growl.success(_t('group_form.group_successfully_deleted'));
|
||||
growl.success(_t('app.admin.members.group_form.group_successfully_deleted'));
|
||||
return $scope.groups.splice(index, 1);
|
||||
}
|
||||
, error => growl.error(_t('group_form.unable_to_delete_group_because_some_users_and_or_groups_are_still_linked_to_it')));
|
||||
, error => growl.error(_t('app.admin.members.group_form.unable_to_delete_group_because_some_users_and_or_groups_are_still_linked_to_it')));
|
||||
|
||||
/**
|
||||
* Enable/disable the group at the specified index
|
||||
@ -86,13 +86,13 @@ Application.Controllers.controller('GroupsController', ['$scope', 'groupsPromise
|
||||
return $scope.toggleDisableGroup = function (index) {
|
||||
const group = $scope.groups[index];
|
||||
if (!group.disabled && (group.users > 0)) {
|
||||
return growl.error(_t('group_form.unable_to_disable_group_with_users', { USERS: group.users }, 'messageformat'));
|
||||
return growl.error(_t('app.admin.members.group_form.unable_to_disable_group_with_users', { USERS: group.users }));
|
||||
} else {
|
||||
return Group.update({ id: group.id }, { group: { disabled: !group.disabled } }, function (response) {
|
||||
$scope.groups[index] = response;
|
||||
return growl.success(_t('group_form.group_successfully_enabled_disabled', { STATUS: response.disabled }, 'messageformat'));
|
||||
return growl.success(_t('app.admin.members.group_form.group_successfully_enabled_disabled', { STATUS: response.disabled }));
|
||||
}
|
||||
, error => growl.error(_t('group_form.unable_to_enable_disable_group', { STATUS: !group.disabled }, 'messageformat')));
|
||||
, error => growl.error(_t('app.admin.members.group_form.unable_to_enable_disable_group', { STATUS: !group.disabled })));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -215,7 +215,7 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
$scope.invoices.unshift(res.avoir);
|
||||
return Invoice.get({ id: invoice.id }, function (data) {
|
||||
invoice.has_avoir = data.has_avoir;
|
||||
return growl.success(_t('invoices.refund_invoice_successfully_created'));
|
||||
return growl.success(_t('app.admin.invoices.refund_invoice_successfully_created'));
|
||||
});
|
||||
});
|
||||
};
|
||||
@ -289,10 +289,10 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
modalInstance.result.then(function (model) {
|
||||
Setting.update({ name: 'invoice_reference' }, { value: model }, function (data) {
|
||||
$scope.invoice.reference.model = model;
|
||||
growl.success(_t('invoices.invoice_reference_successfully_saved'));
|
||||
growl.success(_t('app.admin.invoices.invoice_reference_successfully_saved'));
|
||||
}
|
||||
, function (error) {
|
||||
growl.error(_t('invoices.an_error_occurred_while_saving_invoice_reference'));
|
||||
growl.error(_t('app.admin.invoices.an_error_occurred_while_saving_invoice_reference'));
|
||||
console.error(error);
|
||||
});
|
||||
});
|
||||
@ -327,24 +327,24 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
Setting.update({ name: 'invoice_code-value' }, { value: result.model }, function (data) {
|
||||
$scope.invoice.code.model = result.model;
|
||||
if (result.active) {
|
||||
return growl.success(_t('invoices.invoicing_code_succesfully_saved'));
|
||||
return growl.success(_t('app.admin.invoices.invoicing_code_succesfully_saved'));
|
||||
}
|
||||
}
|
||||
, function (error) {
|
||||
growl.error(_t('invoices.an_error_occurred_while_saving_the_invoicing_code'));
|
||||
growl.error(_t('app.admin.invoices.an_error_occurred_while_saving_the_invoicing_code'));
|
||||
return console.error(error);
|
||||
});
|
||||
|
||||
return Setting.update({ name: 'invoice_code-active' }, { value: result.active ? 'true' : 'false' }, function (data) {
|
||||
$scope.invoice.code.active = result.active;
|
||||
if (result.active) {
|
||||
return growl.success(_t('invoices.code_successfully_activated'));
|
||||
return growl.success(_t('app.admin.invoices.code_successfully_activated'));
|
||||
} else {
|
||||
return growl.success(_t('invoices.code_successfully_disabled'));
|
||||
return growl.success(_t('app.admin.invoices.code_successfully_disabled'));
|
||||
}
|
||||
}
|
||||
, function (error) {
|
||||
growl.error(_t('invoices.an_error_occurred_while_activating_the_invoicing_code'));
|
||||
growl.error(_t('app.admin.invoices.an_error_occurred_while_activating_the_invoicing_code'));
|
||||
return console.error(error);
|
||||
});
|
||||
});
|
||||
@ -373,10 +373,10 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
return modalInstance.result.then(function (model) {
|
||||
Setting.update({ name: 'invoice_order-nb' }, { value: model }, function (data) {
|
||||
$scope.invoice.number.model = model;
|
||||
return growl.success(_t('invoices.order_number_successfully_saved'));
|
||||
return growl.success(_t('app.admin.invoices.order_number_successfully_saved'));
|
||||
}
|
||||
, function (error) {
|
||||
growl.error(_t('invoices.an_error_occurred_while_saving_the_order_number'));
|
||||
growl.error(_t('app.admin.invoices.an_error_occurred_while_saving_the_order_number'));
|
||||
return console.error(error);
|
||||
});
|
||||
});
|
||||
@ -431,24 +431,24 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
Setting.update({ name: 'invoice_VAT-rate' }, { value: result.rate + '' }, function (data) {
|
||||
$scope.invoice.VAT.rate = result.rate;
|
||||
if (result.active) {
|
||||
return growl.success(_t('invoices.VAT_rate_successfully_saved'));
|
||||
return growl.success(_t('app.admin.invoices.VAT_rate_successfully_saved'));
|
||||
}
|
||||
}
|
||||
, function (error) {
|
||||
growl.error(_t('invoices.an_error_occurred_while_saving_the_VAT_rate'));
|
||||
growl.error(_t('app.admin.invoices.an_error_occurred_while_saving_the_VAT_rate'));
|
||||
return console.error(error);
|
||||
});
|
||||
|
||||
return Setting.update({ name: 'invoice_VAT-active' }, { value: result.active ? 'true' : 'false' }, function (data) {
|
||||
$scope.invoice.VAT.active = result.active;
|
||||
if (result.active) {
|
||||
return growl.success(_t('invoices.VAT_successfully_activated'));
|
||||
return growl.success(_t('app.admin.invoices.VAT_successfully_activated'));
|
||||
} else {
|
||||
return growl.success(_t('invoices.VAT_successfully_disabled'));
|
||||
return growl.success(_t('app.admin.invoices.VAT_successfully_disabled'));
|
||||
}
|
||||
}
|
||||
, function (error) {
|
||||
growl.error(_t('invoices.an_error_occurred_while_activating_the_VAT'));
|
||||
growl.error(_t('app.admin.invoices.an_error_occurred_while_activating_the_VAT'));
|
||||
return console.error(error);
|
||||
});
|
||||
});
|
||||
@ -461,10 +461,10 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
const parsed = parseHtml($scope.invoice.text.content);
|
||||
return Setting.update({ name: 'invoice_text' }, { value: parsed }, function (data) {
|
||||
$scope.invoice.text.content = parsed;
|
||||
return growl.success(_t('invoices.text_successfully_saved'));
|
||||
return growl.success(_t('app.admin.invoices.text_successfully_saved'));
|
||||
}
|
||||
, function (error) {
|
||||
growl.error(_t('invoices.an_error_occurred_while_saving_the_text'));
|
||||
growl.error(_t('app.admin.invoices.an_error_occurred_while_saving_the_text'));
|
||||
return console.error(error);
|
||||
});
|
||||
};
|
||||
@ -476,10 +476,10 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
const parsed = parseHtml($scope.invoice.legals.content);
|
||||
return Setting.update({ name: 'invoice_legals' }, { value: parsed }, function (data) {
|
||||
$scope.invoice.legals.content = parsed;
|
||||
return growl.success(_t('invoices.address_and_legal_information_successfully_saved'));
|
||||
return growl.success(_t('app.admin.invoices.address_and_legal_information_successfully_saved'));
|
||||
}
|
||||
, function (error) {
|
||||
growl.error(_t('invoices.an_error_occurred_while_saving_the_address_and_the_legal_information'));
|
||||
growl.error(_t('app.admin.invoices.an_error_occurred_while_saving_the_address_and_the_legal_information'));
|
||||
return console.error(error);
|
||||
});
|
||||
};
|
||||
@ -552,7 +552,7 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
$scope.save = function() {
|
||||
Setting.bulkUpdate(
|
||||
{ settings: Object.values($scope.settings) },
|
||||
function () { growl.success(_t('invoices.codes_customization_success')); },
|
||||
function () { growl.success(_t('app.admin.invoices.codes_customization_success')); },
|
||||
function (error) {
|
||||
growl.error('unexpected_error_occurred');
|
||||
console.error(error);
|
||||
@ -591,9 +591,9 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
return Setting.update(
|
||||
{ name: 'invoice_logo' },
|
||||
{ value: $scope.invoice.logo.base64 },
|
||||
function (data) { growl.success(_t('invoices.logo_successfully_saved')); },
|
||||
function (data) { growl.success(_t('app.admin.invoices.logo_successfully_saved')); },
|
||||
function (error) {
|
||||
growl.error(_t('invoices.an_error_occurred_while_saving_the_logo'));
|
||||
growl.error(_t('app.admin.invoices.an_error_occurred_while_saving_the_logo'));
|
||||
return console.error(error);
|
||||
}
|
||||
);
|
||||
@ -696,17 +696,17 @@ Application.Controllers.controller('AvoirModalController', ['$scope', '$uibModal
|
||||
|
||||
// Possible refunding methods
|
||||
$scope.avoirModes = [
|
||||
{ name: _t('invoices.none'), value: 'none' },
|
||||
{ name: _t('invoices.by_cash'), value: 'cash' },
|
||||
{ name: _t('invoices.by_cheque'), value: 'cheque' },
|
||||
{ name: _t('invoices.by_transfer'), value: 'transfer' },
|
||||
{ name: _t('invoices.by_wallet'), value: 'wallet' }
|
||||
{ name: _t('app.admin.invoices.none'), value: 'none' },
|
||||
{ name: _t('app.admin.invoices.by_cash'), value: 'cash' },
|
||||
{ name: _t('app.admin.invoices.by_cheque'), value: 'cheque' },
|
||||
{ name: _t('app.admin.invoices.by_transfer'), value: 'transfer' },
|
||||
{ name: _t('app.admin.invoices.by_wallet'), value: 'wallet' }
|
||||
];
|
||||
|
||||
// If a subscription was took with the current invoice, should it be canceled or not
|
||||
$scope.subscriptionExpireOptions = {};
|
||||
$scope.subscriptionExpireOptions[_t('yes')] = true;
|
||||
$scope.subscriptionExpireOptions[_t('no')] = false;
|
||||
$scope.subscriptionExpireOptions[_t('app.shared.buttons.yes')] = true;
|
||||
$scope.subscriptionExpireOptions[_t('app.shared.buttons.no')] = false;
|
||||
|
||||
// AngularUI-Bootstrap datepicker parameters to define when to refund
|
||||
$scope.datePicker = {
|
||||
@ -742,7 +742,7 @@ Application.Controllers.controller('AvoirModalController', ['$scope', '$uibModal
|
||||
}
|
||||
|
||||
if ($scope.avoir.invoice_items_ids.length === 0) {
|
||||
return growl.error(_t('invoices.you_must_select_at_least_one_element_to_create_a_refund'));
|
||||
return growl.error(_t('app.admin.invoices.you_must_select_at_least_one_element_to_create_a_refund'));
|
||||
} else {
|
||||
return Invoice.save(
|
||||
{ avoir: $scope.avoir },
|
||||
@ -750,7 +750,7 @@ Application.Controllers.controller('AvoirModalController', ['$scope', '$uibModal
|
||||
$uibModalInstance.close({ avoir, invoice: $scope.invoice });
|
||||
},
|
||||
function (err) { // failed
|
||||
growl.error(_t('invoices.unable_to_create_the_refund'));
|
||||
growl.error(_t('app.admin.invoices.unable_to_create_the_refund'));
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -791,7 +791,7 @@ Application.Controllers.controller('AvoirModalController', ['$scope', '$uibModal
|
||||
});
|
||||
|
||||
if (invoice.stripe) {
|
||||
return $scope.avoirModes.push({ name: _t('invoices.online_payment'), value: 'stripe' });
|
||||
return $scope.avoirModes.push({ name: _t('app.admin.invoices.online_payment'), value: 'stripe' });
|
||||
}
|
||||
};
|
||||
|
||||
@ -861,16 +861,16 @@ Application.Controllers.controller('ClosePeriodModalController', ['$scope', '$ui
|
||||
resolve: {
|
||||
object () {
|
||||
return {
|
||||
title: _t('invoices.confirmation_required'),
|
||||
title: _t('app.admin.invoices.confirmation_required'),
|
||||
msg: $sce.trustAsHtml(
|
||||
_t(
|
||||
'invoices.confirm_close_START_END',
|
||||
{ START: moment.utc($scope.period.start_at).format('LL'), END: moment.utc($scope.period.end_at).format('LL') }
|
||||
)
|
||||
+ '<br/><br/><strong>'
|
||||
+ _t('invoices.period_must_match_fiscal_year')
|
||||
+ _t('app.admin.invoices.period_must_match_fiscal_year')
|
||||
+ '</strong><br/><br/>'
|
||||
+ _t('invoices.this_may_take_a_while')
|
||||
+ _t('app.admin.invoices.this_may_take_a_while')
|
||||
)
|
||||
};
|
||||
}
|
||||
@ -895,7 +895,7 @@ Application.Controllers.controller('ClosePeriodModalController', ['$scope', '$ui
|
||||
},
|
||||
function(error) {
|
||||
$scope.pendingCreation = false;
|
||||
growl.error(_t('invoices.failed_to_close_period'));
|
||||
growl.error(_t('app.admin.invoices.failed_to_close_period'));
|
||||
$scope.errors = error.data;
|
||||
}
|
||||
);
|
||||
@ -982,7 +982,7 @@ Application.Controllers.controller('AccountingExportModalController', ['$scope',
|
||||
|
||||
Export.status(statusQry).then(function (res) {
|
||||
if (!res.data.exists) {
|
||||
growl.success(_t('invoices.export_is_running'));
|
||||
growl.success(_t('app.admin.invoices.export_is_running'));
|
||||
}
|
||||
$uibModalInstance.close(res);
|
||||
});
|
||||
|
@ -182,6 +182,35 @@ Application.Controllers.controller('AdminMembersController', ['$scope', '$sce',
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Ask for confirmation then delete the specified user
|
||||
* @param memberId {number} identifier of the user to delete
|
||||
*/
|
||||
$scope.deleteMember = function(memberId) {
|
||||
dialogs.confirm(
|
||||
{
|
||||
resolve: {
|
||||
object () {
|
||||
return {
|
||||
title: _t('app.admin.members.confirmation_required'),
|
||||
msg: $sce.trustAsHtml(_t('app.admin.members.confirm_delete_member') + '<br/><br/>' + _t('app.admin.members.this_may_take_a_while_please_wait'))
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
function () { // cancel confirmed
|
||||
Member.delete(
|
||||
{ id: memberId },
|
||||
function () {
|
||||
$scope.members.splice(findItemIdxById($scope.members, memberId), 1);
|
||||
return growl.success(_t('app.admin.members.member_successfully_deleted'));
|
||||
},
|
||||
function (error) { growl.error(_t('app.admin.members.unable_to_delete_the_member')); }
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask for confirmation then delete the specified administrator
|
||||
* @param admins {Array} full list of administrators
|
||||
@ -193,8 +222,8 @@ Application.Controllers.controller('AdminMembersController', ['$scope', '$sce',
|
||||
resolve: {
|
||||
object () {
|
||||
return {
|
||||
title: _t('confirmation_required'),
|
||||
msg: $sce.trustAsHtml(_t('do_you_really_want_to_delete_this_administrator_this_cannot_be_undone') + '<br/><br/>' + _t('this_may_take_a_while_please_wait'))
|
||||
title: _t('app.admin.members.confirmation_required'),
|
||||
msg: $sce.trustAsHtml(_t('app.admin.members.do_you_really_want_to_delete_this_administrator_this_cannot_be_undone') + '<br/><br/>' + _t('app.admin.members.this_may_take_a_while_please_wait'))
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -203,10 +232,10 @@ Application.Controllers.controller('AdminMembersController', ['$scope', '$sce',
|
||||
Admin.delete(
|
||||
{ id: admin.id },
|
||||
function () {
|
||||
admins.splice(findAdminIdxById(admins, admin.id), 1);
|
||||
return growl.success(_t('administrator_successfully_deleted'));
|
||||
admins.splice(findItemIdxById(admins, admin.id), 1);
|
||||
return growl.success(_t('app.admin.members.administrator_successfully_deleted'));
|
||||
},
|
||||
function (error) { growl.error(_t('unable_to_delete_the_administrator')); }
|
||||
function (error) { growl.error(_t('app.admin.members.unable_to_delete_the_administrator')); }
|
||||
);
|
||||
}
|
||||
);
|
||||
@ -239,7 +268,7 @@ Application.Controllers.controller('AdminMembersController', ['$scope', '$sce',
|
||||
$scope.alertExport = function (type) {
|
||||
Export.status({ category: 'users', type }).then(function (res) {
|
||||
if (!res.data.exists) {
|
||||
return growl.success(_t('export_is_running_you_ll_be_notified_when_its_ready'));
|
||||
return growl.success(_t('app.admin.members.export_is_running_you_ll_be_notified_when_its_ready'));
|
||||
}
|
||||
});
|
||||
};
|
||||
@ -261,13 +290,13 @@ Application.Controllers.controller('AdminMembersController', ['$scope', '$sce',
|
||||
var searchTimeout = null;
|
||||
|
||||
/**
|
||||
* Iterate through the provided array and return the index of the requested admin
|
||||
* @param admins {Array} full list of users with role 'admin'
|
||||
* @param id {Number} user id of the admin to retrieve in the list
|
||||
* @returns {Number} index of the requested admin, in the provided array
|
||||
* Iterate through the provided array and return the index of the requested item
|
||||
* @param items {Array} full list of users with role 'admin'
|
||||
* @param id {Number} id of the item to retrieve in the list
|
||||
* @returns {Number} index of the requested item, in the provided array
|
||||
*/
|
||||
var findAdminIdxById = function (admins, id) {
|
||||
return (admins.map(function (admin) { return admin.id; })).indexOf(id);
|
||||
var findItemIdxById = function (items, id) {
|
||||
return (items.map(function (item) { return item.id; })).indexOf(id);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -395,10 +424,10 @@ Application.Controllers.controller('EditMemberController', ['$scope', '$state',
|
||||
{ id: subscription.id },
|
||||
{ subscription: { expired_at: $scope.new_expired_at, free } },
|
||||
function (_subscription) {
|
||||
growl.success(_t('you_successfully_changed_the_expiration_date_of_the_user_s_subscription'));
|
||||
growl.success(_t('app.admin.members_edit.you_successfully_changed_the_expiration_date_of_the_user_s_subscription'));
|
||||
return $uibModalInstance.close(_subscription);
|
||||
},
|
||||
function (error) { growl.error(_t('a_problem_occurred_while_saving_the_date')); }
|
||||
function (error) { growl.error(_t('app.admin.members_edit.a_problem_occurred_while_saving_the_date')); }
|
||||
);
|
||||
};
|
||||
|
||||
@ -442,12 +471,12 @@ Application.Controllers.controller('EditMemberController', ['$scope', '$state',
|
||||
$scope.ok = function () {
|
||||
$scope.subscription.user_id = user.id;
|
||||
return Subscription.save({ }, { subscription: $scope.subscription }, function (_subscription) {
|
||||
growl.success(_t('subscription_successfully_purchased'));
|
||||
growl.success(_t('app.admin.members_edit.subscription_successfully_purchased'));
|
||||
$uibModalInstance.close(_subscription);
|
||||
return $state.reload();
|
||||
}
|
||||
, function (error) {
|
||||
growl.error(_t('a_problem_occurred_while_taking_the_subscription'));
|
||||
growl.error(_t('app.admin.members_edit.a_problem_occurred_while_taking_the_subscription'));
|
||||
console.error(error);
|
||||
});
|
||||
};
|
||||
@ -458,7 +487,7 @@ Application.Controllers.controller('EditMemberController', ['$scope', '$state',
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel'); };
|
||||
}]
|
||||
});
|
||||
// once the form was validated succesfully ...
|
||||
// once the form was validated successfully ...
|
||||
return modalInstance.result.then(function (subscription) { $scope.subscription = subscription; });
|
||||
};
|
||||
|
||||
@ -507,11 +536,11 @@ Application.Controllers.controller('EditMemberController', ['$scope', '$state',
|
||||
avoir_description: $scope.description
|
||||
},
|
||||
function (_wallet) {
|
||||
growl.success(_t('wallet_credit_successfully'));
|
||||
growl.success(_t('app.shared.wallet.wallet_credit_successfully'));
|
||||
return $uibModalInstance.close(_wallet);
|
||||
},
|
||||
function (error) {
|
||||
growl.error(_t('a_problem_occurred_for_wallet_credit'));
|
||||
growl.error(_t('app.shared.wallet.a_problem_occurred_for_wallet_credit'));
|
||||
console.error(error);
|
||||
}
|
||||
);
|
||||
@ -721,11 +750,12 @@ Application.Controllers.controller('NewAdminController', ['$state', '$scope', 'A
|
||||
{},
|
||||
{ admin: $scope.admin },
|
||||
function () {
|
||||
growl.success(_t('administrator_successfully_created_he_will_receive_his_connection_directives_by_email', { GENDER: getGender($scope.admin) }, 'messageformat'));
|
||||
growl.success(_t('app.admin.admins_new.administrator_successfully_created_he_will_receive_his_connection_directives_by_email', { GENDER: getGender($scope.admin) }));
|
||||
return $state.go('app.admin.members');
|
||||
}
|
||||
, function (error) {
|
||||
console.log(error);
|
||||
growl.error(_t('app.admin.admins_new.failed_to_create_admin') + JSON.stringify(error.data ? error.data : error));
|
||||
console.error(error);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
@ -37,12 +37,12 @@ Application.Controllers.controller('OpenAPIClientsController', ['$scope', 'clien
|
||||
if (client.id != null) {
|
||||
OpenAPIClient.update({ id: client.id }, { open_api_client: client }, function (clientResp) {
|
||||
client = clientResp;
|
||||
return growl.success(_t('client_successfully_updated'));
|
||||
return growl.success(_t('app.admin.open_api_clients.client_successfully_updated'));
|
||||
});
|
||||
} else {
|
||||
OpenAPIClient.save({ open_api_client: client }, function (client) {
|
||||
$scope.clients.push(client);
|
||||
return growl.success(_t('client_successfully_created'));
|
||||
return growl.success(_t('app.admin.open_api_clients.client_successfully_created'));
|
||||
});
|
||||
}
|
||||
|
||||
@ -61,8 +61,8 @@ Application.Controllers.controller('OpenAPIClientsController', ['$scope', 'clien
|
||||
resolve: {
|
||||
object () {
|
||||
return {
|
||||
title: _t('confirmation_required'),
|
||||
msg: _t('do_you_really_want_to_delete_this_open_api_client')
|
||||
title: _t('app.admin.open_api_clients.confirmation_required'),
|
||||
msg: _t('app.admin.open_api_clients.do_you_really_want_to_delete_this_open_api_client')
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -70,7 +70,7 @@ Application.Controllers.controller('OpenAPIClientsController', ['$scope', 'clien
|
||||
, () =>
|
||||
OpenAPIClient.delete({ id: $scope.clients[index].id }, function () {
|
||||
$scope.clients.splice(index, 1);
|
||||
return growl.success(_t('client_successfully_deleted'));
|
||||
return growl.success(_t('app.admin.open_api_clients.client_successfully_deleted'));
|
||||
})
|
||||
);
|
||||
|
||||
@ -79,8 +79,8 @@ Application.Controllers.controller('OpenAPIClientsController', ['$scope', 'clien
|
||||
resolve: {
|
||||
object () {
|
||||
return {
|
||||
title: _t('confirmation_required'),
|
||||
msg: _t('do_you_really_want_to_revoke_this_open_api_access')
|
||||
title: _t('app.admin.open_api_clients.confirmation_required'),
|
||||
msg: _t('app.admin.open_api_clients.do_you_really_want_to_revoke_this_open_api_access')
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -88,7 +88,7 @@ Application.Controllers.controller('OpenAPIClientsController', ['$scope', 'clien
|
||||
, () =>
|
||||
OpenAPIClient.resetToken({ id: client.id }, {}, function (clientResp) {
|
||||
client.token = clientResp.token;
|
||||
return growl.success(_t('access_successfully_revoked'));
|
||||
return growl.success(_t('app.admin.open_api_clients.access_successfully_revoked'));
|
||||
})
|
||||
);
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ Application.Controllers.controller('NewPlanController', ['$scope', '$uibModal',
|
||||
$uibModalInstance.close($scope.partner);
|
||||
},
|
||||
function (error) {
|
||||
growl.error(_t('new_plan.unable_to_save_this_user_check_that_there_isnt_an_already_a_user_with_the_same_name'));
|
||||
growl.error(_t('app.admin.plans.new.unable_to_save_this_user_check_that_there_isnt_an_already_a_user_with_the_same_name'));
|
||||
console.error(error);
|
||||
}
|
||||
);
|
||||
@ -143,9 +143,9 @@ Application.Controllers.controller('NewPlanController', ['$scope', '$uibModal',
|
||||
*/
|
||||
$scope.afterSubmit = function (content) {
|
||||
if ((content.id == null) && (content.plan_ids == null)) {
|
||||
return growl.error(_t('new_plan.unable_to_create_the_subscription_please_try_again'));
|
||||
return growl.error(_t('app.admin.plans.new.unable_to_create_the_subscription_please_try_again'));
|
||||
} else {
|
||||
growl.success(_t('new_plan.successfully_created_subscriptions_dont_forget_to_redefine_prices'));
|
||||
growl.success(_t('app.admin.plans.new.successfully_created_subscriptions_dont_forget_to_redefine_prices'));
|
||||
if (content.plan_ids != null) {
|
||||
return $state.go('app.admin.pricing');
|
||||
} else {
|
||||
@ -237,9 +237,9 @@ Application.Controllers.controller('EditPlanController', ['$scope', 'groups', 'p
|
||||
*/
|
||||
$scope.afterSubmit = function (content) {
|
||||
if ((content.id == null) && (content.plan_ids == null)) {
|
||||
return growl.error(_t('edit_plan.unable_to_save_subscription_changes_please_try_again'));
|
||||
return growl.error(_t('app.admin.plans.edit.unable_to_save_subscription_changes_please_try_again'));
|
||||
} else {
|
||||
growl.success(_t('edit_plan.subscription_successfully_changed'));
|
||||
growl.success(_t('app.admin.plans.edit.subscription_successfully_changed'));
|
||||
return $state.go('app.admin.pricing');
|
||||
}
|
||||
};
|
||||
|
@ -108,7 +108,7 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
if (data != null) {
|
||||
return TrainingsPricing.update({ id: trainingsPricing.id }, { trainings_pricing: { amount: data } }).$promise;
|
||||
} else {
|
||||
return _t('pricing.please_specify_a_number');
|
||||
return _t('app.admin.pricing.please_specify_a_number');
|
||||
}
|
||||
};
|
||||
|
||||
@ -146,7 +146,7 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
*/
|
||||
$scope.showTrainings = function (trainings) {
|
||||
if (!angular.isArray(trainings) || !(trainings.length > 0)) {
|
||||
return _t('pricing.none');
|
||||
return _t('app.admin.pricing.none');
|
||||
}
|
||||
|
||||
const selected = [];
|
||||
@ -155,7 +155,7 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
return selected.push(t.name);
|
||||
}
|
||||
});
|
||||
if (selected.length) { return selected.join(' | '); } else { return _t('pricing.none'); }
|
||||
if (selected.length) { return selected.join(' | '); } else { return _t('app.admin.pricing.none'); }
|
||||
};
|
||||
|
||||
/**
|
||||
@ -170,7 +170,7 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
{ training_credit_nb: newdata.training_credits }
|
||||
, angular.noop() // do nothing in case of success
|
||||
, function (error) {
|
||||
growl.error(_t('pricing.an_error_occurred_while_saving_the_number_of_credits'));
|
||||
growl.error(_t('app.admin.pricing.an_error_occurred_while_saving_the_number_of_credits'));
|
||||
console.error(error);
|
||||
}
|
||||
);
|
||||
@ -190,11 +190,11 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
return $scope.trainingCreditsGroups[planId].splice($scope.trainingCreditsGroups[planId].indexOf(tc.id), 1);
|
||||
}
|
||||
, function (error) {
|
||||
growl.error(_t('pricing.an_error_occurred_while_deleting_credit_with_the_TRAINING', { TRAINING: tc.creditable.name }));
|
||||
growl.error(_t('app.admin.pricing.an_error_occurred_while_deleting_credit_with_the_TRAINING', { TRAINING: tc.creditable.name }));
|
||||
console.error(error);
|
||||
});
|
||||
} else {
|
||||
return growl.error(_t('pricing.an_error_occurred_unable_to_find_the_credit_to_revoke'));
|
||||
return growl.error(_t('app.admin.pricing.an_error_occurred_unable_to_find_the_credit_to_revoke'));
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -215,7 +215,7 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
}
|
||||
, function (error) { // failed
|
||||
const training = getTrainingFromId(newTrainingId);
|
||||
growl.error(_t('pricing.an_error_occurred_while_creating_credit_with_the_TRAINING', { TRAINING: training.name }));
|
||||
growl.error(_t('app.admin.pricing.an_error_occurred_while_creating_credit_with_the_TRAINING', { TRAINING: training.name }));
|
||||
return console.error(error);
|
||||
});
|
||||
}
|
||||
@ -250,7 +250,7 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
* @returns {String}
|
||||
*/
|
||||
$scope.showCreditableName = function (credit) {
|
||||
let selected = _t('pricing.not_set');
|
||||
let selected = _t('app.admin.pricing.not_set');
|
||||
if (credit && credit.creditable_id) {
|
||||
const object = $scope.getCreditable(credit);
|
||||
selected = object.name;
|
||||
@ -295,7 +295,7 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
$scope.saveMachineCredit = function (data, id) {
|
||||
for (let mc of Array.from($scope.machineCredits)) {
|
||||
if ((mc.plan_id === data.plan_id) && (mc.creditable_id === data.creditable_id) && ((id === null) || (mc.id !== id))) {
|
||||
growl.error(_t('pricing.error_a_credit_linking_this_machine_with_that_subscription_already_exists'));
|
||||
growl.error(_t('app.admin.pricing.error_a_credit_linking_this_machine_with_that_subscription_already_exists'));
|
||||
if (!id) {
|
||||
$scope.machineCredits.pop();
|
||||
}
|
||||
@ -304,18 +304,18 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
}
|
||||
|
||||
if (id != null) {
|
||||
return Credit.update({ id }, { credit: data }, function () { growl.success(_t('pricing.changes_have_been_successfully_saved')); });
|
||||
return Credit.update({ id }, { credit: data }, function () { growl.success(_t('app.admin.pricing.changes_have_been_successfully_saved')); });
|
||||
} else {
|
||||
data.creditable_type = 'Machine';
|
||||
return Credit.save(
|
||||
{ credit: data }
|
||||
, function (resp) {
|
||||
$scope.machineCredits[$scope.machineCredits.length - 1].id = resp.id;
|
||||
return growl.success(_t('pricing.credit_was_successfully_saved'));
|
||||
return growl.success(_t('app.admin.pricing.credit_was_successfully_saved'));
|
||||
}
|
||||
, function (err) {
|
||||
$scope.machineCredits.pop();
|
||||
growl.error(_t('pricing.error_creating_credit'));
|
||||
growl.error(_t('app.admin.pricing.error_creating_credit'));
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
@ -365,7 +365,7 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
$scope.saveSpaceCredit = function (data, id) {
|
||||
for (let sc of Array.from($scope.spaceCredits)) {
|
||||
if ((sc.plan_id === data.plan_id) && (sc.creditable_id === data.creditable_id) && ((id === null) || (sc.id !== id))) {
|
||||
growl.error(_t('pricing.error_a_credit_linking_this_space_with_that_subscription_already_exists'));
|
||||
growl.error(_t('app.admin.pricing.error_a_credit_linking_this_space_with_that_subscription_already_exists'));
|
||||
if (!id) {
|
||||
$scope.spaceCredits.pop();
|
||||
}
|
||||
@ -374,18 +374,18 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
}
|
||||
|
||||
if (id != null) {
|
||||
return Credit.update({ id }, { credit: data }, function () { growl.success(_t('pricing.changes_have_been_successfully_saved')); });
|
||||
return Credit.update({ id }, { credit: data }, function () { growl.success(_t('app.admin.pricing.changes_have_been_successfully_saved')); });
|
||||
} else {
|
||||
data.creditable_type = 'Space';
|
||||
return Credit.save(
|
||||
{ credit: data }
|
||||
, function (resp) {
|
||||
$scope.spaceCredits[$scope.spaceCredits.length - 1].id = resp.id;
|
||||
return growl.success(_t('pricing.credit_was_successfully_saved'));
|
||||
return growl.success(_t('app.admin.pricing.credit_was_successfully_saved'));
|
||||
}
|
||||
, function (err) {
|
||||
$scope.spaceCredits.pop();
|
||||
return growl.error(_t('pricing.error_creating_credit'));
|
||||
return growl.error(_t('app.admin.pricing.error_creating_credit'));
|
||||
});
|
||||
}
|
||||
};
|
||||
@ -419,8 +419,8 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
*/
|
||||
$scope.getPlanType = function (type) {
|
||||
if (type === 'PartnerPlan') {
|
||||
return _t('pricing.partner');
|
||||
} else { return _t('pricing.standard'); }
|
||||
return _t('app.admin.pricing.partner');
|
||||
} else { return _t('app.admin.pricing.standard'); }
|
||||
};
|
||||
|
||||
/**
|
||||
@ -453,7 +453,7 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
if (data != null) {
|
||||
return Price.update({ id: price.id }, { price: { amount: data } }).$promise;
|
||||
} else {
|
||||
return _t('pricing.please_specify_a_number');
|
||||
return _t('app.admin.pricing.please_specify_a_number');
|
||||
}
|
||||
};
|
||||
|
||||
@ -471,8 +471,8 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
resolve: {
|
||||
object () {
|
||||
return {
|
||||
title: _t('pricing.confirmation_required'),
|
||||
msg: _t('pricing.do_you_really_want_to_delete_this_subscription_plan')
|
||||
title: _t('app.admin.pricing.confirmation_required'),
|
||||
msg: _t('app.admin.pricing.do_you_really_want_to_delete_this_subscription_plan')
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -482,12 +482,12 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
Plan.delete(
|
||||
{ id },
|
||||
function (res) {
|
||||
growl.success(_t('pricing.subscription_plan_was_successfully_deleted'));
|
||||
growl.success(_t('app.admin.pricing.subscription_plan_was_successfully_deleted'));
|
||||
return $scope.plans.splice(findItemIdxById(plans, id), 1);
|
||||
},
|
||||
function (error) {
|
||||
if (error.statusText) { console.error(`[EditPricingController::deletePlan] Error: ${error.statusText}`); }
|
||||
growl.error(_t('pricing.unable_to_delete_the_specified_subscription_an_error_occurred'));
|
||||
growl.error(_t('app.admin.pricing.unable_to_delete_the_specified_subscription_an_error_occurred'));
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -519,8 +519,8 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
resolve: {
|
||||
object () {
|
||||
return {
|
||||
title: _t('pricing.confirmation_required'),
|
||||
msg: _t('pricing.do_you_really_want_to_delete_this_coupon')
|
||||
title: _t('app.admin.pricing.confirmation_required'),
|
||||
msg: _t('app.admin.pricing.do_you_really_want_to_delete_this_coupon')
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -528,16 +528,16 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
, function () {
|
||||
// the admin has confirmed, delete the coupon
|
||||
Coupon.delete({ id }, function (res) {
|
||||
growl.success(_t('coupon_was_successfully_deleted'));
|
||||
growl.success(_t('app.admin.pricing.coupon_was_successfully_deleted'));
|
||||
return $scope.coupons.splice(findItemIdxById(coupons, id), 1);
|
||||
}
|
||||
|
||||
, function (error) {
|
||||
if (error.statusText) { console.error(`[EditPricingController::deleteCoupon] Error: ${error.statusText}`); }
|
||||
if (error.status === 422) {
|
||||
return growl.error(_t('pricing.unable_to_delete_the_specified_coupon_already_in_use'));
|
||||
return growl.error(_t('app.admin.pricing.unable_to_delete_the_specified_coupon_already_in_use'));
|
||||
} else {
|
||||
return growl.error(_t('pricing.unable_to_delete_the_specified_coupon_an_unexpected_error_occurred'));
|
||||
return growl.error(_t('app.admin.pricing.unable_to_delete_the_specified_coupon_an_unexpected_error_occurred'));
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -566,11 +566,11 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
// Callback to validate sending of the coupon
|
||||
$scope.ok = function () {
|
||||
Coupon.send({ coupon_code: coupon.code, user_id: $scope.ctrl.member.id }, function (res) {
|
||||
growl.success(_t('pricing.coupon_successfully_sent_to_USER', { USER: $scope.ctrl.member.name }));
|
||||
growl.success(_t('app.admin.pricing.coupon_successfully_sent_to_USER', { USER: $scope.ctrl.member.name }));
|
||||
return $uibModalInstance.close({ user_id: $scope.ctrl.member.id });
|
||||
}
|
||||
, function (err) {
|
||||
growl.error(_t('pricing.an_error_occurred_unable_to_send_the_coupon'));
|
||||
growl.error(_t('app.admin.pricing.an_error_occurred_unable_to_send_the_coupon'));
|
||||
console.error(err);
|
||||
});
|
||||
};
|
||||
|
@ -166,7 +166,7 @@ Application.Controllers.controller('SettingsController', ['$scope', '$filter', '
|
||||
Setting.update(
|
||||
{ name: setting.name },
|
||||
{ value },
|
||||
function () { growl.success(_t('settings.customization_of_SETTING_successfully_saved', { SETTING: _t(`settings.${setting.name}`) })); },
|
||||
function () { growl.success(_t('app.admin.settings.customization_of_SETTING_successfully_saved', { SETTING: _t(`app.admin.settings.${setting.name}`) })); },
|
||||
function (error) { console.log(error); }
|
||||
);
|
||||
};
|
||||
@ -191,7 +191,7 @@ Application.Controllers.controller('SettingsController', ['$scope', '$filter', '
|
||||
// reset history
|
||||
$scope.privacyDraftsHistory = [];
|
||||
data.setting.history.forEach(function (draft) {
|
||||
$scope.privacyDraftsHistory.push({ id: draft.id, name: _t('settings.privacy.draft_from_USER_DATE', { USER: draft.user.name, DATE: draft.created_at }), content: draft.value });
|
||||
$scope.privacyDraftsHistory.push({ id: draft.id, name: _t('app.admin.settings.privacy.draft_from_USER_DATE', { USER: draft.user.name, DATE: draft.created_at }), content: draft.value });
|
||||
});
|
||||
if (type === 'privacy_draft') {
|
||||
const orderedHistory = $filter('orderBy')(data.setting.history, 'created_at');
|
||||
@ -219,7 +219,7 @@ Application.Controllers.controller('SettingsController', ['$scope', '$filter', '
|
||||
angular.forEach(v, function(err) { growl.error(err); })
|
||||
});
|
||||
} else {
|
||||
growl.success(_t('settings.file_successfully_updated'));
|
||||
growl.success(_t('app.admin.settings.file_successfully_updated'));
|
||||
if (content.custom_asset.name === 'cgu-file') {
|
||||
$scope.cguFile = content.custom_asset;
|
||||
$scope.methods.cgu = 'put';
|
||||
@ -316,7 +316,7 @@ Application.Controllers.controller('SettingsController', ['$scope', '$filter', '
|
||||
}
|
||||
|
||||
privacyDraftsPromise.setting.history.forEach(function (draft) {
|
||||
$scope.privacyDraftsHistory.push({ id: draft.id, name: _t('settings.privacy.draft_from_USER_DATE', { USER: draft.user.name, DATE: moment(draft.created_at).format('L LT') }), content: draft.value });
|
||||
$scope.privacyDraftsHistory.push({ id: draft.id, name: _t('app.admin.settings.privacy.draft_from_USER_DATE', { USER: draft.user.name, DATE: moment(draft.created_at).format('L LT') }), content: draft.value });
|
||||
});
|
||||
};
|
||||
|
||||
@ -347,7 +347,7 @@ Application.Controllers.controller('SavePolicyController', ['$scope', '$uibModal
|
||||
*/
|
||||
$scope.publish = function () {
|
||||
saveCb({ name: 'privacy_body', value: privacyPolicy.bodyTemp });
|
||||
growl.info(_t('settings.privacy.users_notified'));
|
||||
growl.info(_t('app.admin.settings.privacy.users_notified'));
|
||||
$uibModalInstance.close('privacy_body');
|
||||
};
|
||||
/**
|
||||
|
@ -130,6 +130,13 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a localized name for the given field
|
||||
*/
|
||||
$scope.customFieldName = function (field) {
|
||||
return _t(`app.admin.statistics.${field}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to open the datepicker (interval start)
|
||||
* @param $event {Object} jQuery event object
|
||||
@ -215,10 +222,10 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
*/
|
||||
$scope.formatSex = function (sex) {
|
||||
if (sex === 'male') {
|
||||
return _t('man');
|
||||
return _t('app.admin.statistics.man');
|
||||
}
|
||||
if (sex === 'female') {
|
||||
return _t('woman');
|
||||
return _t('app.admin.statistics.woman');
|
||||
}
|
||||
};
|
||||
|
||||
@ -397,7 +404,7 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
};
|
||||
|
||||
/**
|
||||
* Run the elasticSearch query to retreive the /stats/type aggregations
|
||||
* Run the elasticSearch query to retrieve the /stats/type aggregations
|
||||
* @param index {String} elasticSearch document type (account|event|machine|project|subscription|training)
|
||||
* @param type {String} statistics type (month|year|booking|hour|user|project)
|
||||
* @param custom {{key:{string}, value:{string}}|null} custom filter property or null to disable this filter
|
||||
@ -552,17 +559,17 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
};
|
||||
|
||||
/**
|
||||
* Fullfil the list of available options in the custom filter panel. The list will be based on common
|
||||
* Fulfill the list of available options in the custom filter panel. The list will be based on common
|
||||
* properties and on index-specific properties (additional_fields)
|
||||
*/
|
||||
var buildCustomFiltersList = function () {
|
||||
$scope.filters = [
|
||||
{ key: 'date', label: _t('date'), values: ['input_date'] },
|
||||
{ key: 'userId', label: _t('user_id'), values: ['input_number'] },
|
||||
{ key: 'gender', label: _t('gender'), values: [{ key: 'male', label: _t('man') }, { key: 'female', label: _t('woman') }] },
|
||||
{ key: 'age', label: _t('age'), values: ['input_number'] },
|
||||
{ key: 'subType', label: _t('type'), values: $scope.type.active.subtypes },
|
||||
{ key: 'ca', label: _t('revenue'), values: ['input_number'] }
|
||||
{ key: 'date', label: _t('app.admin.statistics.date'), values: ['input_date'] },
|
||||
{ key: 'userId', label: _t('app.admin.statistics.user_id'), values: ['input_number'] },
|
||||
{ key: 'gender', label: _t('app.admin.statistics.gender'), values: [{ key: 'male', label: _t('app.admin.statistics.man') }, { key: 'female', label: _t('app.admin.statistics.woman') }] },
|
||||
{ key: 'age', label: _t('app.admin.statistics.age'), values: ['input_number'] },
|
||||
{ key: 'subType', label: _t('app.admin.statistics.type'), values: $scope.type.active.subtypes },
|
||||
{ key: 'ca', label: _t('app.admin.statistics.revenue'), values: ['input_number'] }
|
||||
];
|
||||
|
||||
if (!$scope.type.active.simple) {
|
||||
@ -709,7 +716,7 @@ Application.Controllers.controller('ExportStatisticsController', [ '$scope', '$u
|
||||
|
||||
Export.status(statusQry).then(function (res) {
|
||||
if (!res.data.exists) {
|
||||
return growl.success(_t('export_is_running_you_ll_be_notified_when_its_ready'));
|
||||
return growl.success(_t('app.admin.statistics.export_is_running_you_ll_be_notified_when_its_ready'));
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
Application.Controllers.controller('TagsController', ['$scope', 'tagsPromise', 'Tag', 'growl', '_t', function ($scope, tagsPromise, Tag, growl, _t) {
|
||||
Application.Controllers.controller('TagsController', ['$scope', 'tagsPromise', 'Tag', 'dialogs', 'growl', '_t', function ($scope, tagsPromise, Tag, dialogs, growl, _t) {
|
||||
// List of users's tags
|
||||
$scope.tags = tagsPromise;
|
||||
|
||||
@ -44,15 +44,15 @@ Application.Controllers.controller('TagsController', ['$scope', 'tagsPromise', '
|
||||
*/
|
||||
$scope.saveTag = function (data, id) {
|
||||
if (id != null) {
|
||||
return Tag.update({ id }, { tag: data }, response => growl.success(_t('changes_successfully_saved'))
|
||||
, error => growl.error(_t('an_error_occurred_while_saving_changes')));
|
||||
return Tag.update({ id }, { tag: data }, response => growl.success(_t('app.admin.members.tag_form.changes_successfully_saved'))
|
||||
, error => growl.error(_t('app.admin.members.tag_form.an_error_occurred_while_saving_changes')));
|
||||
} else {
|
||||
return Tag.save({ tag: data }, function (resp) {
|
||||
growl.success(_t('new_tag_successfully_saved'));
|
||||
growl.success(_t('app.admin.members.tag_form.new_tag_successfully_saved'));
|
||||
return $scope.tags[$scope.tags.length - 1].id = resp.id;
|
||||
}
|
||||
, function (error) {
|
||||
growl.error(_t('an_error_occurred_while_saving_the_new_tag'));
|
||||
growl.error(_t('app.admin.members.tag_form.an_error_occurred_while_saving_the_new_tag'));
|
||||
return $scope.tags.splice($scope.tags.length - 1, 1);
|
||||
});
|
||||
}
|
||||
@ -62,13 +62,24 @@ Application.Controllers.controller('TagsController', ['$scope', 'tagsPromise', '
|
||||
* Deletes the tag at the specified index
|
||||
* @param index {number} tag index in the $scope.tags array
|
||||
*/
|
||||
return $scope.removeTag = index =>
|
||||
// TODO add confirmation : les utilisateurs seront déasociés
|
||||
$scope.removeTag = index =>
|
||||
dialogs.confirm({
|
||||
resolve: {
|
||||
object () {
|
||||
return {
|
||||
title: _t('app.admin.members.tag_form.confirmation_required'),
|
||||
msg: _t('app.admin.members.tag_form.confirm_delete_tag_html')
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
, () => {
|
||||
Tag.delete({ id: $scope.tags[index].id }, function (resp) {
|
||||
growl.success(_t('tag_successfully_deleted'));
|
||||
growl.success(_t('app.admin.members.tag_form.tag_successfully_deleted'));
|
||||
return $scope.tags.splice(index, 1);
|
||||
}
|
||||
, error => growl.error(_t('an_error_occurred_and_the_tag_deletion_failed')));
|
||||
, error => growl.error(_t('app.admin.members.tag_form.an_error_occurred_and_the_tag_deletion_failed')));
|
||||
});
|
||||
}
|
||||
|
||||
]);
|
||||
|
@ -196,7 +196,7 @@ Application.Controllers.controller('TrainingsAdminController', ['$scope', '$stat
|
||||
return selected.push(m.name);
|
||||
}
|
||||
});
|
||||
if (selected.length) { return selected.join(', '); } else { return _t('none'); }
|
||||
if (selected.length) { return selected.join(', '); } else { return _t('app.admin.trainings.none'); }
|
||||
};
|
||||
|
||||
/**
|
||||
@ -276,8 +276,8 @@ Application.Controllers.controller('TrainingsAdminController', ['$scope', '$stat
|
||||
resolve: {
|
||||
object () {
|
||||
return {
|
||||
title: _t('confirmation_required'),
|
||||
msg: _t('do_you_really_want_to_delete_this_training')
|
||||
title: _t('app.admin.trainings.confirmation_required'),
|
||||
msg: _t('app.admin.trainings.do_you_really_want_to_delete_this_training')
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -285,10 +285,10 @@ Application.Controllers.controller('TrainingsAdminController', ['$scope', '$stat
|
||||
function () { // deletion confirmed
|
||||
training.$delete(function () {
|
||||
$scope.trainings.splice(index, 1);
|
||||
growl.info(_t('training_successfully_deleted'));
|
||||
growl.info(_t('app.admin.trainings.training_successfully_deleted'));
|
||||
},
|
||||
function (error) {
|
||||
growl.warning(_t('unable_to_delete_the_training_because_some_users_alredy_booked_it'));
|
||||
growl.warning(_t('app.admin.trainings.unable_to_delete_the_training_because_some_users_already_booked_it'));
|
||||
console.error(error);
|
||||
});
|
||||
}
|
||||
|
@ -149,7 +149,7 @@ Application.Controllers.controller('ApplicationController', ['$rootScope', '$sco
|
||||
$uibModalInstance.close(user);
|
||||
} else {
|
||||
// the user was not saved in database, something wrong occurred
|
||||
growl.error(_t('unexpected_error_occurred'));
|
||||
growl.error(_t('app.public.common.unexpected_error_occurred'));
|
||||
}
|
||||
}, function (error) {
|
||||
// creation failed...
|
||||
@ -204,7 +204,7 @@ Application.Controllers.controller('ApplicationController', ['$rootScope', '$sco
|
||||
};
|
||||
}]
|
||||
}).result['finally'](null).then(function () {
|
||||
growl.success(_t('your_password_was_successfully_changed'));
|
||||
growl.success(_t('app.public.common.your_password_was_successfully_changed'));
|
||||
return Auth.login().then(function (user) {
|
||||
$scope.setCurrentUser(user);
|
||||
}, function (error) {
|
||||
@ -325,7 +325,7 @@ Application.Controllers.controller('ApplicationController', ['$rootScope', '$sco
|
||||
angular.forEach(notifications.notifications, function (n) { toDisplay.push(n); });
|
||||
|
||||
if (toDisplay.length < notifications.totals.unread) {
|
||||
toDisplay.push({ message: { description: _t('and_NUMBER_other_notifications', { NUMBER: notifications.totals.unread - toDisplay.length }, 'messageformat') } });
|
||||
toDisplay.push({ message: { description: _t('app.public.common.and_NUMBER_other_notifications', { NUMBER: notifications.totals.unread - toDisplay.length }) } });
|
||||
}
|
||||
|
||||
angular.forEach(toDisplay, function (notification) { growl.info(notification.message.description); });
|
||||
@ -375,7 +375,7 @@ Application.Controllers.controller('ApplicationController', ['$rootScope', '$sco
|
||||
console.error(`Authentication failed: ${JSON.stringify(error)}`);
|
||||
$scope.alerts = [];
|
||||
return $scope.alerts.push({
|
||||
msg: _t('wrong_email_or_password'),
|
||||
msg: _t('app.public.common.wrong_email_or_password'),
|
||||
type: 'danger'
|
||||
});
|
||||
});
|
||||
@ -418,13 +418,13 @@ Application.Controllers.controller('ApplicationController', ['$rootScope', '$sco
|
||||
$scope.alerts = [];
|
||||
return $http.post('/users/password.json', { user: $scope.user }).then(function () { $uibModalInstance.close(); }).catch(function () {
|
||||
$scope.alerts.push({
|
||||
msg: _t('your_email_address_is_unknown'),
|
||||
msg: _t('app.public.common.your_email_address_is_unknown'),
|
||||
type: 'danger'
|
||||
});
|
||||
});
|
||||
};
|
||||
}]
|
||||
}).result['finally'](null).then(function () { growl.info(_t('you_will_receive_in_a_moment_an_email_with_instructions_to_reset_your_password')); });
|
||||
}).result['finally'](null).then(function () { growl.info(_t('app.public.common.you_will_receive_in_a_moment_an_email_with_instructions_to_reset_your_password')); });
|
||||
}
|
||||
});
|
||||
// otherwise the user just closed the modal
|
||||
|
@ -16,8 +16,8 @@
|
||||
* Controller used in the public calendar global
|
||||
*/
|
||||
|
||||
Application.Controllers.controller('CalendarController', ['$scope', '$state', '$aside', 'moment', 'Availability', 'Slot', 'Setting', 'growl', 'dialogs', 'bookingWindowStart', 'bookingWindowEnd', '_t', 'uiCalendarConfig', 'CalendarConfig', 'trainingsPromise', 'machinesPromise', 'spacesPromise',
|
||||
function ($scope, $state, $aside, moment, Availability, Slot, Setting, growl, dialogs, bookingWindowStart, bookingWindowEnd, _t, uiCalendarConfig, CalendarConfig, trainingsPromise, machinesPromise, spacesPromise) {
|
||||
Application.Controllers.controller('CalendarController', ['$scope', '$state', '$aside', 'moment', 'Availability', 'Slot', 'Setting', 'growl', 'dialogs', 'bookingWindowStart', 'bookingWindowEnd', '_t', 'uiCalendarConfig', 'CalendarConfig', 'trainingsPromise', 'machinesPromise', 'spacesPromise', 'iCalendarPromise',
|
||||
function ($scope, $state, $aside, moment, Availability, Slot, Setting, growl, dialogs, bookingWindowStart, bookingWindowEnd, _t, uiCalendarConfig, CalendarConfig, trainingsPromise, machinesPromise, spacesPromise, iCalendarPromise) {
|
||||
/* PRIVATE STATIC CONSTANTS */
|
||||
let currentMachineEvent = null;
|
||||
machinesPromise.forEach(m => m.checked = true);
|
||||
@ -38,6 +38,9 @@ Application.Controllers.controller('CalendarController', ['$scope', '$state', '$
|
||||
// List of spaces
|
||||
$scope.spaces = spacesPromise.filter(t => !t.disabled);
|
||||
|
||||
// List of external iCalendar sources
|
||||
$scope.externals = iCalendarPromise.map(e => Object.assign(e, { checked: true }));
|
||||
|
||||
// add availabilities source to event sources
|
||||
$scope.eventSources = [];
|
||||
|
||||
@ -48,10 +51,41 @@ Application.Controllers.controller('CalendarController', ['$scope', '$state', '$
|
||||
trainings: isSelectAll('trainings', scope),
|
||||
machines: isSelectAll('machines', scope),
|
||||
spaces: isSelectAll('spaces', scope),
|
||||
externals: isSelectAll('externals', scope),
|
||||
evt: filter.evt,
|
||||
dispo: filter.dispo
|
||||
});
|
||||
return $scope.calendarConfig.events = availabilitySourceUrl();
|
||||
$scope.calendarConfig.events = availabilitySourceUrl();
|
||||
// external iCalendar events sources
|
||||
$scope.externals.forEach(e => {
|
||||
if (e.checked) {
|
||||
if (!$scope.eventSources.some(evt => evt.id === e.id)) {
|
||||
$scope.eventSources.push({
|
||||
id: e.id,
|
||||
url: `/api/i_calendar/${e.id}/events`,
|
||||
textColor: e.text_color || '#000',
|
||||
color: e.color
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if ($scope.eventSources.some(evt => evt.id === e.id)) {
|
||||
const idx = $scope.eventSources.findIndex(evt => evt.id === e.id);
|
||||
$scope.eventSources.splice(idx, 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
uiCalendarConfig.calendars.calendar.fullCalendar('refetchEventSources');
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a CSS-like style of the given calendar configuration
|
||||
* @param calendar
|
||||
*/
|
||||
$scope.calendarStyle = function (calendar) {
|
||||
return {
|
||||
'border-color': calendar.color,
|
||||
'color': calendar.text_color
|
||||
};
|
||||
};
|
||||
|
||||
// a variable for formation/machine/event/dispo checkbox is or not checked
|
||||
@ -59,6 +93,7 @@ Application.Controllers.controller('CalendarController', ['$scope', '$state', '$
|
||||
trainings: isSelectAll('trainings', $scope),
|
||||
machines: isSelectAll('machines', $scope),
|
||||
spaces: isSelectAll('spaces', $scope),
|
||||
externals: isSelectAll('externals', $scope),
|
||||
evt: true,
|
||||
dispo: true
|
||||
};
|
||||
@ -85,6 +120,9 @@ Application.Controllers.controller('CalendarController', ['$scope', '$state', '$
|
||||
spaces () {
|
||||
return $scope.spaces;
|
||||
},
|
||||
externals () {
|
||||
return $scope.externals;
|
||||
},
|
||||
filter () {
|
||||
return $scope.filter;
|
||||
},
|
||||
@ -95,10 +133,11 @@ Application.Controllers.controller('CalendarController', ['$scope', '$state', '$
|
||||
return $scope.filterAvailabilities;
|
||||
}
|
||||
},
|
||||
controller: ['$scope', '$uibModalInstance', 'trainings', 'machines', 'spaces', 'filter', 'toggleFilter', 'filterAvailabilities', function ($scope, $uibModalInstance, trainings, machines, spaces, filter, toggleFilter, filterAvailabilities) {
|
||||
controller: ['$scope', '$uibModalInstance', 'trainings', 'machines', 'spaces', 'externals', 'filter', 'toggleFilter', 'filterAvailabilities', function ($scope, $uibModalInstance, trainings, machines, spaces, externals, filter, toggleFilter, filterAvailabilities) {
|
||||
$scope.trainings = trainings;
|
||||
$scope.machines = machines;
|
||||
$scope.spaces = spaces;
|
||||
$scope.externals = externals;
|
||||
$scope.filter = filter;
|
||||
|
||||
$scope.toggleFilter = (type, filter) => toggleFilter(type, filter);
|
||||
@ -114,25 +153,66 @@ Application.Controllers.controller('CalendarController', ['$scope', '$state', '$
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = () => {
|
||||
// fullCalendar (v2) configuration
|
||||
$scope.calendarConfig = CalendarConfig({
|
||||
events: availabilitySourceUrl(),
|
||||
slotEventOverlap: true,
|
||||
header: {
|
||||
left: 'month agendaWeek agendaDay',
|
||||
center: 'title',
|
||||
right: 'today prev,next'
|
||||
},
|
||||
minTime: moment.duration(moment(bookingWindowStart.setting.value).format('HH:mm:ss')),
|
||||
maxTime: moment.duration(moment(bookingWindowEnd.setting.value).format('HH:mm:ss')),
|
||||
defaultView: window.innerWidth <= 480 ? 'agendaDay' : 'agendaWeek',
|
||||
eventClick (event, jsEvent, view) {
|
||||
return calendarEventClickCb(event, jsEvent, view);
|
||||
},
|
||||
viewRender (view, element) {
|
||||
return viewRenderCb(view, element);
|
||||
},
|
||||
eventRender (event, element, view) {
|
||||
return eventRenderCb(event, element);
|
||||
}
|
||||
});
|
||||
$scope.externals.forEach(e => {
|
||||
if (e.checked) {
|
||||
$scope.eventSources.push({
|
||||
id: e.id,
|
||||
url: `/api/i_calendar/${e.id}/events`,
|
||||
textColor: e.text_color || '#000',
|
||||
color: e.color
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback triggered when an event object is clicked in the fullCalendar view
|
||||
*/
|
||||
const calendarEventClickCb = function (event, jsEvent, view) {
|
||||
// current calendar object
|
||||
const { calendar } = uiCalendarConfig.calendars;
|
||||
if (event.available_type === 'machines') {
|
||||
currentMachineEvent = event;
|
||||
calendar.fullCalendar('changeView', 'agendaDay');
|
||||
return calendar.fullCalendar('gotoDate', event.start);
|
||||
calendar.fullCalendar('gotoDate', event.start);
|
||||
} else if (event.available_type === 'space') {
|
||||
calendar.fullCalendar('changeView', 'agendaDay');
|
||||
return calendar.fullCalendar('gotoDate', event.start);
|
||||
calendar.fullCalendar('gotoDate', event.start);
|
||||
} else if (event.available_type === 'event') {
|
||||
return $state.go('app.public.events_show', { id: event.event_id });
|
||||
$state.go('app.public.events_show', { id: event.event_id });
|
||||
} else if (event.available_type === 'training') {
|
||||
return $state.go('app.public.training_show', { id: event.training_id });
|
||||
$state.go('app.public.training_show', { id: event.training_id });
|
||||
} else {
|
||||
if (event.machine_id) {
|
||||
return $state.go('app.public.machines_show', { id: event.machine_id });
|
||||
$state.go('app.public.machines_show', { id: event.machine_id });
|
||||
} else if (event.space_id) {
|
||||
return $state.go('app.public.space_show', { id: event.space_id });
|
||||
$state.go('app.public.space_show', { id: event.space_id });
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -156,7 +236,10 @@ Application.Controllers.controller('CalendarController', ['$scope', '$state', '$
|
||||
}
|
||||
};
|
||||
|
||||
// function is called when calendar view is rendered or changed
|
||||
/**
|
||||
* This function is called when calendar view is rendered or changed
|
||||
* @see https://fullcalendar.io/docs/v3/viewRender#v2
|
||||
*/
|
||||
const viewRenderCb = function (view, element) {
|
||||
toggleSlotEventOverlap(view);
|
||||
if (view.type === 'agendaDay') {
|
||||
@ -165,8 +248,12 @@ Application.Controllers.controller('CalendarController', ['$scope', '$state', '$
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback triggered by fullCalendar when it is about to render an event.
|
||||
* @see https://fullcalendar.io/docs/v3/eventRender#v2
|
||||
*/
|
||||
const eventRenderCb = function (event, element) {
|
||||
if (event.tags.length > 0) {
|
||||
if (event.tags && event.tags.length > 0) {
|
||||
let html = '';
|
||||
for (let tag of Array.from(event.tags)) {
|
||||
html += `<span class='label label-success text-white'>${tag.name}</span> `;
|
||||
@ -184,30 +271,6 @@ Application.Controllers.controller('CalendarController', ['$scope', '$state', '$
|
||||
|
||||
var availabilitySourceUrl = () => `/api/availabilities/public?${$.param(getFilter())}`;
|
||||
|
||||
const initialize = () =>
|
||||
// fullCalendar (v2) configuration
|
||||
$scope.calendarConfig = CalendarConfig({
|
||||
events: availabilitySourceUrl(),
|
||||
slotEventOverlap: true,
|
||||
header: {
|
||||
left: 'month agendaWeek agendaDay',
|
||||
center: 'title',
|
||||
right: 'today prev,next'
|
||||
},
|
||||
minTime: moment.duration(moment(bookingWindowStart.setting.value).format('HH:mm:ss')),
|
||||
maxTime: moment.duration(moment(bookingWindowEnd.setting.value).format('HH:mm:ss')),
|
||||
defaultView: window.innerWidth <= 480 ? 'agendaDay' : 'agendaWeek',
|
||||
eventClick (event, jsEvent, view) {
|
||||
return calendarEventClickCb(event, jsEvent, view);
|
||||
},
|
||||
viewRender (view, element) {
|
||||
return viewRenderCb(view, element);
|
||||
},
|
||||
eventRender (event, element, view) {
|
||||
return eventRenderCb(event, element);
|
||||
}
|
||||
});
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize();
|
||||
}
|
||||
|
@ -126,13 +126,16 @@ Application.Controllers.controller('EventsController', ['$scope', '$state', 'Eve
|
||||
}
|
||||
]);
|
||||
|
||||
Application.Controllers.controller('ShowEventController', ['$scope', '$state', '$stateParams', '$rootScope', 'Event', '$uibModal', 'Member', 'Reservation', 'Price', 'CustomAsset', 'eventPromise', 'growl', '_t', 'Wallet', 'helpers', 'dialogs', 'priceCategoriesPromise', 'settingsPromise',
|
||||
function ($scope, $state, $stateParams, $rootScope, Event, $uibModal, Member, Reservation, Price, CustomAsset, eventPromise, growl, _t, Wallet, helpers, dialogs, priceCategoriesPromise, settingsPromise) {
|
||||
Application.Controllers.controller('ShowEventController', ['$scope', '$state', '$stateParams', '$rootScope', 'Event', '$uibModal', 'Member', 'Reservation', 'Price', 'CustomAsset', 'Slot', 'eventPromise', 'growl', '_t', 'Wallet', 'helpers', 'dialogs', 'priceCategoriesPromise', 'settingsPromise',
|
||||
function ($scope, $state, $stateParams, $rootScope, Event, $uibModal, Member, Reservation, Price, CustomAsset, Slot, eventPromise, growl, _t, Wallet, helpers, dialogs, priceCategoriesPromise, settingsPromise) {
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// reservations for the currently shown event
|
||||
$scope.reservations = [];
|
||||
|
||||
// current date & time
|
||||
$scope.now = moment();
|
||||
|
||||
// user to deal with
|
||||
$scope.ctrl =
|
||||
{ member: {} };
|
||||
@ -166,6 +169,12 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
// Global config: delay in hours before a booking while changing the booking slot is forbidden
|
||||
$scope.moveBookingDelay = parseInt(settingsPromise.booking_move_delay);
|
||||
|
||||
// Global config: is the user authorized to cancel his booking slots?
|
||||
$scope.enableBookingCancel = settingsPromise.booking_cancel_enable === 'true';
|
||||
|
||||
// Global config: delay in hours from now when restrictions occurs about cancelling reservations
|
||||
$scope.cancelBookingDelay = parseInt(settingsPromise.booking_cancel_delay);
|
||||
|
||||
// Message displayed to the end user about rules that applies to events reservations
|
||||
$scope.eventExplicationsAlert = settingsPromise.event_explications_alert;
|
||||
|
||||
@ -178,8 +187,8 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
resolve: {
|
||||
object () {
|
||||
return {
|
||||
title: _t('confirmation_required'),
|
||||
msg: _t('do_you_really_want_to_delete_this_event')
|
||||
title: _t('app.public.events_show.confirmation_required'),
|
||||
msg: _t('app.public.events_show.do_you_really_want_to_delete_this_event')
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -187,10 +196,10 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
// the admin has confirmed, delete
|
||||
event.$delete(function () {
|
||||
$state.go('app.public.events_list');
|
||||
return growl.info(_t('event_successfully_deleted'));
|
||||
return growl.info(_t('app.public.events_show.event_successfully_deleted'));
|
||||
}, function (error) {
|
||||
console.error(error);
|
||||
growl.error(_t('unable_to_delete_the_event_because_some_users_alredy_booked_it'));
|
||||
growl.error(_t('app.public.events_show.unable_to_delete_the_event_because_some_users_alredy_booked_it'));
|
||||
});
|
||||
}
|
||||
);
|
||||
@ -279,7 +288,7 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
const amountToPay = helpers.getAmountToPay($scope.reserve.amountTotal, wallet.amount);
|
||||
if (($scope.currentUser.role !== 'admin') && (amountToPay > 0)) {
|
||||
if ($rootScope.fablabWithoutOnlinePayment) {
|
||||
growl.error(_t('online_payment_disabled'));
|
||||
growl.error(_t('app.public.events_show.online_payment_disabled'));
|
||||
} else {
|
||||
return payByStripe(reservation);
|
||||
}
|
||||
@ -291,7 +300,7 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
});
|
||||
} else {
|
||||
// otherwise we alert, this error musn't occur when the current user is not admin
|
||||
return growl.error(_t('please_select_a_member_first'));
|
||||
return growl.error(_t('app.public.events_show.please_select_a_member_first'));
|
||||
}
|
||||
};
|
||||
|
||||
@ -341,16 +350,50 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to cancel a reservation
|
||||
* @param reservation {{id:number, reservable_id:number, nb_reserve_places:number}}
|
||||
*/
|
||||
$scope.cancelReservation = function(reservation) {
|
||||
dialogs.confirm({
|
||||
resolve: {
|
||||
object: function() {
|
||||
return {
|
||||
title: _t('app.public.events_show.cancel_the_reservation'),
|
||||
msg: _t('app.public.events_show.do_you_really_want_to_cancel_this_reservation_this_apply_to_all_booked_tickets')
|
||||
};
|
||||
}
|
||||
}
|
||||
}, function() { // cancel confirmed
|
||||
Slot.cancel({
|
||||
id: reservation.slots[0].id
|
||||
}, function() { // successfully canceled
|
||||
let index;
|
||||
growl.success(_t('app.public.events_show.reservation_was_successfully_cancelled'));
|
||||
index = $scope.reservations.indexOf(reservation);
|
||||
$scope.event.nb_free_places = $scope.event.nb_free_places + reservation.total_booked_seats;
|
||||
$scope.reservations[index].slots[0].canceled_at = new Date();
|
||||
}, function(error) {
|
||||
growl.warning(_t('app.public.events_show.cancellation_failed'));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Test if the provided reservation has been cancelled
|
||||
* @param reservation {Reservation}
|
||||
* @returns {boolean}
|
||||
*/
|
||||
$scope.isCancelled = function(reservation) {
|
||||
return !!(reservation.slots[0].canceled_at);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to alter an already booked reservation date. A modal window will be opened to allow the user to choose
|
||||
* a new date for his reservation (if any available)
|
||||
* @param reservation {{id:number, reservable_id:number, nb_reserve_places:number}}
|
||||
* @param e {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
*/
|
||||
$scope.modifyReservation = function (reservation, e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
$scope.modifyReservation = function (reservation) {
|
||||
const index = $scope.reservations.indexOf(reservation);
|
||||
return $uibModal.open({
|
||||
templateUrl: '<%= asset_path "events/modify_event_reservation_modal.html" %>',
|
||||
@ -364,9 +407,9 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
$scope.reservation = angular.copy(reservation);
|
||||
|
||||
// set the reservable_id to the first available event
|
||||
for (e of Array.from(event.recurrence_events)) {
|
||||
if (e.nb_free_places > reservation.total_booked_seats) {
|
||||
$scope.reservation.reservable_id = e.id;
|
||||
for (evt of Array.from(event.recurrence_events)) {
|
||||
if (evt.nb_free_places > reservation.total_booked_seats) {
|
||||
$scope.reservation.reservable_id = evt.id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -419,7 +462,7 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
|
||||
/**
|
||||
* Checks if the provided reservation is able to be moved (date change)
|
||||
* @param reservation {{total_booked_seats:number}}
|
||||
* @param reservation {{slots:[], total_booked_seats:number}}
|
||||
*/
|
||||
$scope.reservationCanModify = function (reservation) {
|
||||
const slotStart = moment(reservation.slots[0].start_at);
|
||||
@ -432,6 +475,17 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
return (isAble && $scope.enableBookingMove && (slotStart.diff(now, 'hours') >= $scope.moveBookingDelay));
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if the provided reservation is able to be cancelled
|
||||
* @param reservation {{slots:[]}}
|
||||
*/
|
||||
$scope.reservationCanCancel = function(reservation) {
|
||||
var now, slotStart;
|
||||
slotStart = moment(reservation.slots[0].start_at);
|
||||
now = moment();
|
||||
return $scope.enableBookingCancel && slotStart.diff(now, "hours") >= $scope.cancelBookingDelay;
|
||||
};
|
||||
|
||||
/**
|
||||
* Compute the total amount for the current reservation according to the previously set parameters
|
||||
* and assign the result in $scope.reserve.amountTotal
|
||||
@ -567,7 +621,7 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the current reservation to the default values. This implies to reservation form to be hidden.
|
||||
* Set the current reservation to the default values. This implies the reservation form to be hidden.
|
||||
*/
|
||||
var resetEventReserve = function () {
|
||||
if ($scope.event) {
|
||||
@ -696,12 +750,12 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
|
||||
// Button label
|
||||
if ($scope.amount > 0) {
|
||||
$scope.validButtonName = _t('confirm_payment_of_html', { ROLE: $scope.currentUser.role, AMOUNT: $filter('currency')($scope.amount) }, 'messageformat');
|
||||
$scope.validButtonName = _t('app.public.events_show.confirm_payment_of_html', { ROLE: $scope.currentUser.role, AMOUNT: $filter('currency')($scope.amount) });
|
||||
} else {
|
||||
if ((price.price > 0) && ($scope.walletAmount === 0)) {
|
||||
$scope.validButtonName = _t('confirm_payment_of_html', { ROLE: $scope.currentUser.role, AMOUNT: $filter('currency')(price.price) }, 'messageformat');
|
||||
$scope.validButtonName = _t('app.public.events_show.confirm_payment_of_html', { ROLE: $scope.currentUser.role, AMOUNT: $filter('currency')(price.price) });
|
||||
} else {
|
||||
$scope.validButtonName = _t('confirm');
|
||||
$scope.validButtonName = _t('app.shared.buttons.confirm');
|
||||
}
|
||||
}
|
||||
|
||||
@ -735,7 +789,7 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
|
||||
/**
|
||||
* What to do after the payment was successful
|
||||
* @param resveration {Object} booked reservation
|
||||
* @param reservation {Object} booked reservation
|
||||
*/
|
||||
var afterPayment = function (reservation) {
|
||||
$scope.event.nb_free_places = $scope.event.nb_free_places - reservation.total_booked_seats;
|
||||
|
@ -146,7 +146,7 @@ const _reserveMachine = function (machine, e) {
|
||||
let text = '';
|
||||
angular.forEach($scope.machine.trainings, function (training) {
|
||||
if (text.length > 0) {
|
||||
text += _this._t('machines_list._or_the_');
|
||||
text += _this._t('app.public.machines_list._or_the_');
|
||||
}
|
||||
return text += training.name.substr(0, 1).toLowerCase() + training.name.substr(1);
|
||||
});
|
||||
@ -281,14 +281,14 @@ Application.Controllers.controller('ShowMachineController', ['$scope', '$state',
|
||||
$scope.delete = function (machine) {
|
||||
// check the permissions
|
||||
if ($scope.currentUser.role !== 'admin') {
|
||||
console.error(_t('unauthorized_operation'));
|
||||
console.error(_t('app.public.machines_show.unauthorized_operation'));
|
||||
} else {
|
||||
dialogs.confirm({
|
||||
resolve: {
|
||||
object () {
|
||||
return {
|
||||
title: _t('confirmation_required'),
|
||||
msg: _t('do_you_really_want_to_delete_this_machine')
|
||||
title: _t('app.public.machines_show.confirmation_required'),
|
||||
msg: _t('app.public.machines_show.do_you_really_want_to_delete_this_machine')
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -297,7 +297,7 @@ Application.Controllers.controller('ShowMachineController', ['$scope', '$state',
|
||||
// delete the machine then redirect to the machines listing
|
||||
machine.$delete(
|
||||
function () { $state.go('app.public.machines_list'); },
|
||||
function (error) { growl.warning(_t('the_machine_cant_be_deleted_because_it_is_already_reserved_by_some_users')); console.error(error); }
|
||||
function (error) { growl.warning(_t('app.public.machines_show.the_machine_cant_be_deleted_because_it_is_already_reserved_by_some_users')); console.error(error); }
|
||||
);
|
||||
});
|
||||
}
|
||||
@ -402,16 +402,16 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
$scope.machineExplicationsAlert = settingsPromise.machine_explications_alert;
|
||||
|
||||
/**
|
||||
* Change the last selected slot's appearence to looks like 'added to cart'
|
||||
* Change the last selected slot's appearance to looks like 'added to cart'
|
||||
*/
|
||||
$scope.markSlotAsAdded = function () {
|
||||
$scope.selectedEvent.backgroundColor = FREE_SLOT_BORDER_COLOR;
|
||||
$scope.selectedEvent.title = _t('i_reserve');
|
||||
$scope.selectedEvent.title = _t('app.logged.machines_reserve.i_reserve');
|
||||
return updateCalendar();
|
||||
};
|
||||
|
||||
/**
|
||||
* Change the last selected slot's appearence to looks like 'never added to cart'
|
||||
* Change the last selected slot's appearance to looks like 'never added to cart'
|
||||
*/
|
||||
$scope.markSlotAsRemoved = function (slot) {
|
||||
slot.backgroundColor = 'white';
|
||||
@ -431,16 +431,16 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
$scope.slotCancelled = function () { $scope.markSlotAsRemoved($scope.selectedEvent); };
|
||||
|
||||
/**
|
||||
* Change the last selected slot's appearence to looks like 'currently looking for a new destination to exchange'
|
||||
* Change the last selected slot's appearance to looks like 'currently looking for a new destination to exchange'
|
||||
*/
|
||||
$scope.markSlotAsModifying = function () {
|
||||
$scope.selectedEvent.backgroundColor = '#eee';
|
||||
$scope.selectedEvent.title = _t('i_change');
|
||||
$scope.selectedEvent.title = _t('app.logged.machines_reserve.i_change');
|
||||
return updateCalendar();
|
||||
};
|
||||
|
||||
/**
|
||||
* Change the last selected slot's appearence to looks like 'the slot being exchanged will take this place'
|
||||
* Change the last selected slot's appearance to looks like 'the slot being exchanged will take this place'
|
||||
*/
|
||||
$scope.changeModifyMachineSlot = function () {
|
||||
if ($scope.events.placable) {
|
||||
@ -449,7 +449,7 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
}
|
||||
if (!$scope.events.placable || ($scope.events.placable._id !== $scope.selectedEvent._id)) {
|
||||
$scope.selectedEvent.backgroundColor = '#bbb';
|
||||
$scope.selectedEvent.title = _t('i_shift');
|
||||
$scope.selectedEvent.title = _t('app.logged.machines_reserve.i_shift');
|
||||
}
|
||||
return updateCalendar();
|
||||
};
|
||||
@ -458,7 +458,7 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
* When modifying an already booked reservation, callback when the modification was successfully done.
|
||||
*/
|
||||
$scope.modifyMachineSlot = function () {
|
||||
$scope.events.placable.title = $scope.currentUser.role !== 'admin' ? _t('i_ve_reserved') : _t('not_available');
|
||||
$scope.events.placable.title = $scope.currentUser.role !== 'admin' ? _t('app.logged.machines_reserve.i_ve_reserved') : _t('app.logged.machines_reserve.not_available');
|
||||
$scope.events.placable.backgroundColor = 'white';
|
||||
$scope.events.placable.borderColor = $scope.events.modifiable.borderColor;
|
||||
$scope.events.placable.id = $scope.events.modifiable.id;
|
||||
@ -476,14 +476,14 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
};
|
||||
|
||||
/**
|
||||
* Cancel the current booking modification, reseting the whole process
|
||||
* Cancel the current booking modification, resetting the whole process
|
||||
*/
|
||||
$scope.cancelModifyMachineSlot = function () {
|
||||
if ($scope.events.placable) {
|
||||
$scope.events.placable.backgroundColor = 'white';
|
||||
$scope.events.placable.title = '';
|
||||
}
|
||||
$scope.events.modifiable.title = $scope.currentUser.role !== 'admin' ? _t('i_ve_reserved') : _t('not_available');
|
||||
$scope.events.modifiable.title = $scope.currentUser.role !== 'admin' ? _t('app.logged.machines_reserve.i_ve_reserved') : _t('app.logged.machines_reserve.not_available');
|
||||
$scope.events.modifiable.backgroundColor = 'white';
|
||||
|
||||
return updateCalendar();
|
||||
@ -500,7 +500,7 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
};
|
||||
|
||||
/**
|
||||
* Changes the user current view from the plan subsription screen to the machine reservation agenda
|
||||
* Changes the user current view from the plan subscription screen to the machine reservation agenda
|
||||
* @param e {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
*/
|
||||
$scope.doNotSubscribePlan = function (e) {
|
||||
@ -539,11 +539,11 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
machineSlot.is_reserved = true;
|
||||
machineSlot.can_modify = true;
|
||||
if ($scope.currentUser.role !== 'admin') {
|
||||
machineSlot.title = _t('i_ve_reserved');
|
||||
machineSlot.title = _t('app.logged.machines_reserve.i_ve_reserved');
|
||||
machineSlot.borderColor = BOOKED_SLOT_BORDER_COLOR;
|
||||
updateMachineSlot(machineSlot, reservation, $scope.currentUser);
|
||||
} else {
|
||||
machineSlot.title = _t('not_available');
|
||||
machineSlot.title = _t('app.logged.machines_reserve.not_available');
|
||||
machineSlot.borderColor = UNAVAILABLE_SLOT_BORDER_COLOR;
|
||||
updateMachineSlot(machineSlot, reservation, $scope.ctrl.member);
|
||||
}
|
||||
@ -595,7 +595,7 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
};
|
||||
|
||||
/**
|
||||
* Triggered when fullCalendar tries to graphicaly render an event block.
|
||||
* Triggered when fullCalendar tries to graphically render an event block.
|
||||
* Append the event tag into the block, just after the event title.
|
||||
* @see http://fullcalendar.io/docs/event_rendering/eventRender/
|
||||
*/
|
||||
|
@ -18,33 +18,33 @@ Application.Controllers.controller('MainNavController', ['$scope', function ($sc
|
||||
$scope.navLinks = [
|
||||
{
|
||||
state: 'app.public.home',
|
||||
linkText: 'home',
|
||||
linkText: 'app.public.common.home',
|
||||
linkIcon: 'home'
|
||||
},
|
||||
|
||||
{
|
||||
state: 'app.public.machines_list',
|
||||
linkText: 'reserve_a_machine',
|
||||
linkText: 'app.public.common.reserve_a_machine',
|
||||
linkIcon: 'cogs'
|
||||
},
|
||||
{
|
||||
state: 'app.public.trainings_list',
|
||||
linkText: 'trainings_registrations',
|
||||
linkText: 'app.public.common.trainings_registrations',
|
||||
linkIcon: 'graduation-cap'
|
||||
},
|
||||
{
|
||||
state: 'app.public.events_list',
|
||||
linkText: 'events_registrations',
|
||||
linkText: 'app.public.common.events_registrations',
|
||||
linkIcon: 'tags'
|
||||
},
|
||||
{
|
||||
state: 'app.public.calendar',
|
||||
linkText: 'public_calendar',
|
||||
linkText: 'app.public.common.public_calendar',
|
||||
linkIcon: 'calendar'
|
||||
},
|
||||
{
|
||||
state: 'app.public.projects_list',
|
||||
linkText: 'projects_gallery',
|
||||
linkText: 'app.public.common.projects_gallery',
|
||||
linkIcon: 'th'
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ Application.Controllers.controller('MainNavController', ['$scope', function ($sc
|
||||
if (!Fablab.withoutPlans) {
|
||||
$scope.navLinks.push({
|
||||
state: 'app.public.plans',
|
||||
linkText: 'subscriptions',
|
||||
linkText: 'app.public.common.subscriptions',
|
||||
linkIcon: 'credit-card'
|
||||
});
|
||||
}
|
||||
@ -61,7 +61,7 @@ Application.Controllers.controller('MainNavController', ['$scope', function ($sc
|
||||
if (!Fablab.withoutSpaces) {
|
||||
$scope.navLinks.splice(3, 0, {
|
||||
state: 'app.public.spaces_list',
|
||||
linkText: 'reserve_a_space',
|
||||
linkText: 'app.public.common.reserve_a_space',
|
||||
linkIcon: 'rocket'
|
||||
});
|
||||
}
|
||||
@ -70,57 +70,57 @@ Application.Controllers.controller('MainNavController', ['$scope', function ($sc
|
||||
const adminNavLinks = [
|
||||
{
|
||||
state: 'app.admin.trainings',
|
||||
linkText: 'trainings_monitoring',
|
||||
linkText: 'app.public.common.trainings_monitoring',
|
||||
linkIcon: 'graduation-cap'
|
||||
},
|
||||
{
|
||||
state: 'app.admin.calendar',
|
||||
linkText: 'manage_the_calendar',
|
||||
linkText: 'app.public.common.manage_the_calendar',
|
||||
linkIcon: 'calendar'
|
||||
},
|
||||
{
|
||||
state: 'app.admin.members',
|
||||
linkText: 'manage_the_users',
|
||||
linkText: 'app.public.common.manage_the_users',
|
||||
linkIcon: 'users'
|
||||
},
|
||||
{
|
||||
state: 'app.admin.invoices',
|
||||
linkText: 'manage_the_invoices',
|
||||
linkText: 'app.public.common.manage_the_invoices',
|
||||
linkIcon: 'file-pdf-o'
|
||||
},
|
||||
{
|
||||
state: 'app.admin.pricing',
|
||||
linkText: 'subscriptions_and_prices',
|
||||
linkText: 'app.public.common.subscriptions_and_prices',
|
||||
linkIcon: 'money'
|
||||
},
|
||||
{
|
||||
state: 'app.admin.events',
|
||||
linkText: 'manage_the_events',
|
||||
linkText: 'app.public.common.manage_the_events',
|
||||
linkIcon: 'tags'
|
||||
},
|
||||
{
|
||||
state: 'app.public.machines_list',
|
||||
linkText: 'manage_the_machines',
|
||||
linkText: 'app.public.common.manage_the_machines',
|
||||
linkIcon: 'cogs'
|
||||
},
|
||||
{
|
||||
state: 'app.admin.project_elements',
|
||||
linkText: 'manage_the_projects_elements',
|
||||
linkText: 'app.public.common.manage_the_projects_elements',
|
||||
linkIcon: 'tasks'
|
||||
},
|
||||
{
|
||||
state: 'app.admin.statistics',
|
||||
linkText: 'statistics',
|
||||
linkText: 'app.public.common.statistics',
|
||||
linkIcon: 'bar-chart-o'
|
||||
},
|
||||
{
|
||||
state: 'app.admin.settings',
|
||||
linkText: 'customization',
|
||||
linkText: 'app.public.common.customization',
|
||||
linkIcon: 'gear'
|
||||
},
|
||||
{
|
||||
state: 'app.admin.open_api_clients',
|
||||
linkText: 'open_api_clients',
|
||||
linkText: 'app.public.common.open_api_clients',
|
||||
linkIcon: 'cloud'
|
||||
}
|
||||
].concat(Fablab.adminNavLinks);
|
||||
@ -130,7 +130,7 @@ Application.Controllers.controller('MainNavController', ['$scope', function ($sc
|
||||
if (!Fablab.withoutSpaces) {
|
||||
return $scope.adminNavLinks.splice(7, 0, {
|
||||
state: 'app.public.spaces_list',
|
||||
linkText: 'manage_the_spaces',
|
||||
linkText: 'app.public.common.manage_the_spaces',
|
||||
linkIcon: 'rocket'
|
||||
});
|
||||
}
|
||||
|
@ -142,10 +142,10 @@ Application.Controllers.controller('EditProfileController', ['$scope', '$rootSco
|
||||
$rootScope.currentUser = user;
|
||||
Auth._currentUser.group_id = user.group_id;
|
||||
$scope.group.change = false;
|
||||
return growl.success(_t('edit_profile.your_group_has_been_successfully_changed'));
|
||||
return growl.success(_t('app.logged.dashboard.settings.your_group_has_been_successfully_changed'));
|
||||
}
|
||||
, function (err) {
|
||||
growl.error(_t('edit_profile.an_unexpected_error_prevented_your_group_from_being_changed'));
|
||||
growl.error(_t('app.logged.dashboard.settings.an_unexpected_error_prevented_your_group_from_being_changed'));
|
||||
return console.error(err);
|
||||
});
|
||||
|
||||
@ -198,13 +198,13 @@ Application.Controllers.controller('EditProfileController', ['$scope', '$rootSco
|
||||
resolve: {
|
||||
object () {
|
||||
return {
|
||||
title: _t('confirmation_required'),
|
||||
title: _t('app.logged.dashboard.settings.confirmation_required'),
|
||||
msg: $sce.trustAsHtml(
|
||||
_t('edit_profile.confirm_delete_your_account') + '<br/>' +
|
||||
'<strong>' + _t('edit_profile.all_data_will_be_lost') + '</strong><br/><br/>' +
|
||||
_t('edit_profile.invoicing_data_kept') + '<br/>' +
|
||||
_t('edit_profile.statistic_data_anonymized') + '<br/>' +
|
||||
_t('edit_profile.no_further_access_to_projects')
|
||||
_t('app.logged.dashboard.settings.confirm_delete_your_account') + '<br/>' +
|
||||
'<strong>' + _t('app.logged.dashboard.settings.all_data_will_be_lost') + '</strong><br/><br/>' +
|
||||
_t('app.logged.dashboard.settings.invoicing_data_kept') + '<br/>' +
|
||||
_t('app.logged.dashboard.settings.statistic_data_anonymized') + '<br/>' +
|
||||
_t('app.logged.dashboard.settings.no_further_access_to_projects')
|
||||
)
|
||||
};
|
||||
}
|
||||
@ -214,12 +214,12 @@ Application.Controllers.controller('EditProfileController', ['$scope', '$rootSco
|
||||
Member.remove({ id: user.id }, () =>
|
||||
Auth.logout().then(function () {
|
||||
$state.go('app.public.home');
|
||||
return growl.success(_t('edit_profile.your_user_account_has_been_successfully_deleted_goodbye'));
|
||||
return growl.success(_t('app.logged.dashboard.settings.your_user_account_has_been_successfully_deleted_goodbye'));
|
||||
})
|
||||
|
||||
, function (error) {
|
||||
console.log(error);
|
||||
return growl.error(_t('edit_profile.an_error_occured_preventing_your_account_from_being_deleted'));
|
||||
return growl.error(_t('app.logged.dashboard.settings.an_error_occured_preventing_your_account_from_being_deleted'));
|
||||
})
|
||||
);
|
||||
|
||||
|
@ -99,7 +99,7 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
const amountToPay = helpers.getAmountToPay($scope.cart.total, wallet.amount);
|
||||
if (($scope.currentUser.role !== 'admin') && (amountToPay > 0)) {
|
||||
if ($rootScope.fablabWithoutOnlinePayment) {
|
||||
growl.error(_t('online_payment_disabled'));
|
||||
growl.error(_t('app.public.plans.online_payment_disabled'));
|
||||
} else {
|
||||
return payByStripe();
|
||||
}
|
||||
@ -133,16 +133,16 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
if ($scope.currentUser.role !== 'admin') {
|
||||
$rootScope.currentUser = user;
|
||||
Auth._currentUser.group_id = user.group_id;
|
||||
growl.success(_t('your_group_was_successfully_changed'));
|
||||
growl.success(_t('app.public.plans.your_group_was_successfully_changed'));
|
||||
} else {
|
||||
growl.success(_t('the_user_s_group_was_successfully_changed'));
|
||||
growl.success(_t('app.public.plans.the_user_s_group_was_successfully_changed'));
|
||||
}
|
||||
}
|
||||
, function (err) {
|
||||
if ($scope.currentUser.role !== 'admin') {
|
||||
growl.error(_t('an_error_prevented_your_group_from_being_changed'));
|
||||
growl.error(_t('app.public.plans.an_error_prevented_your_group_from_being_changed'));
|
||||
} else {
|
||||
growl.error(_t('an_error_prevented_to_change_the_user_s_group'));
|
||||
growl.error(_t('app.public.plans.an_error_prevented_to_change_the_user_s_group'));
|
||||
}
|
||||
console.error(err);
|
||||
});
|
||||
@ -318,12 +318,12 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
|
||||
// Button label
|
||||
if ($scope.amount > 0) {
|
||||
$scope.validButtonName = _t('confirm_payment_of_html', { ROLE: $scope.currentUser.role, AMOUNT: $filter('currency')($scope.amount) }, 'messageformat');
|
||||
$scope.validButtonName = _t('app.public.plans.confirm_payment_of_html', { ROLE: $scope.currentUser.role, AMOUNT: $filter('currency')($scope.amount) });
|
||||
} else {
|
||||
if ((price.price > 0) && ($scope.walletAmount === 0)) {
|
||||
$scope.validButtonName = _t('confirm_payment_of_html', { ROLE: $scope.currentUser.role, AMOUNT: $filter('currency')(price.price) }, 'messageformat');
|
||||
$scope.validButtonName = _t('app.public.plans.confirm_payment_of_html', { ROLE: $scope.currentUser.role, AMOUNT: $filter('currency')(price.price) });
|
||||
} else {
|
||||
$scope.validButtonName = _t('confirm');
|
||||
$scope.validButtonName = _t('app.shared.buttons.confirm');
|
||||
}
|
||||
}
|
||||
|
||||
@ -345,7 +345,7 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
}
|
||||
, function (data, status) { // failed
|
||||
$scope.alerts = [];
|
||||
$scope.alerts.push({ msg: _t('an_error_occured_during_the_payment_process_please_try_again_later'), type: 'danger' });
|
||||
$scope.alerts.push({ msg: _t('app.public.plans.an_error_occured_during_the_payment_process_please_try_again_later'), type: 'danger' });
|
||||
$scope.attempting = false;
|
||||
}
|
||||
);
|
||||
|
@ -123,7 +123,7 @@ Application.Controllers.controller('CompleteProfileController', ['$scope', '$roo
|
||||
if (err.data.error) {
|
||||
growl.error(err.data.error);
|
||||
} else {
|
||||
growl.error(_t('an_unexpected_error_occurred_check_your_authentication_code'));
|
||||
growl.error(_t('app.logged.profile_completion.an_unexpected_error_occurred_check_your_authentication_code'));
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
@ -174,7 +174,7 @@ Application.Controllers.controller('CompleteProfileController', ['$scope', '$roo
|
||||
function (email) {
|
||||
// Request the server to send an auth-migration email to the current user
|
||||
AuthProvider.send_code({ email },
|
||||
function (res) { growl.info(_t('code_successfully_sent_again')); },
|
||||
function (res) { growl.info(_t('app.logged.profile_completion.code_successfully_sent_again')); },
|
||||
function (err) { growl.error(err.data.error); }
|
||||
);
|
||||
}
|
||||
|
@ -165,8 +165,8 @@ class ProjectsController {
|
||||
resolve: {
|
||||
object () {
|
||||
return {
|
||||
title: _t('confirmation_required'),
|
||||
msg: _t('do_you_really_want_to_delete_this_step')
|
||||
title: _t('app.shared.project.confirmation_required'),
|
||||
msg: _t('app.shared.project.do_you_really_want_to_delete_this_step')
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -215,6 +215,10 @@ class ProjectsController {
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* This function will query the API to autocomplete the typed user's name
|
||||
* @param nameLookup {string}
|
||||
*/
|
||||
$scope.autoCompleteName = function (nameLookup) {
|
||||
if (!nameLookup) {
|
||||
return;
|
||||
@ -246,6 +250,16 @@ class ProjectsController {
|
||||
return step.project_step_images_attributes.splice(index, 1);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the text to display on the save button, depending on the current state of the project
|
||||
*/
|
||||
$scope.saveButtonValue = function () {
|
||||
if (!$scope.project.state || $scope.project.state === 'draft') {
|
||||
return _t('app.shared.project.save_as_draft');
|
||||
}
|
||||
return _t('app.shared.buttons.save');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -324,7 +338,7 @@ Application.Controllers.controller('ProjectsController', ['$scope', '$state', 'P
|
||||
$scope.projectsPagination = new paginationService.Instance(OpenlabProject, currentPage, PROJECTS_PER_PAGE, null, { }, loadMoreOpenlabCallback);
|
||||
return OpenlabProject.query({ q: $scope.search.q, page: currentPage, per_page: PROJECTS_PER_PAGE }, function (projectsPromise) {
|
||||
if (projectsPromise.errors != null) {
|
||||
growl.error(_t('projects_list.openlab_search_not_available_at_the_moment'));
|
||||
growl.error(_t('app.public.projects_list.openlab_search_not_available_at_the_moment'));
|
||||
$scope.openlab.searchOverWholeNetwork = false;
|
||||
return $scope.triggerSearch();
|
||||
} else {
|
||||
@ -533,8 +547,8 @@ Application.Controllers.controller('ShowProjectController', ['$scope', '$state',
|
||||
resolve: {
|
||||
object () {
|
||||
return {
|
||||
title: _t('confirmation_required'),
|
||||
msg: _t('do_you_really_want_to_delete_this_project')
|
||||
title: _t('app.public.projects_show.confirmation_required'),
|
||||
msg: _t('app.public.projects_show.do_you_really_want_to_delete_this_project')
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -543,7 +557,7 @@ Application.Controllers.controller('ShowProjectController', ['$scope', '$state',
|
||||
$scope.project.$delete(function () { $state.go('app.public.projects_list', {}, { reload: true }); });
|
||||
});
|
||||
} else {
|
||||
return console.error(_t('unauthorized_operation'));
|
||||
return console.error(_t('app.public.projects_show.unauthorized_operation'));
|
||||
}
|
||||
};
|
||||
|
||||
@ -577,12 +591,12 @@ Application.Controllers.controller('ShowProjectController', ['$scope', '$state',
|
||||
{ abuse: $scope.signaler },
|
||||
function (res) {
|
||||
// creation successful
|
||||
growl.success(_t('your_report_was_successful_thanks'));
|
||||
growl.success(_t('app.public.projects_show.your_report_was_successful_thanks'));
|
||||
return $uibModalInstance.close(res);
|
||||
}
|
||||
, function (error) {
|
||||
// creation failed...
|
||||
growl.error(_t('an_error_occured_while_sending_your_report'));
|
||||
growl.error(_t('app.public.projects_show.an_error_occured_while_sending_your_report'));
|
||||
}
|
||||
);
|
||||
};
|
||||
|
@ -185,14 +185,14 @@ Application.Controllers.controller('ShowSpaceController', ['$scope', '$state', '
|
||||
event.preventDefault();
|
||||
// check the permissions
|
||||
if ($scope.currentUser.role !== 'admin') {
|
||||
return console.error(_t('space_show.unauthorized_operation'));
|
||||
return console.error(_t('app.public.space_show.unauthorized_operation'));
|
||||
} else {
|
||||
return dialogs.confirm({
|
||||
resolve: {
|
||||
object () {
|
||||
return {
|
||||
title: _t('space_show.confirmation_required'),
|
||||
msg: _t('space_show.do_you_really_want_to_delete_this_space')
|
||||
title: _t('app.public.space_show.confirmation_required'),
|
||||
msg: _t('app.public.space_show.do_you_really_want_to_delete_this_space')
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -204,7 +204,7 @@ Application.Controllers.controller('ShowSpaceController', ['$scope', '$state', '
|
||||
$state.go('app.public.spaces_list');
|
||||
},
|
||||
function (error) {
|
||||
growl.warning(_t('space_show.the_space_cant_be_deleted_because_it_is_already_reserved_by_some_users'));
|
||||
growl.warning(_t('app.public.space_show.the_space_cant_be_deleted_because_it_is_already_reserved_by_some_users'));
|
||||
console.error(error);
|
||||
}
|
||||
);
|
||||
@ -333,7 +333,7 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
|
||||
*/
|
||||
$scope.markSlotAsModifying = function () {
|
||||
$scope.selectedEvent.backgroundColor = '#eee';
|
||||
$scope.selectedEvent.title = _t('space_reserve.i_change');
|
||||
$scope.selectedEvent.title = _t('app.logged.space_reserve.i_change');
|
||||
return updateCalendar();
|
||||
};
|
||||
|
||||
@ -347,7 +347,7 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
|
||||
}
|
||||
if (!$scope.events.placable || ($scope.events.placable._id !== $scope.selectedEvent._id)) {
|
||||
$scope.selectedEvent.backgroundColor = '#bbb';
|
||||
$scope.selectedEvent.title = _t('space_reserve.i_shift');
|
||||
$scope.selectedEvent.title = _t('app.logged.space_reserve.i_shift');
|
||||
}
|
||||
return updateCalendar();
|
||||
};
|
||||
@ -356,7 +356,7 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
|
||||
* When modifying an already booked reservation, callback when the modification was successfully done.
|
||||
*/
|
||||
$scope.modifyTrainingSlot = function () {
|
||||
$scope.events.placable.title = _t('space_reserve.i_ve_reserved');
|
||||
$scope.events.placable.title = _t('app.logged.space_reserve.i_ve_reserved');
|
||||
$scope.events.placable.backgroundColor = 'white';
|
||||
$scope.events.placable.borderColor = $scope.events.modifiable.borderColor;
|
||||
$scope.events.placable.id = $scope.events.modifiable.id;
|
||||
@ -382,7 +382,7 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
|
||||
$scope.events.placable.backgroundColor = 'white';
|
||||
$scope.events.placable.title = '';
|
||||
}
|
||||
$scope.events.modifiable.title = _t('space_reserve.i_ve_reserved');
|
||||
$scope.events.modifiable.title = _t('app.logged.space_reserve.i_ve_reserved');
|
||||
$scope.events.modifiable.backgroundColor = 'white';
|
||||
|
||||
return updateCalendar();
|
||||
@ -451,7 +451,7 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
|
||||
angular.forEach($scope.events.paid, function (spaceSlot, key) {
|
||||
spaceSlot.is_reserved = true;
|
||||
spaceSlot.can_modify = true;
|
||||
spaceSlot.title = _t('space_reserve.i_ve_reserved');
|
||||
spaceSlot.title = _t('app.logged.space_reserve.i_ve_reserved');
|
||||
spaceSlot.backgroundColor = 'white';
|
||||
spaceSlot.borderColor = RESERVED_SLOT_BORDER_COLOR;
|
||||
return updateSpaceSlotId(spaceSlot, reservation);
|
||||
|
@ -47,15 +47,15 @@ Application.Controllers.controller('ShowTrainingController', ['$scope', '$state'
|
||||
$scope.delete = function (training) {
|
||||
// check the permissions
|
||||
if ($scope.currentUser.role !== 'admin') {
|
||||
console.error(_t('unauthorized_operation'));
|
||||
growl.error(_t('app.public.training_show.unauthorized_operation'));
|
||||
} else {
|
||||
dialogs.confirm(
|
||||
{
|
||||
resolve: {
|
||||
object () {
|
||||
return {
|
||||
title: _t('confirmation_required'),
|
||||
msg: _t('do_you_really_want_to_delete_this_training')
|
||||
title: _t('app.public.training_show.confirmation_required'),
|
||||
msg: _t('app.public.training_show.do_you_really_want_to_delete_this_training')
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -65,7 +65,7 @@ Application.Controllers.controller('ShowTrainingController', ['$scope', '$state'
|
||||
training.$delete(
|
||||
function () { $state.go('app.public.trainings_list'); },
|
||||
function (error) {
|
||||
growl.warning(_t('the_training_cant_be_deleted_because_it_is_already_reserved_by_some_users'));
|
||||
growl.warning(_t('app.public.training_show.the_training_cant_be_deleted_because_it_is_already_reserved_by_some_users'));
|
||||
console.error(error);
|
||||
}
|
||||
);
|
||||
@ -208,7 +208,7 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
|
||||
*/
|
||||
$scope.markSlotAsModifying = function () {
|
||||
$scope.selectedEvent.backgroundColor = '#eee';
|
||||
$scope.selectedEvent.title = $scope.selectedEvent.training.name + ' - ' + _t('i_change');
|
||||
$scope.selectedEvent.title = $scope.selectedEvent.training.name + ' - ' + _t('app.logged.trainings_reserve.i_change');
|
||||
return updateCalendar();
|
||||
};
|
||||
|
||||
@ -222,7 +222,7 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
|
||||
}
|
||||
if (!$scope.events.placable || ($scope.events.placable._id !== $scope.selectedEvent._id)) {
|
||||
$scope.selectedEvent.backgroundColor = '#bbb';
|
||||
$scope.selectedEvent.title = $scope.selectedEvent.training.name + ' - ' + _t('i_shift');
|
||||
$scope.selectedEvent.title = $scope.selectedEvent.training.name + ' - ' + _t('app.logged.trainings_reserve.i_shift');
|
||||
}
|
||||
return updateCalendar();
|
||||
};
|
||||
@ -231,7 +231,7 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
|
||||
* When modifying an already booked reservation, callback when the modification was successfully done.
|
||||
*/
|
||||
$scope.modifyTrainingSlot = function () {
|
||||
$scope.events.placable.title = $scope.currentUser.role !== 'admin' ? $scope.events.placable.training.name + ' - ' + _t('i_ve_reserved') : $scope.events.placable.training.name;
|
||||
$scope.events.placable.title = $scope.currentUser.role !== 'admin' ? $scope.events.placable.training.name + ' - ' + _t('app.logged.trainings_reserve.i_ve_reserved') : $scope.events.placable.training.name;
|
||||
$scope.events.placable.backgroundColor = 'white';
|
||||
$scope.events.placable.borderColor = $scope.events.modifiable.borderColor;
|
||||
$scope.events.placable.id = $scope.events.modifiable.id;
|
||||
@ -257,7 +257,7 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
|
||||
$scope.events.placable.backgroundColor = 'white';
|
||||
$scope.events.placable.title = $scope.events.placable.training.name;
|
||||
}
|
||||
$scope.events.modifiable.title = $scope.currentUser.role !== 'admin' ? $scope.events.modifiable.training.name + ' - ' + _t('i_ve_reserved') : $scope.events.modifiable.training.name;
|
||||
$scope.events.modifiable.title = $scope.currentUser.role !== 'admin' ? $scope.events.modifiable.training.name + ' - ' + _t('app.logged.trainings_reserve.i_ve_reserved') : $scope.events.modifiable.training.name;
|
||||
$scope.events.modifiable.backgroundColor = 'white';
|
||||
|
||||
return updateCalendar();
|
||||
@ -329,7 +329,7 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
|
||||
$scope.events.paid[0].can_modify = true;
|
||||
updateTrainingSlotId($scope.events.paid[0], reservation);
|
||||
$scope.events.paid[0].borderColor = '#b2e774';
|
||||
$scope.events.paid[0].title = $scope.events.paid[0].training.name + ' - ' + _t('i_ve_reserved');
|
||||
$scope.events.paid[0].title = $scope.events.paid[0].training.name + ' - ' + _t('app.logged.trainings_reserve.i_ve_reserved');
|
||||
|
||||
if ($scope.selectedPlan) {
|
||||
$scope.ctrl.member.subscribed_plan = angular.copy($scope.selectedPlan);
|
||||
|
@ -117,7 +117,7 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
return $scope.modePlans = true;
|
||||
} else {
|
||||
// otherwise we alert, this error musn't occur when the current user hasn't the admin role
|
||||
return growl.error(_t('cart.please_select_a_member_first'));
|
||||
return growl.error(_t('app.shared.cart.please_select_a_member_first'));
|
||||
}
|
||||
};
|
||||
|
||||
@ -133,7 +133,7 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
const amountToPay = helpers.getAmountToPay($scope.amountTotal, wallet.amount);
|
||||
if (!$scope.isAdmin() && (amountToPay > 0)) {
|
||||
if ($rootScope.fablabWithoutOnlinePayment) {
|
||||
growl.error(_t('cart.online_payment_disabled'));
|
||||
growl.error(_t('app.shared.cart.online_payment_disabled'));
|
||||
} else {
|
||||
return payByStripe(reservation);
|
||||
}
|
||||
@ -145,7 +145,7 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
});
|
||||
} else {
|
||||
// otherwise we alert, this error musn't occur when the current user is not admin
|
||||
return growl.error(_t('cart.please_select_a_member_first'));
|
||||
return growl.error(_t('app.shared.cart.please_select_a_member_first'));
|
||||
}
|
||||
};
|
||||
|
||||
@ -173,7 +173,7 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
return $scope.events.modifiable = null;
|
||||
}
|
||||
, function (err) { // failure
|
||||
growl.error(_t('cart.unable_to_change_the_reservation'));
|
||||
growl.error(_t('app.shared.cart.unable_to_change_the_reservation'));
|
||||
return console.error(err);
|
||||
});
|
||||
};
|
||||
@ -315,19 +315,19 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
resolve: {
|
||||
object () {
|
||||
return {
|
||||
title: _t('cart.confirmation_required'),
|
||||
msg: _t('cart.do_you_really_want_to_cancel_this_reservation')
|
||||
title: _t('app.shared.cart.confirmation_required'),
|
||||
msg: _t('app.shared.cart.do_you_really_want_to_cancel_this_reservation')
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
function () { // cancel confirmed
|
||||
Slot.cancel({ id: $scope.slot.id }, function () { // successfully canceled
|
||||
growl.success(_t('cart.reservation_was_cancelled_successfully'));
|
||||
growl.success(_t('app.shared.cart.reservation_was_cancelled_successfully'));
|
||||
if (typeof $scope.onSlotCancelSuccess === 'function') { return $scope.onSlotCancelSuccess(); }
|
||||
}
|
||||
, function () { // error while canceling
|
||||
growl.error(_t('cart.cancellation_failed'));
|
||||
growl.error(_t('app.shared.cart.cancellation_failed'));
|
||||
});
|
||||
}
|
||||
);
|
||||
@ -403,7 +403,7 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
});
|
||||
} else {
|
||||
// otherwise we alert, this error musn't occur when the current user is not admin
|
||||
growl.warning(_t('cart.please_select_a_member_first'));
|
||||
growl.warning(_t('app.shared.cart.please_select_a_member_first'));
|
||||
return $scope.amountTotal = null;
|
||||
}
|
||||
};
|
||||
@ -556,12 +556,12 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
|
||||
// Button label
|
||||
if ($scope.amount > 0) {
|
||||
$scope.validButtonName = _t('cart.confirm_payment_of_html', { ROLE: $rootScope.currentUser.role, AMOUNT: $filter('currency')($scope.amount) }, 'messageformat');
|
||||
$scope.validButtonName = _t('app.shared.cart.confirm_payment_of_html', { ROLE: $rootScope.currentUser.role, AMOUNT: $filter('currency')($scope.amount) });
|
||||
} else {
|
||||
if ((price.price > 0) && ($scope.walletAmount === 0)) {
|
||||
$scope.validButtonName = _t('cart.confirm_payment_of_html', { ROLE: $rootScope.currentUser.role, AMOUNT: $filter('currency')(price.price) }, 'messageformat');
|
||||
$scope.validButtonName = _t('app.shared.cart.confirm_payment_of_html', { ROLE: $rootScope.currentUser.role, AMOUNT: $filter('currency')(price.price) });
|
||||
} else {
|
||||
$scope.validButtonName = _t('confirm');
|
||||
$scope.validButtonName = _t('app.shared.buttons.confirm');
|
||||
}
|
||||
}
|
||||
|
||||
@ -576,7 +576,7 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
}
|
||||
, function (response) {
|
||||
$scope.alerts = [];
|
||||
$scope.alerts.push({ msg: _t('cart.a_problem_occurred_during_the_payment_process_please_try_again_later'), type: 'danger' });
|
||||
$scope.alerts.push({ msg: _t('app.shared.cart.a_problem_occurred_during_the_payment_process_please_try_again_later'), type: 'danger' });
|
||||
return $scope.attempting = false;
|
||||
});
|
||||
};
|
||||
|
@ -53,15 +53,15 @@ Application.Directives.directive('coupon', [ '$rootScope', 'Coupon', '_t', funct
|
||||
$scope.status = 'valid';
|
||||
$scope.coupon = res;
|
||||
if (res.type === 'percent_off') {
|
||||
return $scope.messages.push({ type: 'success', message: _t('the_coupon_has_been_applied_you_get_PERCENT_discount', { PERCENT: res.percent_off }) });
|
||||
return $scope.messages.push({ type: 'success', message: _t('app.shared.coupon_input.the_coupon_has_been_applied_you_get_PERCENT_discount', { PERCENT: res.percent_off }) });
|
||||
} else {
|
||||
return $scope.messages.push({ type: 'success', message: _t('the_coupon_has_been_applied_you_get_AMOUNT_CURRENCY', { AMOUNT: res.amount_off, CURRENCY: $rootScope.currencySymbol }) });
|
||||
return $scope.messages.push({ type: 'success', message: _t('app.shared.coupon_input.the_coupon_has_been_applied_you_get_AMOUNT_CURRENCY', { AMOUNT: res.amount_off, CURRENCY: $rootScope.currencySymbol }) });
|
||||
}
|
||||
}
|
||||
, function (err) {
|
||||
$scope.status = 'invalid';
|
||||
$scope.coupon = null;
|
||||
return $scope.messages.push({ type: 'danger', message: _t(`unable_to_apply_the_coupon_because_${err.data.status}`) });
|
||||
return $scope.messages.push({ type: 'danger', message: _t(`app.shared.coupon_input.unable_to_apply_the_coupon_because_${err.data.status}`) });
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -1,14 +1,3 @@
|
||||
/* eslint-disable
|
||||
no-return-assign,
|
||||
no-undef,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
// Fix any style issues and re-enable lint.
|
||||
/*
|
||||
* decaffeinate suggestions:
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
@ -36,9 +25,9 @@ Application.Directives.directive('selectMember', [ 'Diacritics', 'Member', funct
|
||||
q['subscription'] = attributes.subscription;
|
||||
}
|
||||
|
||||
return Member.search(q, function (users) {
|
||||
Member.search(q, function (users) {
|
||||
scope.matchingMembers = users;
|
||||
return scope.isLoadingMembers = false;
|
||||
scope.isLoadingMembers = false;
|
||||
}
|
||||
, function (error) { console.error(error); });
|
||||
};
|
||||
|
@ -73,7 +73,7 @@ Application.Directives.directive('stripeForm', ['Payment', 'growl', '_t',
|
||||
if (response.error.statusText) {
|
||||
growl.error(response.error.statusText);
|
||||
} else {
|
||||
growl.error(`${_t('payment_card_error')} ${response.error}`);
|
||||
growl.error(`${_t('app.shared.messages.payment_card_error')} ${response.error}`);
|
||||
}
|
||||
confirmButton.prop('disabled', false);
|
||||
} else if (response.requires_action) {
|
||||
|
@ -318,22 +318,12 @@ Application.Filters.filter('toIsoDate', [function () {
|
||||
};
|
||||
}]);
|
||||
|
||||
Application.Filters.filter('booleanFormat', [ '_t', function (_t) {
|
||||
return function (boolean) {
|
||||
if (boolean || (boolean === 'true')) {
|
||||
return _t('yes');
|
||||
} else {
|
||||
return _t('no');
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
Application.Filters.filter('booleanFormat', [ '_t', function (_t) {
|
||||
return function (boolean) {
|
||||
if (((typeof boolean === 'boolean') && boolean) || ((typeof boolean === 'string') && (boolean === 'true'))) {
|
||||
return _t('yes');
|
||||
return _t('app.shared.buttons.yes');
|
||||
} else {
|
||||
return _t('no');
|
||||
return _t('app.shared.buttons.no');
|
||||
}
|
||||
};
|
||||
}]);
|
||||
@ -341,7 +331,7 @@ Application.Filters.filter('booleanFormat', [ '_t', function (_t) {
|
||||
Application.Filters.filter('maxCount', [ '_t', function (_t) {
|
||||
return function (max) {
|
||||
if ((typeof max === 'undefined') || (max === null) || ((typeof max === 'number') && (max === 0))) {
|
||||
return _t('unlimited');
|
||||
return _t('app.admin.pricing.unlimited');
|
||||
} else {
|
||||
return max;
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ angular.module('application.router', ['ui.router'])
|
||||
resolve: {
|
||||
logoFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'logo-file' }).$promise; }],
|
||||
logoBlackFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'logo-black-file' }).$promise; }],
|
||||
commonTranslations: ['Translations', function (Translations) { return Translations.query(['app.public.common', 'app.shared.buttons', 'app.shared.elements']).$promise; }]
|
||||
sharedTranslations: ['Translations', function (Translations) { return Translations.query(['app.shared', 'app.public.common']).$promise; }]
|
||||
},
|
||||
onEnter: ['$rootScope', 'logoFile', 'logoBlackFile', 'CSRF', function ($rootScope, logoFile, logoBlackFile, CSRF) {
|
||||
// Retrieve Anti-CSRF tokens from cookies
|
||||
@ -47,7 +47,10 @@ angular.module('application.router', ['ui.router'])
|
||||
}]
|
||||
})
|
||||
.state('app.public', {
|
||||
abstract: true
|
||||
abstract: true,
|
||||
resolve: {
|
||||
publicTranslations: ['Translations', function (Translations) { return Translations.query(['app.public']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.logged', {
|
||||
abstract: true,
|
||||
@ -55,7 +58,8 @@ angular.module('application.router', ['ui.router'])
|
||||
authorizedRoles: ['member', 'admin']
|
||||
},
|
||||
resolve: {
|
||||
currentUser: ['Auth', function (Auth) { return Auth.currentUser(); }]
|
||||
currentUser: ['Auth', function (Auth) { return Auth.currentUser(); }],
|
||||
loggedTranslations: ['Translations', function (Translations) { return Translations.query(['app.logged']).$promise; }]
|
||||
},
|
||||
onEnter: ['$state', '$timeout', 'currentUser', '$rootScope', function ($state, $timeout, currentUser, $rootScope) {
|
||||
$rootScope.currentUser = currentUser;
|
||||
@ -67,7 +71,8 @@ angular.module('application.router', ['ui.router'])
|
||||
authorizedRoles: ['admin']
|
||||
},
|
||||
resolve: {
|
||||
currentUser: ['Auth', function (Auth) { return Auth.currentUser(); }]
|
||||
currentUser: ['Auth', function (Auth) { return Auth.currentUser(); }],
|
||||
adminTranslations: ['Translations', function (Translations) { return Translations.query(['app.admin']).$promise; }]
|
||||
},
|
||||
onEnter: ['$state', '$timeout', 'currentUser', '$rootScope', function ($state, $timeout, currentUser, $rootScope) {
|
||||
$rootScope.currentUser = currentUser;
|
||||
@ -82,9 +87,6 @@ angular.module('application.router', ['ui.router'])
|
||||
templateUrl: '<%= asset_path "shared/about.html" %>',
|
||||
controller: 'AboutController'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: ['Translations', function (Translations) { return Translations.query('app.public.about').$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.public.home', {
|
||||
@ -101,7 +103,6 @@ angular.module('application.router', ['ui.router'])
|
||||
upcomingEventsPromise: ['Event', function (Event) { return Event.upcoming({ limit: 3 }).$promise; }],
|
||||
homeBlogpostPromise: ['Setting', function (Setting) { return Setting.get({ name: 'home_blogpost' }).$promise; }],
|
||||
twitterNamePromise: ['Setting', function (Setting) { return Setting.get({ name: 'twitter_name' }).$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query('app.public.home').$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.public.privacy', {
|
||||
@ -111,9 +112,6 @@ angular.module('application.router', ['ui.router'])
|
||||
templateUrl: '<%= asset_path "shared/privacy.html" %>',
|
||||
controller: 'PrivacyController'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: ['Translations', function (Translations) { return Translations.query('app.public.privacy').$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -132,7 +130,6 @@ angular.module('application.router', ['ui.router'])
|
||||
groupsPromise: ['Group', function (Group) { return Group.query().$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; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.logged.profileCompletion', 'app.shared.user']).$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -151,9 +148,6 @@ angular.module('application.router', ['ui.router'])
|
||||
templateUrl: '<%= asset_path "dashboard/profile.html" %>',
|
||||
controller: 'DashboardController'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.logged.dashboard.profile', 'app.shared.public_profile']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.logged.dashboard.settings', {
|
||||
@ -167,7 +161,6 @@ angular.module('application.router', ['ui.router'])
|
||||
resolve: {
|
||||
groups: ['Group', function (Group) { return Group.query().$promise; }],
|
||||
activeProviderPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.active().$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.logged.dashboard.settings', 'app.shared.user']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.logged.dashboard.projects', {
|
||||
@ -177,9 +170,6 @@ angular.module('application.router', ['ui.router'])
|
||||
templateUrl: '<%= asset_path "dashboard/projects.html" %>',
|
||||
controller: 'DashboardController'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: ['Translations', function (Translations) { return Translations.query('app.logged.dashboard.projects').$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.logged.dashboard.trainings', {
|
||||
@ -189,9 +179,6 @@ angular.module('application.router', ['ui.router'])
|
||||
templateUrl: '<%= asset_path "dashboard/trainings.html" %>',
|
||||
controller: 'DashboardController'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: ['Translations', function (Translations) { return Translations.query('app.logged.dashboard.trainings').$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.logged.dashboard.events', {
|
||||
@ -201,9 +188,6 @@ angular.module('application.router', ['ui.router'])
|
||||
templateUrl: '<%= asset_path "dashboard/events.html" %>',
|
||||
controller: 'DashboardController'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: ['Translations', function (Translations) { return Translations.query('app.logged.dashboard.events').$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.logged.dashboard.invoices', {
|
||||
@ -213,9 +197,6 @@ angular.module('application.router', ['ui.router'])
|
||||
templateUrl: '<%= asset_path "dashboard/invoices.html" %>',
|
||||
controller: 'DashboardController'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: ['Translations', function (Translations) { return Translations.query('app.logged.dashboard.invoices').$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.logged.dashboard.wallet', {
|
||||
@ -228,8 +209,7 @@ angular.module('application.router', ['ui.router'])
|
||||
},
|
||||
resolve: {
|
||||
walletPromise: ['Wallet', 'currentUser', function (Wallet, currentUser) { return Wallet.getWalletByUser({ user_id: currentUser.id }).$promise; }],
|
||||
transactionsPromise: ['Wallet', 'walletPromise', function (Wallet, walletPromise) { return Wallet.transactions({ id: walletPromise.id }).$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.shared.wallet']).$promise; }]
|
||||
transactionsPromise: ['Wallet', 'walletPromise', function (Wallet, walletPromise) { return Wallet.transactions({ id: walletPromise.id }).$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -243,8 +223,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
memberPromise: ['$stateParams', 'Member', function ($stateParams, Member) { return Member.get({ id: $stateParams.id }).$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.logged.members_show', 'app.shared.public_profile']).$promise; }]
|
||||
memberPromise: ['$stateParams', 'Member', function ($stateParams, Member) { return Member.get({ id: $stateParams.id }).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.logged.members', {
|
||||
@ -256,8 +235,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
membersPromise: ['Member', function (Member) { return Member.query({ requested_attributes: '[profile]', page: 1, size: 10 }).$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query('app.logged.members').$promise; }]
|
||||
membersPromise: ['Member', function (Member) { return Member.query({ requested_attributes: '[profile]', page: 1, size: 10 }).$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -273,8 +251,7 @@ angular.module('application.router', ['ui.router'])
|
||||
resolve: {
|
||||
themesPromise: ['Theme', function (Theme) { return Theme.query().$promise; }],
|
||||
componentsPromise: ['Component', function (Component) { return Component.query().$promise; }],
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query('app.public.projects_list').$promise; }]
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.logged.projects_new', {
|
||||
@ -286,8 +263,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
allowedExtensions: ['Project', function (Project) { return Project.allowedExtensions().$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.logged.projects_new', 'app.shared.project']).$promise; }]
|
||||
allowedExtensions: ['Project', function (Project) { return Project.allowedExtensions().$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.public.projects_show', {
|
||||
@ -299,8 +275,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
projectPromise: ['$stateParams', 'Project', function ($stateParams, Project) { return Project.get({ id: $stateParams.id }).$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query('app.public.projects_show').$promise; }]
|
||||
projectPromise: ['$stateParams', 'Project', function ($stateParams, Project) { return Project.get({ id: $stateParams.id }).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.logged.projects_edit', {
|
||||
@ -313,8 +288,7 @@ angular.module('application.router', ['ui.router'])
|
||||
},
|
||||
resolve: {
|
||||
projectPromise: ['$stateParams', 'Project', function ($stateParams, Project) { return Project.get({ id: $stateParams.id }).$promise; }],
|
||||
allowedExtensions: ['Project', function (Project) { return Project.allowedExtensions().$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.logged.projects_edit', 'app.shared.project']).$promise; }]
|
||||
allowedExtensions: ['Project', function (Project) { return Project.allowedExtensions().$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -328,8 +302,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.public.machines_list', 'app.shared.training_reservation_modal', 'app.shared.request_training_modal']).$promise; }]
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.machines_new', {
|
||||
@ -339,9 +312,6 @@ angular.module('application.router', ['ui.router'])
|
||||
templateUrl: '<%= asset_path "machines/new.html" %>',
|
||||
controller: 'NewMachineController'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.admin.machines_new', 'app.shared.machine']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.public.machines_show', {
|
||||
@ -353,8 +323,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
machinePromise: ['Machine', '$stateParams', function (Machine, $stateParams) { return Machine.get({ id: $stateParams.id }).$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.public.machines_show', 'app.shared.training_reservation_modal', 'app.shared.request_training_modal']).$promise; }]
|
||||
machinePromise: ['Machine', '$stateParams', function (Machine, $stateParams) { return Machine.get({ id: $stateParams.id }).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.logged.machines_reserve', {
|
||||
@ -380,11 +349,6 @@ angular.module('application.router', ['ui.router'])
|
||||
'booking_cancel_delay', \
|
||||
'subscription_explications_alert']`
|
||||
}).$promise;
|
||||
}],
|
||||
translations: ['Translations', function (Translations) {
|
||||
return Translations.query(['app.logged.machines_reserve', 'app.shared.plan_subscribe', 'app.shared.member_select',
|
||||
'app.shared.stripe', 'app.shared.valid_reservation_modal', 'app.shared.confirm_modify_slot_modal',
|
||||
'app.shared.wallet', 'app.shared.coupon_input', 'app.shared.cart']).$promise;
|
||||
}]
|
||||
}
|
||||
})
|
||||
@ -397,8 +361,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
machinePromise: ['Machine', '$stateParams', function (Machine, $stateParams) { return Machine.get({ id: $stateParams.id }).$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.admin.machines_edit', 'app.shared.machine']).$promise; }]
|
||||
machinePromise: ['Machine', '$stateParams', function (Machine, $stateParams) { return Machine.get({ id: $stateParams.id }).$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -413,8 +376,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
spacesPromise: ['Space', function (Space) { return Space.query().$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.public.spaces_list']).$promise; }]
|
||||
spacesPromise: ['Space', function (Space) { return Space.query().$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.space_new', {
|
||||
@ -425,9 +387,6 @@ angular.module('application.router', ['ui.router'])
|
||||
templateUrl: '<%= asset_path "spaces/new.html" %>',
|
||||
controller: 'NewSpaceController'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.admin.space_new', 'app.shared.space']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.public.space_show', {
|
||||
@ -440,8 +399,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
spacePromise: ['Space', '$stateParams', function (Space, $stateParams) { return Space.get({ id: $stateParams.id }).$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.public.space_show']).$promise; }]
|
||||
spacePromise: ['Space', '$stateParams', function (Space, $stateParams) { return Space.get({ id: $stateParams.id }).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.space_edit', {
|
||||
@ -454,8 +412,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
spacePromise: ['Space', '$stateParams', function (Space, $stateParams) { return Space.get({ id: $stateParams.id }).$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.admin.space_edit', 'app.shared.space']).$promise; }]
|
||||
spacePromise: ['Space', '$stateParams', function (Space, $stateParams) { return Space.get({ id: $stateParams.id }).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.logged.space_reserve', {
|
||||
@ -482,11 +439,6 @@ angular.module('application.router', ['ui.router'])
|
||||
'booking_cancel_delay', \
|
||||
'subscription_explications_alert', \
|
||||
'space_explications_alert']` }).$promise;
|
||||
}],
|
||||
translations: ['Translations', function (Translations) {
|
||||
return Translations.query(['app.logged.space_reserve', 'app.shared.plan_subscribe', 'app.shared.member_select',
|
||||
'app.shared.stripe', 'app.shared.valid_reservation_modal', 'app.shared.confirm_modify_slot_modal',
|
||||
'app.shared.wallet', 'app.shared.coupon_input', 'app.shared.cart']).$promise;
|
||||
}]
|
||||
}
|
||||
})
|
||||
@ -501,8 +453,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
trainingsPromise: ['Training', function (Training) { return Training.query({ public_page: true }).$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.public.trainings_list']).$promise; }]
|
||||
trainingsPromise: ['Training', function (Training) { return Training.query({ public_page: true }).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.public.training_show', {
|
||||
@ -514,8 +465,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
trainingPromise: ['Training', '$stateParams', function (Training, $stateParams) { return Training.get({ id: $stateParams.id }).$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.public.training_show']).$promise; }]
|
||||
trainingPromise: ['Training', '$stateParams', function (Training, $stateParams) { return Training.get({ id: $stateParams.id }).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.logged.trainings_reserve', {
|
||||
@ -545,11 +495,6 @@ angular.module('application.router', ['ui.router'])
|
||||
'subscription_explications_alert', \
|
||||
'training_explications_alert', \
|
||||
'training_information_message']` }).$promise;
|
||||
}],
|
||||
translations: ['Translations', function (Translations) {
|
||||
return Translations.query(['app.logged.trainings_reserve', 'app.shared.plan_subscribe', 'app.shared.member_select',
|
||||
'app.shared.stripe', 'app.shared.valid_reservation_modal', 'app.shared.confirm_modify_slot_modal',
|
||||
'app.shared.wallet', 'app.shared.coupon_input', 'app.shared.cart']).$promise;
|
||||
}]
|
||||
}
|
||||
})
|
||||
@ -561,9 +506,6 @@ angular.module('application.router', ['ui.router'])
|
||||
templateUrl: '<%= asset_path "notifications/index.html.erb" %>',
|
||||
controller: 'NotificationsController'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: ['Translations', function (Translations) { return Translations.query('app.logged.notifications').$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -580,11 +522,7 @@ angular.module('application.router', ['ui.router'])
|
||||
resolve: {
|
||||
subscriptionExplicationsPromise: ['Setting', function (Setting) { return Setting.get({ name: 'subscription_explications_alert' }).$promise; }],
|
||||
plansPromise: ['Plan', function (Plan) { return Plan.query().$promise; }],
|
||||
groupsPromise: ['Group', function (Group) { return Group.query().$promise; }],
|
||||
translations: ['Translations', function (Translations) {
|
||||
return Translations.query(['app.public.plans', 'app.shared.member_select', 'app.shared.stripe', 'app.shared.wallet',
|
||||
'app.shared.coupon_input']).$promise;
|
||||
}]
|
||||
groupsPromise: ['Group', function (Group) { return Group.query().$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -600,8 +538,7 @@ angular.module('application.router', ['ui.router'])
|
||||
resolve: {
|
||||
categoriesPromise: ['Category', function (Category) { return Category.query().$promise; }],
|
||||
themesPromise: ['EventTheme', function (EventTheme) { return EventTheme.query().$promise; }],
|
||||
ageRangesPromise: ['AgeRange', function (AgeRange) { return AgeRange.query().$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query('app.public.events_list').$promise; }]
|
||||
ageRangesPromise: ['AgeRange', function (AgeRange) { return AgeRange.query().$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.public.events_show', {
|
||||
@ -615,11 +552,7 @@ angular.module('application.router', ['ui.router'])
|
||||
resolve: {
|
||||
eventPromise: ['Event', '$stateParams', function (Event, $stateParams) { return Event.get({ id: $stateParams.id }).$promise; }],
|
||||
priceCategoriesPromise: ['PriceCategory', function (PriceCategory) { return PriceCategory.query().$promise; }],
|
||||
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['booking_move_enable', 'booking_move_delay', 'event_explications_alert']" }).$promise; }],
|
||||
translations: ['Translations', function (Translations) {
|
||||
return Translations.query(['app.public.events_show', 'app.shared.member_select', 'app.shared.stripe',
|
||||
'app.shared.valid_reservation_modal', 'app.shared.wallet', 'app.shared.coupon_input']).$promise;
|
||||
}]
|
||||
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['booking_move_enable', 'booking_move_delay', 'booking_cancel_enable', 'booking_cancel_delay', 'event_explications_alert']" }).$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -638,7 +571,7 @@ angular.module('application.router', ['ui.router'])
|
||||
trainingsPromise: ['Training', function (Training) { return Training.query().$promise; }],
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }],
|
||||
spacesPromise: ['Space', function (Space) { return Space.query().$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.public.calendar']).$promise; }]
|
||||
iCalendarPromise: ['ICalendar', function (ICalendar) { return ICalendar.query().$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -655,8 +588,19 @@ angular.module('application.router', ['ui.router'])
|
||||
resolve: {
|
||||
bookingWindowStart: ['Setting', function (Setting) { return Setting.get({ name: 'booking_window_start' }).$promise; }],
|
||||
bookingWindowEnd: ['Setting', function (Setting) { return Setting.get({ name: 'booking_window_end' }).$promise; }],
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query('app.admin.calendar').$promise; }]
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.calendar.icalendar', {
|
||||
url: '/admin/calendar/icalendar',
|
||||
views: {
|
||||
'main@': {
|
||||
templateUrl: '<%= asset_path "admin/calendar/icalendar.html" %>',
|
||||
controller: 'AdminICalendarController'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
iCalendars: ['ICalendar', function (ICalendar) { return ICalendar.query().$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -672,8 +616,7 @@ angular.module('application.router', ['ui.router'])
|
||||
resolve: {
|
||||
componentsPromise: ['Component', function (Component) { return Component.query().$promise; }],
|
||||
licencesPromise: ['Licence', function (Licence) { return Licence.query().$promise; }],
|
||||
themesPromise: ['Theme', function (Theme) { return Theme.query().$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query('app.admin.project_elements').$promise; }]
|
||||
themesPromise: ['Theme', function (Theme) { return Theme.query().$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.manage_abuses', {
|
||||
@ -685,8 +628,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
abusesPromise: ['Abuse', function(Abuse) { return Abuse.query().$promise; }],
|
||||
translations: ['Translations', function(Translations) { return Translations.query('app.admin.manage_abuses').$promise; }]
|
||||
abusesPromise: ['Abuse', function(Abuse) { return Abuse.query().$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -701,8 +643,7 @@ angular.module('application.router', ['ui.router'])
|
||||
},
|
||||
resolve: {
|
||||
trainingsPromise: ['Training', function (Training) { return Training.query().$promise; }],
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.admin.trainings', 'app.shared.trainings']).$promise; }]
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.trainings_new', {
|
||||
@ -714,8 +655,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.admin.trainings_new', 'app.shared.trainings']).$promise; }]
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.trainings_edit', {
|
||||
@ -728,8 +668,7 @@ angular.module('application.router', ['ui.router'])
|
||||
},
|
||||
resolve: {
|
||||
trainingPromise: ['Training', '$stateParams', function (Training, $stateParams) { return Training.get({ id: $stateParams.id }).$promise; }],
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query('app.shared.trainings').$promise; }]
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }]
|
||||
}
|
||||
})
|
||||
// events
|
||||
@ -746,8 +685,7 @@ angular.module('application.router', ['ui.router'])
|
||||
categoriesPromise: ['Category', function (Category) { return Category.query().$promise; }],
|
||||
themesPromise: ['EventTheme', function (EventTheme) { return EventTheme.query().$promise; }],
|
||||
ageRangesPromise: ['AgeRange', function (AgeRange) { return AgeRange.query().$promise; }],
|
||||
priceCategoriesPromise: ['PriceCategory', function (PriceCategory) { return PriceCategory.query().$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query('app.admin.events').$promise; }]
|
||||
priceCategoriesPromise: ['PriceCategory', function (PriceCategory) { return PriceCategory.query().$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.events_new', {
|
||||
@ -762,8 +700,7 @@ angular.module('application.router', ['ui.router'])
|
||||
categoriesPromise: ['Category', function (Category) { return Category.query().$promise; }],
|
||||
themesPromise: ['EventTheme', function (EventTheme) { return EventTheme.query().$promise; }],
|
||||
ageRangesPromise: ['AgeRange', function (AgeRange) { return AgeRange.query().$promise; }],
|
||||
priceCategoriesPromise: ['PriceCategory', function (PriceCategory) { return PriceCategory.query().$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.admin.events_new', 'app.shared.event']).$promise; }]
|
||||
priceCategoriesPromise: ['PriceCategory', function (PriceCategory) { return PriceCategory.query().$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.events_edit', {
|
||||
@ -779,8 +716,7 @@ angular.module('application.router', ['ui.router'])
|
||||
categoriesPromise: ['Category', function (Category) { return Category.query().$promise; }],
|
||||
themesPromise: ['EventTheme', function (EventTheme) { return EventTheme.query().$promise; }],
|
||||
ageRangesPromise: ['AgeRange', function (AgeRange) { return AgeRange.query().$promise; }],
|
||||
priceCategoriesPromise: ['PriceCategory', function (PriceCategory) { return PriceCategory.query().$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.admin.events_edit', 'app.shared.event']).$promise; }]
|
||||
priceCategoriesPromise: ['PriceCategory', function (PriceCategory) { return PriceCategory.query().$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.event_reservations', {
|
||||
@ -793,8 +729,7 @@ angular.module('application.router', ['ui.router'])
|
||||
},
|
||||
resolve: {
|
||||
eventPromise: ['Event', '$stateParams', function (Event, $stateParams) { return Event.get({ id: $stateParams.id }).$promise; }],
|
||||
reservationsPromise: ['Reservation', '$stateParams', function (Reservation, $stateParams) { return Reservation.query({ reservable_id: $stateParams.id, reservable_type: 'Event' }).$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query('app.admin.event_reservations').$promise; }]
|
||||
reservationsPromise: ['Reservation', '$stateParams', function (Reservation, $stateParams) { return Reservation.query({ reservable_id: $stateParams.id, reservable_type: 'Event' }).$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -812,7 +747,6 @@ angular.module('application.router', ['ui.router'])
|
||||
groups: ['Group', function (Group) { return Group.query().$promise; }],
|
||||
machinesPricesPromise: ['Price', function (Price) { return Price.query({ priceable_type: 'Machine', plan_id: 'null' }).$promise; }],
|
||||
trainingsPricingsPromise: ['TrainingsPricing', function (TrainingsPricing) { return TrainingsPricing.query().$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.admin.pricing', 'app.shared.member_select', 'app.shared.coupon']).$promise; }],
|
||||
trainingsPromise: ['Training', function (Training) { return Training.query().$promise; }],
|
||||
machineCreditsPromise: ['Credit', function (Credit) { return Credit.query({ creditable_type: 'Machine' }).$promise; }],
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }],
|
||||
@ -840,9 +774,6 @@ angular.module('application.router', ['ui.router'])
|
||||
templateUrl: '<%= asset_path "admin/plans/new.html" %>',
|
||||
controller: 'NewPlanController'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.admin.plans.new', 'app.shared.plan']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.plans.edit', {
|
||||
@ -857,8 +788,7 @@ angular.module('application.router', ['ui.router'])
|
||||
spaces: ['Space', function (Space) { return Space.query().$promise; }],
|
||||
machines: ['Machine', function (Machine) { return Machine.query().$promise; }],
|
||||
plans: ['Plan', function (Plan) { return Plan.query().$promise; }],
|
||||
planPromise: ['Plan', '$stateParams', function (Plan, $stateParams) { return Plan.get({ id: $stateParams.id }).$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.admin.plans.edit', 'app.shared.plan']).$promise; }]
|
||||
planPromise: ['Plan', '$stateParams', function (Plan, $stateParams) { return Plan.get({ id: $stateParams.id }).$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -870,9 +800,6 @@ angular.module('application.router', ['ui.router'])
|
||||
templateUrl: '<%= asset_path "admin/coupons/new.html" %>',
|
||||
controller: 'NewCouponController'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.admin.coupons_new', 'app.shared.coupon']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.coupons_edit', {
|
||||
@ -884,8 +811,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
couponPromise: ['Coupon', '$stateParams', function (Coupon, $stateParams) { return Coupon.get({ id: $stateParams.id }).$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.admin.coupons_edit', 'app.shared.coupon']).$promise; }]
|
||||
couponPromise: ['Coupon', '$stateParams', function (Coupon, $stateParams) { return Coupon.get({ id: $stateParams.id }).$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -914,8 +840,7 @@ angular.module('application.router', ['ui.router'])
|
||||
query: { number: '', customer: '', date: null, order_by: '-reference', page: 1, size: 20 }
|
||||
}).$promise;
|
||||
}],
|
||||
closedPeriods: [ 'AccountingPeriod', function(AccountingPeriod) { return AccountingPeriod.query().$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query('app.admin.invoices').$promise; }]
|
||||
closedPeriods: [ 'AccountingPeriod', function(AccountingPeriod) { return AccountingPeriod.query().$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -945,8 +870,7 @@ angular.module('application.router', ['ui.router'])
|
||||
adminsPromise: ['Admin', function (Admin) { return Admin.query().$promise; }],
|
||||
groupsPromise: ['Group', function (Group) { return Group.query().$promise; }],
|
||||
tagsPromise: ['Tag', function (Tag) { return Tag.query().$promise; }],
|
||||
authProvidersPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.query().$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query('app.admin.members').$promise; }]
|
||||
authProvidersPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.query().$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.members_new', {
|
||||
@ -956,9 +880,6 @@ angular.module('application.router', ['ui.router'])
|
||||
templateUrl: '<%= asset_path "admin/members/new.html" %>',
|
||||
controller: 'NewMemberController'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.admin.members_new', 'app.shared.user', 'app.shared.user_admin']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.members_import', {
|
||||
@ -970,7 +891,6 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.admin.members_import', 'app.shared.user', 'app.shared.user_admin']).$promise; }],
|
||||
tags: ['Tag', function(Tag) { return Tag.query().$promise }]
|
||||
}
|
||||
})
|
||||
@ -983,7 +903,6 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.admin.members_import_result', 'app.shared.user', 'app.shared.user_admin']).$promise; }],
|
||||
importItem: ['Import', '$stateParams', function(Import, $stateParams) { return Import.get({ id: $stateParams.id }).$promise }]
|
||||
}
|
||||
})
|
||||
@ -1000,8 +919,7 @@ angular.module('application.router', ['ui.router'])
|
||||
activeProviderPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.active().$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; }],
|
||||
tagsPromise: ['Tag', function (Tag) { return Tag.query().$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.admin.members_edit', 'app.shared.user', 'app.shared.user_admin', 'app.shared.wallet']).$promise; }]
|
||||
tagsPromise: ['Tag', function (Tag) { return Tag.query().$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.admins_new', {
|
||||
@ -1011,9 +929,6 @@ angular.module('application.router', ['ui.router'])
|
||||
templateUrl: '<%= asset_path "admin/admins/new.html" %>',
|
||||
controller: 'NewAdminController'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: ['Translations', function (Translations) { return Translations.query('app.admin.admins_new').$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -1028,8 +943,7 @@ angular.module('application.router', ['ui.router'])
|
||||
},
|
||||
resolve: {
|
||||
mappingFieldsPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.mapping_fields().$promise; }],
|
||||
authProvidersPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.query().$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.admin.authentication_new', 'app.shared.authentication', 'app.shared.oauth2']).$promise; }]
|
||||
authProvidersPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.query().$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.authentication_edit', {
|
||||
@ -1042,8 +956,7 @@ angular.module('application.router', ['ui.router'])
|
||||
},
|
||||
resolve: {
|
||||
providerPromise: ['AuthProvider', '$stateParams', function (AuthProvider, $stateParams) { return AuthProvider.get({ id: $stateParams.id }).$promise; }],
|
||||
mappingFieldsPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.mapping_fields().$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query(['app.admin.authentication_edit', 'app.shared.authentication', 'app.shared.oauth2']).$promise; }]
|
||||
mappingFieldsPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.mapping_fields().$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -1058,8 +971,7 @@ angular.module('application.router', ['ui.router'])
|
||||
},
|
||||
resolve: {
|
||||
membersPromise: ['Member', function (Member) { return Member.mapping().$promise; }],
|
||||
statisticsPromise: ['Statistics', function (Statistics) { return Statistics.query().$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query('app.admin.statistics').$promise; }]
|
||||
statisticsPromise: ['Statistics', function (Statistics) { return Statistics.query().$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.stats_graphs', {
|
||||
@ -1069,9 +981,6 @@ angular.module('application.router', ['ui.router'])
|
||||
templateUrl: '<%= asset_path "admin/statistics/graphs.html" %>',
|
||||
controller: 'GraphsController'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: ['Translations', function (Translations) { return Translations.query('app.admin.stats_graphs').$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -1121,8 +1030,7 @@ angular.module('application.router', ['ui.router'])
|
||||
cguFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'cgu-file' }).$promise; }],
|
||||
cgvFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'cgv-file' }).$promise; }],
|
||||
faviconFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'favicon-file' }).$promise; }],
|
||||
profileImageFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'profile-image-file' }).$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query('app.admin.settings').$promise; }]
|
||||
profileImageFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'profile-image-file' }).$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -1136,8 +1044,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
clientsPromise: ['OpenAPIClient', function (OpenAPIClient) { return OpenAPIClient.query().$promise; }],
|
||||
translations: ['Translations', function (Translations) { return Translations.query('app.admin.open_api_clients').$promise; }]
|
||||
clientsPromise: ['OpenAPIClient', function (OpenAPIClient) { return OpenAPIClient.query().$promise; }]
|
||||
}
|
||||
});
|
||||
}
|
||||
|
5
app/assets/javascripts/services/ical.js
Normal file
5
app/assets/javascripts/services/ical.js
Normal file
@ -0,0 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Ical', ['$resource', function ($resource) {
|
||||
return $resource('/api/ical/externals');
|
||||
}]);
|
17
app/assets/javascripts/services/icalendar.js
Normal file
17
app/assets/javascripts/services/icalendar.js
Normal file
@ -0,0 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('ICalendar', ['$resource', function ($resource) {
|
||||
return $resource('/api/i_calendar/:id',
|
||||
{ id: '@id' }, {
|
||||
events: {
|
||||
method: 'GET',
|
||||
url: '/api/i_calendar/:id/events'
|
||||
},
|
||||
sync: {
|
||||
method: 'POST',
|
||||
url: '/api/i_calendar/:id/sync',
|
||||
params: { id: '@id' }
|
||||
}
|
||||
}
|
||||
);
|
||||
}]);
|
@ -12,6 +12,10 @@
|
||||
.bg-stage { background-color: $violet; }
|
||||
.bg-success { background-color: $brand-success; }
|
||||
.bg-info { background-color: $brand-info; }
|
||||
.border-machine { border-color: $beige !important; }
|
||||
.border-space { border-color: $cyan !important; }
|
||||
.border-formation { border-color: $violet !important; }
|
||||
.border-event { border-color: $japonica !important; }
|
||||
|
||||
.bg-black-light { background-color: #424242 !important; }
|
||||
|
||||
|
@ -290,6 +290,11 @@
|
||||
@include border-radius(3px);
|
||||
padding: 5px 10px;
|
||||
}
|
||||
&.well-disabled {
|
||||
border-color: $gray-lighter;
|
||||
background-color: $gray-lighter;
|
||||
color: $gray-light;
|
||||
}
|
||||
}
|
||||
|
||||
.read {
|
||||
@ -629,3 +634,42 @@ padding: 10px;
|
||||
.help-block.error {
|
||||
color: #ff565d;
|
||||
}
|
||||
|
||||
.disabled {
|
||||
background-color: $gray-lighter;
|
||||
color: $gray-light;
|
||||
|
||||
& a {
|
||||
color: $gray;
|
||||
}
|
||||
|
||||
.canceled-marker {
|
||||
float: right;
|
||||
top: -13px;
|
||||
position: relative;
|
||||
color: red;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
.calendar-legend-block {
|
||||
text-align: right;
|
||||
padding-right: 2em;
|
||||
|
||||
h4 {
|
||||
font-size: 12px;
|
||||
font-style: italic;
|
||||
}
|
||||
.legends {
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
.calendar-legend {
|
||||
border: 1px solid;
|
||||
border-left: 3px solid;
|
||||
border-radius: 3px;
|
||||
font-size: 10px;
|
||||
padding: 2px;
|
||||
margin-left: 10px;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
@ -101,7 +101,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
body.container{
|
||||
padding: 0;
|
||||
}
|
||||
|
@ -126,6 +126,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
.fc-selected {
|
||||
box-shadow: 0 6px 10px 0 rgba(0,0,0,0.14),0 1px 18px 0 rgba(0,0,0,0.12),0 3px 5px -1px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -102,6 +102,7 @@ p, .widget p {
|
||||
|
||||
.text-italic { font-style: italic; }
|
||||
|
||||
.text-left { text-align: left !important; }
|
||||
.text-center { text-align: center; }
|
||||
.text-right { text-align: right; }
|
||||
|
||||
@ -379,6 +380,10 @@ p, .widget p {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media screen and (min-width: $screen-lg-min) {
|
||||
.b-r-lg {border-right: 1px solid $border-color; }
|
||||
.hide-b-r-lg { border: none !important; }
|
||||
|
@ -32,11 +32,7 @@
|
||||
@import "app.buttons";
|
||||
@import "app.components";
|
||||
@import "app.plugins";
|
||||
@import "modules/invoice";
|
||||
@import "modules/signup";
|
||||
@import "modules/abuses";
|
||||
@import "modules/cookies";
|
||||
@import "modules/stripe";
|
||||
@import "modules/*";
|
||||
|
||||
@import "app.responsive";
|
||||
|
||||
|
24
app/assets/stylesheets/modules/icalendar.scss
Normal file
24
app/assets/stylesheets/modules/icalendar.scss
Normal file
@ -0,0 +1,24 @@
|
||||
.calendar-form {
|
||||
margin : 2em;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 3px;
|
||||
padding: 1em;
|
||||
|
||||
& > .input-group, & > .minicolors {
|
||||
margin-top: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.calendar-name {
|
||||
font-weight: 600;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.calendar-url {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.external-calendar-legend {
|
||||
border-left: 3px solid;
|
||||
border-radius: 3px;
|
||||
}
|
@ -7,7 +7,7 @@
|
||||
</div>
|
||||
<div class="col-xs-10 col-sm-10 col-md-8 b-l">
|
||||
<section class="heading-title">
|
||||
<h1 translate>{{ 'manage_abuses.abuses_list' }}</h1>
|
||||
<h1 translate>{{ 'app.admin.manage_abuses.abuses_list' }}</h1>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
@ -15,24 +15,24 @@
|
||||
|
||||
<section class="m-lg">
|
||||
<div class="row m-b-md">
|
||||
<span ng-show="abuses.length === 0" translate>{{ 'manage_abuses.no_reports' }}</span>
|
||||
<span ng-show="abuses.length === 0" translate>{{ 'app.admin.manage_abuses.no_reports' }}</span>
|
||||
<ul ng-show="abuses.length > 0">
|
||||
<li class="abuse" ng-repeat="abuse in abuses">
|
||||
<div class="signaled">
|
||||
<a ui-sref="app.public.projects_show({id:abuse.signaled.slug})">{{abuse.signaled.name}}</a>,
|
||||
<span translate>{{ 'manage_abuses.published_by' }}</span>
|
||||
<span translate>{{ 'app.admin.manage_abuses.published_by' }}</span>
|
||||
<a ui-sref="app.admin.members_edit({id:abuse.signaled.author.id})">{{abuse.signaled.author.full_name}}</a>,
|
||||
<span translate>{{ 'manage_abuses.at_date' }}</span>
|
||||
<span translate>{{ 'app.admin.manage_abuses.at_date' }}</span>
|
||||
<span>{{abuse.signaled.published_at | amDateFormat:'L' }}</span>
|
||||
<button class="btn btn-success" ng-click="confirmProcess(abuse.id)">
|
||||
<i class="fa fa-check"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="report">
|
||||
<span translate>{{ 'manage_abuses.at_date' }}</span>
|
||||
<span translate>{{ 'app.admin.manage_abuses.at_date' }}</span>
|
||||
<span>{{abuse.created_at | amDateFormat:'L' }}</span>,
|
||||
<a href="mailto:{{abuse.email}}">{{abuse.first_name}} {{abuse.last_name}}</a>
|
||||
<span translate>{{ 'manage_abuses.has_reported' }}</span>
|
||||
<span translate>{{ 'app.admin.manage_abuses.has_reported' }}</span>
|
||||
<cite>{{ abuse.message }}</cite>
|
||||
</div>
|
||||
</li>
|
||||
|
@ -7,7 +7,7 @@
|
||||
</div>
|
||||
<div class="col-xs-10 col-sm-10 col-md-8 b-l">
|
||||
<section class="heading-title">
|
||||
<h1 translate>{{ 'add_an_administrator' }}</h1>
|
||||
<h1 translate>{{ 'app.admin.admins_new.add_an_administrator' }}</h1>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@ -20,12 +20,12 @@
|
||||
<form role="form" name="adminForm" class="form-horizontal" novalidate>
|
||||
<section class="panel panel-default bg-light m-lg">
|
||||
<div class="panel-body m-r">
|
||||
<ng-include src="'<%= asset_path 'shared/_admin_form.html' %>'"></ng-include>
|
||||
<ng-include src="'<%= asset_path "shared/_admin_form.html" %>'"></ng-include>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="panel-footer no-padder">
|
||||
<input type="submit" value="{{ 'save' | translate}}" class="r-b btn-valid btn btn-warning btn-block p-lg btn-lg text-u-c" ng-click="saveAdmin()" ng-disabled="adminForm.$invalid"/>
|
||||
<input type="submit" value="{{ 'app.shared.buttons.save' | translate}}" class="r-b btn-valid btn btn-warning btn-block p-lg btn-lg text-u-c" ng-click="saveAdmin()" ng-disabled="adminForm.$invalid"/>
|
||||
</div>
|
||||
</section>
|
||||
</form>
|
||||
|
@ -1,16 +1,16 @@
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title"><span translate>{{ 'data_mapping' }}</span> : {{field.local_field}}</h3>
|
||||
<h3 class="modal-title"><span translate>{{ 'app.shared.authentication.data_mapping' }}</span> : {{field.local_field}}</h3>
|
||||
</div>
|
||||
<div class="modal-body m-lg">
|
||||
<div>
|
||||
<span translate>{{ 'expected_data_type' }}</span> : {{datatype}}
|
||||
<span translate>{{ 'app.shared.authentication.expected_data_type' }}</span> : {{datatype}}
|
||||
</div>
|
||||
<form name="mappingForm" class="m-t-md">
|
||||
<ng-switch on="datatype">
|
||||
|
||||
<!-- BOOLEAN -->
|
||||
<div ng-switch-when="boolean">
|
||||
<label for="add_mapping" translate>{{ 'mappings' }}</label>
|
||||
<label for="add_mapping" translate>{{ 'app.shared.authentication.mappings' }}</label>
|
||||
<ul class="list-unstyled">
|
||||
<li class="m-t-sm m-l">
|
||||
<input type="text"
|
||||
@ -35,7 +35,7 @@
|
||||
|
||||
<!-- DATE -->
|
||||
<div ng-switch-when="date">
|
||||
<label for="date_format" translate>{{ 'input_format' }}</label>
|
||||
<label for="date_format" translate>{{ 'app.shared.authentication.input_format' }}</label>
|
||||
<select name="date_format"
|
||||
id="date_format"
|
||||
class="form-control"
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
<!-- INTEGER -->
|
||||
<div ng-switch-when="integer">
|
||||
<label for="add_mapping" translate>{{ 'mappings' }}</label>
|
||||
<label for="add_mapping" translate>{{ 'app.shared.authentication.mappings' }}</label>
|
||||
<button class="btn btn-default pull-right" ng-click="addIntegerMapping()"><i class="fa fa-plus"></i></button>
|
||||
<ul class="list-unstyled">
|
||||
<li ng-repeat="map in transformation.rules.mapping" class="m-t-sm m-l">
|
||||
@ -60,6 +60,6 @@
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-primary" ng-click="ok()" ng-disabled="!mappingForm.$valid" ng-if="datatype != 'string' && datatype != 'text'" translate>{{ 'confirm' }}</button>
|
||||
<button class="btn btn-warning" ng-click="cancel()" translate>{{ 'cancel' }}</button>
|
||||
<button class="btn btn-primary" ng-click="ok()" ng-disabled="!mappingForm.$valid" ng-if="datatype != 'string' && datatype != 'text'" translate>{{ 'app.shared.buttons.confirm' }}</button>
|
||||
<button class="btn btn-warning" ng-click="cancel()" translate>{{ 'app.shared.buttons.cancel' }}</button>
|
||||
</div>
|
@ -1,5 +1,5 @@
|
||||
<div class="form-group" ng-class="{'has-error': providerForm['auth_provider[name]'].$dirty && providerForm['auth_provider[name]'].$invalid}">
|
||||
<label for="provider_name" class="col-sm-3 control-label" translate>{{ 'name' }}</label>
|
||||
<label for="provider_name" class="col-sm-3 control-label" translate>{{ 'app.shared.authentication.name' }}</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text"
|
||||
ng-model="provider.name"
|
||||
@ -8,23 +8,23 @@
|
||||
id="provider_name"
|
||||
ng-disabled="mode == 'edition'"
|
||||
required />
|
||||
<span class="help-block" ng-show="providerForm['auth_provider[name]'].$dirty && providerForm['auth_provider[name]'].$error.required" translate>{{ 'provider_name_is_required' }}</span>
|
||||
<span class="help-block" ng-show="providerForm['auth_provider[name]'].$dirty && providerForm['auth_provider[name]'].$error.required" translate>{{ 'app.shared.authentication.provider_name_is_required' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{'has-error': providerForm['auth_provider[providable_type]'].$dirty && providerForm['auth_provider[providable_type]'].$invalid}">
|
||||
<label for="provider_type" class="col-sm-3 control-label" translate>{{ 'authentication_type' }}</label>
|
||||
<label for="provider_type" class="col-sm-3 control-label" translate>{{ 'app.shared.authentication.authentication_type' }}</label>
|
||||
<div class="col-sm-9">
|
||||
<select ng-model="provider.providable_type"
|
||||
ng-change="updateProvidable()"
|
||||
class="form-control"
|
||||
name="auth_provider[providable_type]"
|
||||
id="provider_type"
|
||||
ng-options="key as (value | translate) for (key, value) in authMethods"
|
||||
ng-options="key as methodName(key) for (key, value) in authMethods"
|
||||
ng-disabled="mode == 'edition'"
|
||||
required>
|
||||
</select>
|
||||
<input type="hidden" name="auth_provider[type]" ng-value="provider.type" />
|
||||
<span class="help-block" ng-show="providerForm['auth_provider[providable_type]'].$dirty && providerForm['auth_provider[providable_type]'].$error.required" translate>{{ 'authentication_type_is_required' }}</span>
|
||||
<span class="help-block" ng-show="providerForm['auth_provider[providable_type]'].$dirty && providerForm['auth_provider[providable_type]'].$error.required" translate>{{ 'app.shared.authentication.authentication_type_is_required' }}</span>
|
||||
</div>
|
||||
</div>
|
@ -1,7 +1,7 @@
|
||||
<hr/>
|
||||
|
||||
<div class="form-group" ng-class="{'has-error': providerForm['auth_provider[base_url]'].$dirty && providerForm['auth_provider[base_url]'].$invalid}">
|
||||
<label for="provider_base_url" class="col-sm-3 control-label" translate>{{ 'common_url' }}</label>
|
||||
<label for="provider_base_url" class="col-sm-3 control-label" translate>{{ 'app.shared.oauth2.common_url' }}</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text"
|
||||
ng-model="provider.providable_attributes.base_url"
|
||||
@ -11,13 +11,13 @@
|
||||
placeholder="https://sso.example.net..."
|
||||
required
|
||||
url>
|
||||
<span class="help-block" ng-show="providerForm['auth_provider[base_url]'].$dirty && providerForm['auth_provider[base_url]'].$error.required" translate>{{ 'common_url_is_required' }}</span>
|
||||
<span class="help-block" ng-show="providerForm['auth_provider[base_url]'].$error.url" translate>{{ 'provided_url_is_not_a_valid_url' }}</span>
|
||||
<span class="help-block" ng-show="providerForm['auth_provider[base_url]'].$dirty && providerForm['auth_provider[base_url]'].$error.required" translate>{{ 'app.shared.oauth2.common_url_is_required' }}</span>
|
||||
<span class="help-block" ng-show="providerForm['auth_provider[base_url]'].$error.url" translate>{{ 'app.shared.oauth2.provided_url_is_not_a_valid_url' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{'has-error': providerForm['auth_provider[authorization_endpoint]'].$dirty && providerForm['auth_provider[authorization_endpoint]'].$invalid}">
|
||||
<label for="provider_authorization_endpoint" class="col-sm-3 control-label" translate>{{ 'authorization_endpoint' }}</label>
|
||||
<label for="provider_authorization_endpoint" class="col-sm-3 control-label" translate>{{ 'app.shared.oauth2.authorization_endpoint' }}</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text"
|
||||
ng-model="provider.providable_attributes.authorization_endpoint"
|
||||
@ -27,13 +27,13 @@
|
||||
placeholder="/oauth2/auth..."
|
||||
required
|
||||
endpoint>
|
||||
<span class="help-block" ng-show="providerForm['auth_provider[authorization_endpoint]'].$dirty && providerForm['auth_provider[authorization_url]'].$error.required" translate>{{ 'oauth2_authorization_endpoint_is_required' }}</span>
|
||||
<span class="help-block" ng-show="providerForm['auth_provider[authorization_endpoint]'].$error.endpoint" translate>{{ 'provided_endpoint_is_not_valid' }}</span>
|
||||
<span class="help-block" ng-show="providerForm['auth_provider[authorization_endpoint]'].$dirty && providerForm['auth_provider[authorization_url]'].$error.required" translate>{{ 'app.shared.oauth2.oauth2_authorization_endpoint_is_required' }}</span>
|
||||
<span class="help-block" ng-show="providerForm['auth_provider[authorization_endpoint]'].$error.endpoint" translate>{{ 'app.shared.oauth2.provided_endpoint_is_not_valid' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{'has-error': providerForm['auth_provider[token_endpoint]'].$dirty && providerForm['auth_provider[token_endpoint]'].$invalid}">
|
||||
<label for="provider_token_endpoint" class="col-sm-3 control-label" translate>{{ 'token_acquisition_endpoint' }}</label>
|
||||
<label for="provider_token_endpoint" class="col-sm-3 control-label" translate>{{ 'app.shared.oauth2.token_acquisition_endpoint' }}</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text"
|
||||
ng-model="provider.providable_attributes.token_endpoint"
|
||||
@ -43,13 +43,13 @@
|
||||
placeholder="/oauth2/token..."
|
||||
required
|
||||
endpoint>
|
||||
<span class="help-block" ng-show="providerForm['auth_provider[token_endpoint]'].$dirty && providerForm['auth_provider[token_endpoint]'].$error.required" translate>{{ 'oauth2_token_acquisition_endpoint_is_required' }}</span>
|
||||
<span class="help-block" ng-show="providerForm['auth_provider[token_endpoint]'].$error.endpoint" translate>{{ 'provided_endpoint_is_not_valid' }}</span>
|
||||
<span class="help-block" ng-show="providerForm['auth_provider[token_endpoint]'].$dirty && providerForm['auth_provider[token_endpoint]'].$error.required" translate>{{ 'app.shared.oauth2.oauth2_token_acquisition_endpoint_is_required' }}</span>
|
||||
<span class="help-block" ng-show="providerForm['auth_provider[token_endpoint]'].$error.endpoint" translate>{{ 'app.shared.oauth2.provided_endpoint_is_not_valid' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{'has-error': providerForm['auth_provider[profile_url]'].$dirty && providerForm['auth_provider[profile_url]'].$invalid}">
|
||||
<label for="provider_profile_url" class="col-sm-3 control-label" translate>{{ 'profil_edition_url' }}</label>
|
||||
<label for="provider_profile_url" class="col-sm-3 control-label" translate>{{ 'app.shared.oauth2.profil_edition_url' }}</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text"
|
||||
ng-model="provider.providable_attributes.profile_url"
|
||||
@ -59,13 +59,13 @@
|
||||
placeholder="https://exemple.net/user..."
|
||||
required
|
||||
url>
|
||||
<span class="help-block" ng-show="providerForm['auth_provider[profile_url]'].$dirty && providerForm['auth_provider[profile_url]'].$error.required" translate>{{ 'profile_edition_url_is_required' }}</span>
|
||||
<span class="help-block" ng-show="providerForm['auth_provider[profile_url]'].$error.url" translate>{{ 'provided_url_is_not_a_valid_url' }}</span>
|
||||
<span class="help-block" ng-show="providerForm['auth_provider[profile_url]'].$dirty && providerForm['auth_provider[profile_url]'].$error.required" translate>{{ 'app.shared.oauth2.profile_edition_url_is_required' }}</span>
|
||||
<span class="help-block" ng-show="providerForm['auth_provider[profile_url]'].$error.url" translate>{{ 'app.shared.oauth2.provided_url_is_not_a_valid_url' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{'has-error': providerForm['auth_provider[client_id]'].$dirty && providerForm['auth_provider[client_id]'].$invalid}">
|
||||
<label for="provider_client_id" class="col-sm-3 control-label" translate>{{ 'client_identifier' }}</label>
|
||||
<label for="provider_client_id" class="col-sm-3 control-label" translate>{{ 'app.shared.oauth2.client_identifier' }}</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text"
|
||||
ng-model="provider.providable_attributes.client_id"
|
||||
@ -73,12 +73,12 @@
|
||||
name="auth_provider[client_id]"
|
||||
id="provider_client_id"
|
||||
required>
|
||||
<span class="help-block" ng-show="providerForm['auth_provider[client_id]'].$dirty && providerForm['auth_provider[client_id]'].$error.required" translate>{{ 'oauth2_client_identifier_is_required' }} {{ 'obtain_it_when_registering_with_your_provider' }}</span>
|
||||
<span class="help-block" ng-show="providerForm['auth_provider[client_id]'].$dirty && providerForm['auth_provider[client_id]'].$error.required" translate>{{ 'app.shared.oauth2.oauth2_client_identifier_is_required' }} {{ 'obtain_it_when_registering_with_your_provider' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{'has-error': providerForm['auth_provider[client_secret]'].$dirty && providerForm['auth_provider[client_secret]'].$invalid}">
|
||||
<label for="provider_client_secret" class="col-sm-3 control-label" translate>{{ 'client_secret' }}</label>
|
||||
<label for="provider_client_secret" class="col-sm-3 control-label" translate>{{ 'app.shared.oauth2.client_secret' }}</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text"
|
||||
ng-model="provider.providable_attributes.client_secret"
|
||||
@ -86,8 +86,8 @@
|
||||
name="auth_provider[client_secret]"
|
||||
id="provider_client_secret"
|
||||
required>
|
||||
<span class="help-block" ng-show="providerForm['auth_provider[client_secret]'].$dirty && providerForm['auth_provider[client_secret]'].$error.required" translate>{{ 'oauth2_client_secret_is_required' }} {{ 'obtain_it_when_registering_with_your_provider' }}</span>
|
||||
<span class="help-block" ng-show="providerForm['auth_provider[client_secret]'].$dirty && providerForm['auth_provider[client_secret]'].$error.required" translate>{{ 'app.shared.oauth2.oauth2_client_secret_is_required' }} {{ 'obtain_it_when_registering_with_your_provider' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ng-include src="'<%= asset_path 'admin/authentications/_oauth2_mapping.html' %>'"></ng-include>
|
||||
<ng-include src="'<%= asset_path "admin/authentications/_oauth2_mapping.html" %>'"></ng-include>
|
||||
|
@ -1,15 +1,15 @@
|
||||
<h4 class="m-l m-t-xl" translate>{{ 'define_the_fields_mapping' }}</h4>
|
||||
<h4 class="m-l m-t-xl" translate>{{ 'app.shared.oauth2.define_the_fields_mapping' }}</h4>
|
||||
|
||||
|
||||
<button type="button" class="btn btn-success m-l m-b" ng-click="newMapping = {}"><i class="fa fa-plus"></i> {{ 'add_a_match' | translate }}</button>
|
||||
<button type="button" class="btn btn-success m-l m-b" ng-click="newMapping = {}"><i class="fa fa-plus"></i> {{ 'app.shared.oauth2.add_a_match' | translate }}</button>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th translate>{{ 'model' }}</th>
|
||||
<th translate>{{ 'field' }}</th>
|
||||
<th translate>{{ 'api_endpoint_url' }}</th>
|
||||
<th translate>{{ 'api_type' }}</th>
|
||||
<th translate>{{ 'api_fields' }}</th>
|
||||
<th translate>{{ 'app.shared.oauth2.model' }}</th>
|
||||
<th translate>{{ 'app.shared.oauth2.field' }}</th>
|
||||
<th translate>{{ 'app.shared.oauth2.api_endpoint_url' }}</th>
|
||||
<th translate>{{ 'app.shared.oauth2.api_type' }}</th>
|
||||
<th translate>{{ 'app.shared.oauth2.api_fields' }}</th>
|
||||
<th style="width: 6.4em;"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -9,7 +9,7 @@
|
||||
</div>
|
||||
<div class="col-md-8 b-l b-r">
|
||||
<section class="heading-title">
|
||||
<h1>{{ 'provider' | translate }} {{provider.name}}</h1>
|
||||
<h1>{{ 'app.admin.authentication_edit.provider' | translate }} {{provider.name}}</h1>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
@ -17,7 +17,7 @@
|
||||
<div class="col-md-3">
|
||||
<section class="heading-actions wrapper">
|
||||
<div class="btn btn-lg btn-block btn-default m-t-xs" ng-click="cancel()" translate>
|
||||
{{ 'cancel' }}
|
||||
{{ 'app.shared.buttons.cancel' }}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@ -35,13 +35,13 @@
|
||||
|
||||
<section class="panel panel-default bg-light m-lg">
|
||||
<div class="panel-body m-r">
|
||||
<ng-include src="'<%= asset_path 'admin/authentications/_form.html' %>'"></ng-include>
|
||||
<ng-include src="'<%= asset_path 'admin/authentications/_oauth2.html'%>'" ng-if="provider.providable_type == 'OAuth2Provider'"></ng-include>
|
||||
<ng-include src="'<%= asset_path "admin/authentications/_form.html" %>'"></ng-include>
|
||||
<ng-include src="'<%= asset_path "admin/authentications/_oauth2.html"%>'" ng-if="provider.providable_type == 'OAuth2Provider'"></ng-include>
|
||||
</div> <!-- ./panel-body -->
|
||||
|
||||
|
||||
<div class="panel-footer no-padder">
|
||||
<input type="button" value="{{ 'confirm_changes' | translate }}" class="r-b btn-valid btn btn-warning btn-block p-lg btn-lg text-u-c" ng-disabled="providerForm.$invalid" ng-click="updateProvider()"/>
|
||||
<input type="button" value="{{ 'app.shared.buttons.confirm_changes' | translate }}" class="r-b btn-valid btn btn-warning btn-block p-lg btn-lg text-u-c" ng-disabled="providerForm.$invalid" ng-click="updateProvider()"/>
|
||||
</div>
|
||||
</section>
|
||||
</form>
|
||||
|
@ -2,23 +2,23 @@
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="fa fa-filter"></i></span>
|
||||
<input type="text" ng-model="searchFilter" class="form-control" placeholder="{{ 'search_for_an_authentication_provider' | translate }}">
|
||||
<input type="text" ng-model="searchFilter" class="form-control" placeholder="{{ 'app.admin.members.authentication_form.search_for_an_authentication_provider' | translate }}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<button type="button" class="btn btn-warning m-t m-b" ui-sref="app.admin.authentication_new" translate>{{ 'add_a_new_authentication_provider' }}</button>
|
||||
<button type="button" class="btn btn-warning m-t m-b" ui-sref="app.admin.authentication_new" translate>{{ 'app.admin.members.authentication_form.add_a_new_authentication_provider' }}</button>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:15%" translate>{{ 'name' }}</th>
|
||||
<th style="width:15%" translate>{{ 'app.admin.members.authentication_form.name' }}</th>
|
||||
|
||||
<th style="width:15%" translate>{{ 'strategy_name' }}</th>
|
||||
<th style="width:15%" translate>{{ 'app.admin.members.authentication_form.strategy_name' }}</th>
|
||||
|
||||
<th style="width:15%" translate>{{ 'type' }}</th>
|
||||
<th style="width:15%" translate>{{ 'app.admin.members.authentication_form.type' }}</th>
|
||||
|
||||
<th style="width:15%" translate>{{ 'state' }}</th>
|
||||
<th style="width:15%" translate>{{ 'app.admin.members.authentication_form.state' }}</th>
|
||||
|
||||
<th style="width:10%"></th>
|
||||
</tr>
|
||||
@ -31,7 +31,7 @@
|
||||
<td>{{ getState(provider.status) }}</td>
|
||||
<td>
|
||||
<button class="btn btn-default" ui-sref="app.admin.authentication_edit({id:provider.id})">
|
||||
<i class="fa fa-pencil-square-o"></i> {{ 'edit' | translate }}
|
||||
<i class="fa fa-pencil-square-o"></i> {{ 'app.shared.buttons.edit' | translate }}
|
||||
</button>
|
||||
<button class="btn btn-danger" ng-if="provider.status != 'active'" ng-click="destroyProvider(providers, provider)">
|
||||
<i class="fa fa-trash-o"></i>
|
||||
|
@ -9,7 +9,7 @@
|
||||
</div>
|
||||
<div class="col-md-8 b-l b-r">
|
||||
<section class="heading-title">
|
||||
<h1 translate>{{ 'add_a_new_authentication_provider' }}</h1>
|
||||
<h1 translate>{{ 'app.admin.authentication_new.add_a_new_authentication_provider' }}</h1>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
@ -17,7 +17,7 @@
|
||||
<div class="col-md-3">
|
||||
<section class="heading-actions wrapper">
|
||||
<div class="btn btn-lg btn-block btn-default m-t-xs" ng-click="cancel()" translate>
|
||||
{{ 'cancel' }}
|
||||
{{ 'app.shared.buttons.cancel' }}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@ -36,13 +36,13 @@
|
||||
<section class="panel panel-default bg-light m-lg">
|
||||
<div class="panel-body m-r">
|
||||
|
||||
<ng-include src="'<%= asset_path 'admin/authentications/_form.html' %>'"></ng-include>
|
||||
<ng-include src="'<%= asset_path 'admin/authentications/_oauth2.html'%>'" ng-if="provider.providable_type == 'OAuth2Provider'"></ng-include>
|
||||
<ng-include src="'<%= asset_path "admin/authentications/_form.html" %>'"></ng-include>
|
||||
<ng-include src="'<%= asset_path "admin/authentications/_oauth2.html" %>'" ng-if="provider.providable_type == 'OAuth2Provider'"></ng-include>
|
||||
</div> <!-- ./panel-body -->
|
||||
|
||||
|
||||
<div class="panel-footer no-padder">
|
||||
<input type="button" value="{{ 'save' | translate }}" class="r-b btn-valid btn btn-warning btn-block p-lg btn-lg text-u-c" ng-disabled="providerForm.$invalid" ng-click="registerProvider()"/>
|
||||
<input type="button" value="{{ 'app.shared.buttons.save' | translate }}" class="r-b btn-valid btn btn-warning btn-block p-lg btn-lg text-u-c" ng-disabled="providerForm.$invalid" ng-click="registerProvider()"/>
|
||||
</div>
|
||||
</section>
|
||||
</form>
|
||||
|
@ -5,17 +5,17 @@
|
||||
<a href="#" ng-click="backPrevLocation($event)"><i class="fa fa-long-arrow-left "></i></a>
|
||||
</section>
|
||||
</div>
|
||||
<div class="col-xs-10 col-sm-10 col-md-8 b-l b-r-md">
|
||||
<div class="col-xs-10 b-l b-r-md">
|
||||
<section class="heading-title">
|
||||
<h1 translate>{{ 'admin_calendar.calendar_management' }}</h1>
|
||||
<h1 translate>{{ 'app.admin.calendar.calendar_management' }}</h1>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-sm-12 col-md-3 b-t hide-b-md">
|
||||
<section class="heading-actions wrapper" ng-class="{'p-s': !fablabWithoutSpaces}">
|
||||
<span class="badge text-sm bg-formation" ng-class="{'m-t-sm': fablabWithoutSpaces}" translate>{{ 'admin_calendar.trainings' }}</span><br>
|
||||
<span class="badge text-sm bg-machine" translate>{{ 'admin_calendar.machines' }}</span><br>
|
||||
<span class="badge text-sm bg-space" ng-hide="fablabWithoutSpaces" translate>{{ 'admin_calendar.spaces' }}</span>
|
||||
<div class="col-xs-1">
|
||||
<section class="heading-actions wrapper">
|
||||
<a role="button" ui-sref="app.admin.calendar.icalendar" class="btn btn-default b-2x rounded pointer m-t-sm">
|
||||
<i class="fa fa-exchange" aria-hidden="true"></i>
|
||||
</a>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@ -27,6 +27,15 @@
|
||||
|
||||
<div class="col-sm-12 col-md-12 col-lg-9">
|
||||
<div ui-calendar="calendarConfig" ng-model="eventSources" calendar="calendar" class="wrapper-lg"></div>
|
||||
<div class="calendar-legend-block">
|
||||
<h4 translate>{{ 'app.admin.calendar.legend' }}</h4>
|
||||
<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-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-event" ng-show="eventsInCalendar" translate>{{ 'app.admin.calendar.events' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 col-md-12 col-lg-3">
|
||||
@ -35,17 +44,17 @@
|
||||
ng-href="api/availabilities/export_index.xlsx"
|
||||
target="export-frame"
|
||||
ng-click="alertExport('index')"
|
||||
uib-popover="{{ 'admin_calendar.availabilities_notice' | translate}}"
|
||||
uib-popover="{{ 'app.admin.calendar.availabilities_notice' | translate}}"
|
||||
popover-trigger="mouseenter"
|
||||
popover-placement="bottom">
|
||||
<i class="fa fa-file-excel-o"></i> {{ 'admin_calendar.availabilities' | translate }}
|
||||
<i class="fa fa-file-excel-o"></i> {{ 'app.admin.calendar.availabilities' | translate }}
|
||||
</a>
|
||||
<iframe name="export-frame" height="0" width="0" class="none"></iframe>
|
||||
</div>
|
||||
|
||||
<div class="widget panel b-a m m-t-lg" ng-if="availability">
|
||||
<div class="widget panel b-a m m-t-lg" ng-if="availability" ng-hide="availability.available_type == 'event'">
|
||||
<div class="panel-heading b-b small">
|
||||
<h3 translate>{{ 'admin_calendar.ongoing_reservations' }}</h3>
|
||||
<h3 translate>{{ 'app.admin.calendar.ongoing_reservations' }}</h3>
|
||||
</div>
|
||||
<div class="widget-content no-bg auto wrapper" ng-class="{'reservations-locked': availability.lock}">
|
||||
<ul class="list-unstyled" ng-if="reservations.length > 0">
|
||||
@ -56,14 +65,14 @@
|
||||
<span class="btn btn-warning btn-xs" ng-click="cancelBooking(r)" ng-if="!r.canceled_at"><i class="fa fa-times red"></i></span>
|
||||
</li>
|
||||
</ul>
|
||||
<div ng-show="reservations.length == 0" translate>{{ 'admin_calendar.no_reservations' }}</div>
|
||||
<div class="m-t" ng-show="availability.lock"><i class="fa fa-ban"/> <span class="m-l-xs" translate>{{ 'admin_calendar.reservations_locked' }}</span></div>
|
||||
<div ng-show="reservations.length == 0" translate>{{ 'app.admin.calendar.no_reservations' }}</div>
|
||||
<div class="m-t" ng-show="availability.lock"><i class="fa fa-ban"></i> <span class="m-l-xs" translate>{{ 'app.admin.calendar.reservations_locked' }}</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="widget panel b-a m m-t-lg" ng-if="availability.machine_ids.length > 0">
|
||||
<div class="panel-heading b-b small">
|
||||
<h3 translate>{{ 'admin_calendar.machines' }}</h3>
|
||||
<h3 translate>{{ 'app.admin.calendar.machines' }}</h3>
|
||||
</div>
|
||||
<div class="widget-content no-bg auto wrapper">
|
||||
<ul class="list-unstyled">
|
||||
@ -75,28 +84,42 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="widget panel b-a m m-t-lg" ng-if="availability">
|
||||
<div class="widget panel b-a m m-t-lg" ng-if="availability" >
|
||||
<div class="panel-heading b-b small">
|
||||
<h3 translate>{{ 'admin_calendar.actions' }}</h3>
|
||||
<h3 translate>{{ 'app.admin.calendar.actions' }}</h3>
|
||||
</div>
|
||||
<div class="widget-content no-bg auto wrapper">
|
||||
<div class="widget-content no-bg auto wrapper" ng-hide="availability.available_type == 'event'">
|
||||
<button class="btn btn-default" ng-click="toggleLockReservations()">
|
||||
<span ng-hide="availability.lock">
|
||||
<i class="fa fa-stop" />
|
||||
<span class="m-l-xs" translate>{{ 'admin_calendar.block_reservations' }}</span>
|
||||
<i class="fa fa-stop"></i>
|
||||
<span class="m-l-xs" translate>{{ 'app.admin.calendar.block_reservations' }}</span>
|
||||
</span>
|
||||
<span ng-show="availability.lock">
|
||||
<i class="fa fa-play" />
|
||||
<span class="m-l-xs" translate>{{ 'admin_calendar.allow_reservations' }}</span>
|
||||
<i class="fa fa-play"></i>
|
||||
<span class="m-l-xs" translate>{{ 'app.admin.calendar.allow_reservations' }}</span>
|
||||
</span>
|
||||
</button>
|
||||
<button class="btn btn-default m-t" ng-click="removeSlot()">
|
||||
<span>
|
||||
<i class="fa fa-trash" />
|
||||
<span class="m-l-xs" translate>{{ 'admin_calendar.delete_slot' }}</span>
|
||||
<i class="fa fa-trash"></i>
|
||||
<span class="m-l-xs" translate>{{ 'app.admin.calendar.delete_slot' }}</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="widget-content no-bg auto wrapper" ng-show="availability.available_type == 'event'">
|
||||
<a class="btn btn-default pointer" ui-sref="app.admin.events_edit({id: availability.event_id})">
|
||||
<span>
|
||||
<i class="fa fa-edit"></i>
|
||||
<span class="m-l-xs" translate>{{ 'app.admin.calendar.edit_event' }}</span>
|
||||
</span>
|
||||
</a>
|
||||
<a class="btn btn-default m-t pointer" ui-sref="app.admin.event_reservations({id: availability.event_id})">
|
||||
<span>
|
||||
<i class="fa fa-bookmark"></i>
|
||||
<span class="m-l-xs" translate>{{ 'app.admin.calendar.view_reservations' }}</span>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
26
app/assets/templates/admin/calendar/deleteRecurrent.html
Normal file
26
app/assets/templates/admin/calendar/deleteRecurrent.html
Normal file
@ -0,0 +1,26 @@
|
||||
<div class="modal-header">
|
||||
<img ng-src="{{logoBlack.custom_asset_file_attributes.attachment_url}}" alt="{{logo.custom_asset_file_attributes.attachment}}" class="modal-logo"/>
|
||||
<h1 translate>{{ 'app.admin.calendar.confirmation_required' }}</h1>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p ng-hide="isRecurrent" translate>{{ 'app.admin.calendar.do_you_really_want_to_delete_this_slot' }}</p>
|
||||
<p ng-show="isRecurrent" translate>{{ 'app.admin.calendar.delete_recurring_slot' }}</p>
|
||||
<div ng-show="isRecurrent" class="form-group">
|
||||
<label class="checkbox">
|
||||
<input type="radio" name="delete_mode" ng-model="deleteMode" value="single" required/>
|
||||
<span translate>{{ 'app.admin.calendar.delete_this_slot' }}</span>
|
||||
</label>
|
||||
<label class="checkbox">
|
||||
<input type="radio" name="delete_mode" ng-model="deleteMode" value="next" required/>
|
||||
<span translate>{{ 'app.admin.calendar.delete_this_and_next' }}</span>
|
||||
</label>
|
||||
<label class="checkbox">
|
||||
<input type="radio" name="delete_mode" ng-model="deleteMode" value="all" required/>
|
||||
<span translate>{{ 'app.admin.calendar.delete_all' }}</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-info" ng-click="ok()" translate>{{ 'app.shared.buttons.delete' }}</button>
|
||||
<button class="btn btn-default" ng-click="cancel()" translate>{{ 'app.shared.buttons.cancel' }}</button>
|
||||
</div>
|
@ -1,27 +1,27 @@
|
||||
<div class="modal-header">
|
||||
<h3 class="text-center red">
|
||||
{{ 'admin_calendar.DATE_slot' | translate:{DATE:(start | amDateFormat: 'LL')} }} {{start | amDateFormat:'LT'}} - {{end | amDateFormat:'LT'}}
|
||||
{{ 'app.admin.calendar.DATE_slot' | translate:{DATE:(start | amDateFormat: 'LL')} }} {{start | amDateFormat:'LT'}} - {{end | amDateFormat:'LT'}}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="modal-body" ng-show="step === 1">
|
||||
<label class="m-t-sm" translate>{{ 'admin_calendar.what_kind_of_slot_do_you_want_to_create' }}</label>
|
||||
<label class="m-t-sm" translate>{{ 'app.admin.calendar.what_kind_of_slot_do_you_want_to_create' }}</label>
|
||||
<div class="form-group">
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" id="training" name="available_type" value="training" ng-model="availability.available_type">
|
||||
<span translate>{{ 'admin_calendar.training' }}</span>
|
||||
<span translate>{{ 'app.admin.calendar.training' }}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" id="machine" name="available_type" value="machines" ng-model="availability.available_type">
|
||||
<span translate>{{ 'admin_calendar.machine' }}</span>
|
||||
<span translate>{{ 'app.admin.calendar.machine' }}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio" ng-hide="fablabWithoutSpaces">
|
||||
<label>
|
||||
<input type="radio" id="space" name="available_type" value="space" ng-model="availability.available_type" ng-disabled="spaces.length === 0">
|
||||
<span translate>{{ 'admin_calendar.space' }}</span>
|
||||
<span translate>{{ 'app.admin.calendar.space' }}</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@ -29,7 +29,7 @@
|
||||
<div class="modal-body" ng-show="step === 2">
|
||||
|
||||
<div ng-show="availability.available_type == 'machines'">
|
||||
<p class="text-center font-sbold m-t-sm">{{ 'admin_calendar.select_some_machines' | translate }}</p>
|
||||
<p class="text-center font-sbold m-t-sm">{{ 'app.admin.calendar.select_some_machines' | translate }}</p>
|
||||
|
||||
<div class="form-group m-l-xl">
|
||||
<label class="checkbox" ng-repeat="machine in machines">
|
||||
@ -43,7 +43,7 @@
|
||||
</select>
|
||||
<div class="row m-t">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-6 control-label" for="nb_places_training" translate>{{ 'admin_calendar.number_of_tickets' }}</label>
|
||||
<label class="col-sm-6 control-label" for="nb_places_training" translate>{{ 'app.admin.calendar.number_of_tickets' }}</label>
|
||||
<div class="col-sm-6">
|
||||
<input type="number" id="nb_places_training" class="form-control" ng-model="availability.nb_total_places">
|
||||
</div>
|
||||
@ -56,7 +56,7 @@
|
||||
</select>
|
||||
<div class="row m-t">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-6 control-label" for="nb_places_space" translate>{{ 'admin_calendar.number_of_tickets' }}</label>
|
||||
<label class="col-sm-6 control-label" for="nb_places_space" translate>{{ 'app.admin.calendar.number_of_tickets' }}</label>
|
||||
<div class="col-sm-6">
|
||||
<input type="number" id="nb_places_space" class="form-control" ng-model="availability.nb_total_places">
|
||||
</div>
|
||||
@ -66,19 +66,19 @@
|
||||
</div>
|
||||
<div class="modal-body" ng-show="step === 3">
|
||||
<div id="timeAdjust" class="m-t-sm">
|
||||
<p class="text-center font-sbold" translate>{{ 'admin_calendar.adjust_the_opening_hours' }}</p>
|
||||
<p class="text-center font-sbold" translate>{{ 'app.admin.calendar.adjust_the_opening_hours' }}</p>
|
||||
<div class="row">
|
||||
<div class="col-md-3 col-md-offset-2">
|
||||
<uib-timepicker ng-model="start" hour-step="timepickers.start.hstep" readonly-input="true" minute-step="timepickers.start.mstep" show-meridian="false"></uib-timepicker>
|
||||
</div>
|
||||
<span class="col-md-1 m-t-xl m-l" translate>{{ 'admin_calendar.to_time' }}</span>
|
||||
<span class="col-md-1 m-t-xl m-l" translate>{{ 'app.admin.calendar.to_time' }}</span>
|
||||
<fieldset ng-disabled="endDateReadOnly" class="col-md-5">
|
||||
<uib-timepicker ng-model="end" hour-step="timepickers.end.hstep" readonly-input="true" minute-step="timepickers.end.mstep" show-meridian="false"></uib-timepicker>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
<div id="tagAssociate" class="m-t-lg">
|
||||
<p class="text-center font-sbold" translate>{{ 'admin_calendar.restrict_this_slot_with_labels_optional' }}</p>
|
||||
<p class="text-center font-sbold" translate>{{ 'app.admin.calendar.restrict_this_slot_with_labels_optional' }}</p>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<ui-select multiple ng-model="availability.tag_ids" class="form-control">
|
||||
@ -93,13 +93,89 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer" ng-show="step < 3">
|
||||
<button class="btn btn-info" ng-click="previous()" ng-disabled="step === 1" translate>{{ 'admin_calendar.previous' }}</button>
|
||||
<button class="btn btn-info" ng-click="next()" translate>{{ 'admin_calendar.next' }}</button>
|
||||
<button class="btn btn-default" ng-click="cancel()" translate>{{ 'cancel' }}</button>
|
||||
<div class="modal-body m-h" ng-show="step === 4">
|
||||
<div class="m-t-sm">
|
||||
<p class="text-center font-sbold" translate>{{ 'app.admin.calendar.recurrence' }}</p>
|
||||
<div class="row">
|
||||
<div class="form-group">
|
||||
<label for="is_recurrent" translate>{{ 'app.admin.calendar.enabled' }}</label>
|
||||
<input bs-switch
|
||||
ng-model="availability.is_recurrent"
|
||||
id="is_recurrent"
|
||||
type="checkbox"
|
||||
class="form-control"
|
||||
switch-on-text="{{ 'app.shared.buttons.yes' | translate }}"
|
||||
switch-off-text="{{ 'app.shared.buttons.no' | translate }}"
|
||||
switch-animate="true"/>
|
||||
<input type="hidden" name="availability[is_recurrent]" value="{{availability.is_recurrent}}"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="form-group">
|
||||
<label for="period">{{ 'app.admin.calendar.period' | translate }}</label>
|
||||
<select id="period"
|
||||
name="period"
|
||||
class="form-control"
|
||||
ng-model="availability.period"
|
||||
ng-required="availability.is_recurrent"
|
||||
ng-disabled="!availability.is_recurrent">
|
||||
<option value="week" ng-selected="availability.period == 'week'" translate>{{ 'app.admin.calendar.week' }}</option>
|
||||
<option value="month" ng-selected="availability.period == 'month'" translate>{{ 'app.admin.calendar.month' }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="form-group">
|
||||
<label for="nb_periods">{{ 'app.admin.calendar.number_of_periods' | translate }}</label>
|
||||
<input id="nb_periods"
|
||||
name="nb_periods"
|
||||
class="form-control"
|
||||
ng-model="availability.nb_periods"
|
||||
type="number"
|
||||
ng-required="availability.is_recurrent"
|
||||
ng-disabled="!availability.is_recurrent" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="form-group">
|
||||
<label for="end_date">{{ 'app.admin.calendar.end_date' | translate }}</label>
|
||||
<input id="end_date"
|
||||
name="end_date"
|
||||
class="form-control"
|
||||
ng-model="availability.end_date"
|
||||
type="date"
|
||||
ng-required="availability.is_recurrent"
|
||||
ng-disabled="!availability.is_recurrent" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer" ng-show="step === 3">
|
||||
<button class="btn btn-info" ng-click="previous()" translate>{{ 'admin_calendar.previous' }}</button>
|
||||
<button class="btn btn-warning" ng-click="ok()" translate>{{ 'confirm' }}</button>
|
||||
<button class="btn btn-default" ng-click="cancel()" translate>{{ 'cancel' }}</button>
|
||||
<div class="modal-body m-h" ng-show="step === 5">
|
||||
<div class="m-t-sm">
|
||||
<p class="text-center font-sbold" translate>{{ 'app.admin.calendar.summary' }}</p>
|
||||
<div class="row">
|
||||
<span>{{ 'app.admin.calendar.about_to_create' | translate:{NUMBER:occurrences.length,TYPE:availability.available_type} }}</span>
|
||||
<ul>
|
||||
<li ng-repeat="slot in occurrences">{{slot.start_at | amDateFormat:'L LT'}} - {{slot.end_at | amDateFormat:'LT'}}</li>
|
||||
</ul>
|
||||
<div>
|
||||
<span class="underline" translate>{{ 'app.admin.calendar.reservable' }}</span>
|
||||
<span ng-bind-html="reservableName"></span>
|
||||
</div>
|
||||
<div class="m-t">
|
||||
<span class="underline" translate>{{ 'app.admin.calendar.labels' }}</span>
|
||||
<span ng-bind-html="tagsName"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer" ng-show="step < 5">
|
||||
<button class="btn btn-info" ng-click="previous()" ng-disabled="step === 1" translate>{{ 'app.admin.calendar.previous' }}</button>
|
||||
<button class="btn btn-info" ng-click="next()" translate>{{ 'app.admin.calendar.next' }}</button>
|
||||
<button class="btn btn-default" ng-click="cancel()" translate>{{ 'app.shared.buttons.cancel' }}</button>
|
||||
</div>
|
||||
<div class="modal-footer" ng-show="step === 5">
|
||||
<button class="btn btn-info" ng-click="previous()" translate>{{ 'app.admin.calendar.previous' }}</button>
|
||||
<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>
|
||||
|
96
app/assets/templates/admin/calendar/icalendar.html
Normal file
96
app/assets/templates/admin/calendar/icalendar.html
Normal file
@ -0,0 +1,96 @@
|
||||
<section class="heading b-b">
|
||||
<div class="row no-gutter">
|
||||
<div class="col-xs-2 col-sm-2 col-md-1">
|
||||
<section class="heading-btn">
|
||||
<a role="button" ng-click="backPrevLocation($event)"><i class="fa fa-long-arrow-left "></i></a>
|
||||
</section>
|
||||
</div>
|
||||
<div class="col-md-8 b-l b-r-md">
|
||||
<section class="heading-title">
|
||||
<h1 translate>{{ 'app.admin.icalendar.icalendar_import' }}</h1>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<section class="heading-actions wrapper">
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="row no-gutter">
|
||||
|
||||
<div class="col-sm-12 col-md-12 col-lg-9">
|
||||
<div class="alert alert-info m-lg" translate>
|
||||
{{ 'app.admin.icalendar.intro' }}
|
||||
</div>
|
||||
<div class="wrapper-lg">
|
||||
<table class="table" ng-show="calendars.length > 0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 35%;" translate>{{ 'app.admin.icalendar.name' }}</th>
|
||||
<th style="width: 35%;" translate>{{ 'app.admin.icalendar.url' }}</th>
|
||||
<th translate>{{ 'app.admin.icalendar.display' }}</th>
|
||||
<th style="width: 20%;"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="calendar in calendars">
|
||||
<td class="calendar-name">{{calendar.name}}</td>
|
||||
<td class="calendar-url"><a href="{{calendar.url}}" target="_blank">{{calendar.url}}</a></td>
|
||||
<td class="calendar-legend-block text-left"><span class="calendar-legend" ng-style="calendarStyle(calendar)" translate> {{ calendar.text_hidden ? '' : 'app.admin.icalendar.example' }}</span>
|
||||
<td class="calendar-actions">
|
||||
<button class="btn btn-info" ng-click="sync(calendar)"><i class="fa fa-refresh"></i></button>
|
||||
<button class="btn btn-danger" ng-click="delete(calendar)"><i class="fa fa-trash"></i></button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<form class="calendar-form" name="newImportForm">
|
||||
<h4 translate>{{ 'app.admin.icalendar.new_import' }}</h4>
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">
|
||||
<i class="fa fa-font"></i>
|
||||
</div>
|
||||
<input type="text" ng-model="newCalendar.name" class="form-control" placeholder="{{ 'app.admin.icalendar.name' | translate }}" required>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">
|
||||
<i class="fa fa-link"></i>
|
||||
</div>
|
||||
<input type="url" ng-model="newCalendar.url" class="form-control" placeholder="{{ 'app.admin.icalendar.url' | translate }}" required>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">
|
||||
<i class="fa fa-paint-brush"></i>
|
||||
</div>
|
||||
<input type="text" minicolors ng-model="newCalendar.color" class="form-control" placeholder="{{ 'app.admin.icalendar.color' | translate}}" required/>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">
|
||||
<i class="fa fa-paint-brush"></i>
|
||||
</div>
|
||||
<input type="text" minicolors ng-model="newCalendar.text_color" class="form-control" placeholder="{{ 'app.admin.icalendar.text_color' | translate}}" ng-required="!newCalendar.text_hidden"/>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<label for="hideText" class="control-label m-r" translate>{{ 'app.admin.icalendar.hide_text' }}</label>
|
||||
<input bs-switch
|
||||
ng-model="newCalendar.text_hidden"
|
||||
id="hideText"
|
||||
type="checkbox"
|
||||
class="form-control"
|
||||
switch-on-text="{{ 'app.admin.icalendar.hidden' | translate }}"
|
||||
switch-off-text="{{ 'app.admin.icalendar.shown' | translate }}"
|
||||
switch-animate="true"/>
|
||||
</div>
|
||||
<div class="m-t text-right">
|
||||
<button role="button" class="btn btn-warning" ng-click="save()" ng-disabled="newImportForm.$invalid" translate>
|
||||
{{ 'app.shared.buttons.confirm' }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
@ -1,15 +1,15 @@
|
||||
<div class="form-group" ng-class="{'has-error': couponForm['coupon[name]'].$dirty && couponForm['coupon[name]'].$invalid}">
|
||||
<label for="coupon[name]">{{ 'name' | translate }} *</label>
|
||||
<label for="coupon[name]">{{ 'app.shared.coupon.name' | translate }} *</label>
|
||||
<input type="text" id="coupon[name]"
|
||||
name="coupon[name]"
|
||||
class="form-control"
|
||||
ng-model="coupon.name"
|
||||
required="required"/>
|
||||
<span class="help-block error" ng-show="couponForm['coupon[name]'].$dirty && couponForm['coupon[name]'].$error.required" translate>{{ 'name_is_required' }}</span>
|
||||
<span class="help-block error" ng-show="couponForm['coupon[name]'].$dirty && couponForm['coupon[name]'].$error.required" translate>{{ 'app.shared.coupon.name_is_required' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{'has-error': couponForm['coupon[code]'].$dirty && couponForm['coupon[code]'].$invalid}">
|
||||
<label for="coupon[code]">{{ 'code' | translate }} *</label>
|
||||
<label for="coupon[code]">{{ 'app.shared.coupon.code' | translate }} *</label>
|
||||
<input type="text" id="coupon[code]"
|
||||
name="coupon[code]"
|
||||
class="form-control"
|
||||
@ -17,25 +17,25 @@
|
||||
ng-pattern="/^[A-Z0-9\-]+$/"
|
||||
ng-disabled="mode == 'EDIT'"
|
||||
required="required"/>
|
||||
<span class="help-block error" ng-show="couponForm['coupon[code]'].$dirty && couponForm['coupon[code]'].$error.required" translate>{{ 'code_is_required' }}</span>
|
||||
<span class="help-block error" ng-show="couponForm['coupon[code]'].$dirty && couponForm['coupon[code]'].$error.pattern" translate>{{ 'code_must_be_composed_of_capital_letters_digits_and_or_dashes' }}</span>
|
||||
<span class="help-block error" ng-show="couponForm['coupon[code]'].$dirty && couponForm['coupon[code]'].$error.required" translate>{{ 'app.shared.coupon.code_is_required' }}</span>
|
||||
<span class="help-block error" ng-show="couponForm['coupon[code]'].$dirty && couponForm['coupon[code]'].$error.pattern" translate>{{ 'app.shared.coupon.code_must_be_composed_of_capital_letters_digits_and_or_dashes' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="coupon[type]">{{ 'kind_of_coupon' | translate }} *</label>
|
||||
<label for="coupon[type]">{{ 'app.shared.coupon.kind_of_coupon' | translate }} *</label>
|
||||
<select id="coupon[type]"
|
||||
name="coupon[type]"
|
||||
class="form-control"
|
||||
ng-model="coupon.type"
|
||||
ng-disabled="mode == 'EDIT'"
|
||||
required="required">
|
||||
<option value="percent_off" translate>{{ 'percentage' }}</option>
|
||||
<option value="amount_off" translate>{{ 'amount' }}</option>
|
||||
<option value="percent_off" translate>{{ 'app.shared.coupon.percentage' }}</option>
|
||||
<option value="amount_off" translate>{{ 'app.shared.coupon.amount' }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{'has-error': couponForm['coupon[percent_off]'].$dirty && couponForm['coupon[percent_off]'].$invalid}" ng-show="coupon.type == 'percent_off'">
|
||||
<label for="coupon[percent_off]">{{ 'percent_off' | translate }} *</label>
|
||||
<label for="coupon[percent_off]">{{ 'app.shared.coupon.percent_off' | translate }} *</label>
|
||||
<div class="input-group">
|
||||
<input type="number" id="coupon[percent_off]"
|
||||
name="coupon[percent_off]"
|
||||
@ -47,13 +47,13 @@
|
||||
ng-required="coupon.type == 'percent_off'"/>
|
||||
<span class="input-group-addon"><i class="fa fa-percent"></i></span>
|
||||
</div>
|
||||
<span class="help-block error" ng-show="couponForm['coupon[percent_off]'].$dirty && couponForm['coupon[percent_off]'].$error.required" translate>{{ 'percent_off_is_required' }}</span>
|
||||
<span class="help-block error" ng-show="couponForm['coupon[percent_off]'].$dirty && (couponForm['coupon[percent_off]'].$error.min || couponForm['coupon[percent_off]'].$error.max)" translate>{{ 'percentage_must_be_between_0_and_100' }}</span>
|
||||
<span class="help-block error" ng-show="couponForm['coupon[percent_off]'].$dirty && couponForm['coupon[percent_off]'].$error.required" translate>{{ 'app.shared.coupon.percent_off_is_required' }}</span>
|
||||
<span class="help-block error" ng-show="couponForm['coupon[percent_off]'].$dirty && (couponForm['coupon[percent_off]'].$error.min || couponForm['coupon[percent_off]'].$error.max)" translate>{{ 'app.shared.coupon.percentage_must_be_between_0_and_100' }}</span>
|
||||
</div>
|
||||
|
||||
|
||||
<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]">{{ 'amount_off' | translate }} *</label>
|
||||
<label for="coupon[amount_off]">{{ 'app.shared.coupon.amount_off' | translate }} *</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon">{{currencySymbol}}</span>
|
||||
<input type="number" id="coupon[amount_off]"
|
||||
@ -64,25 +64,25 @@
|
||||
ng-disabled="mode == 'EDIT'"
|
||||
ng-required="coupon.type == 'amount_off'"/>
|
||||
</div>
|
||||
<span class="help-block error" ng-show="couponForm['coupon[percent_off]'].$dirty && couponForm['coupon[percent_off]'].$error.required" translate>{{ 'percent_off_is_required' }}</span>
|
||||
<span class="help-block error" ng-show="couponForm['coupon[percent_off]'].$dirty && (couponForm['coupon[percent_off]'].$error.min || couponForm['coupon[percent_off]'].$error.max)" translate>{{ 'percentage_must_be_between_0_and_100' }}</span>
|
||||
<span class="help-block error" ng-show="couponForm['coupon[percent_off]'].$dirty && couponForm['coupon[percent_off]'].$error.required" translate>{{ 'app.shared.coupon.percent_off_is_required' }}</span>
|
||||
<span class="help-block error" ng-show="couponForm['coupon[percent_off]'].$dirty && (couponForm['coupon[percent_off]'].$error.min || couponForm['coupon[percent_off]'].$error.max)" translate>{{ 'app.shared.coupon.percentage_must_be_between_0_and_100' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{'has-error': couponForm['coupon[validity_per_user]'].$dirty && couponForm['coupon[validity_per_user]'].$invalid}">
|
||||
<label for="coupon[validity_per_user]">{{ 'validity_per_user' | translate }} *</label>
|
||||
<label for="coupon[validity_per_user]">{{ 'app.shared.coupon.validity_per_user' | translate }} *</label>
|
||||
<select id="coupon[validity_per_user]"
|
||||
name="coupon[validity_per_user]"
|
||||
class="form-control"
|
||||
ng-model="coupon.validity_per_user"
|
||||
required="required"
|
||||
ng-disabled="mode == 'EDIT'"
|
||||
ng-options="( validity | translate ) for validity in validities">
|
||||
ng-options="validityName(validity) for validity in validities">
|
||||
</select>
|
||||
<span class="help-block error" ng-show="couponForm['coupon[validity_per_user]'].$dirty && couponForm['coupon[validity_per_user]'].$error.required" translate>{{ 'validity_per_user_is_required' }}</span>
|
||||
<span class="help-block error" ng-show="couponForm['coupon[validity_per_user]'].$dirty && couponForm['coupon[validity_per_user]'].$error.required" translate>{{ 'app.shared.coupon.validity_per_user_is_required' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{'has-error': errors['valid_until']}">
|
||||
<label for="coupon[valid_until]" translate>{{ 'valid_until' }}</label>
|
||||
<label for="coupon[valid_until]" translate>{{ 'app.shared.coupon.valid_until' }}</label>
|
||||
<div class="input-group">
|
||||
<input type="text" id="coupon[valid_until]"
|
||||
name="coupon[valid_until]"
|
||||
@ -100,34 +100,34 @@
|
||||
<span class="help-block error" ng-show="errors['valid_until']">{{ errors['valid_until'].join(' ; ') }}</span>
|
||||
|
||||
<span class="text-info text-xs">
|
||||
<i class="fa fa-lightbulb-o"></i> {{ 'leave_empty_for_no_limit' | translate }}
|
||||
<i class="fa fa-lightbulb-o"></i> {{ 'app.shared.coupon.leave_empty_for_no_limit' | translate }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{'has-error': couponForm['coupon[max_usages]'].$dirty && couponForm['coupon[max_usages]'].$invalid}">
|
||||
<label for="coupon[max_usages]">{{ 'max_usages' | translate }}</label>
|
||||
<label for="coupon[max_usages]">{{ 'app.shared.coupon.max_usages' | translate }}</label>
|
||||
<input type="number" id="coupon[max_usages]"
|
||||
name="coupon[max_usages]"
|
||||
class="form-control"
|
||||
ng-model="coupon.max_usages"
|
||||
ng-disabled="mode == 'EDIT'"
|
||||
min="0"/>
|
||||
<span class="help-block error" ng-show="couponForm['coupon[max_usages]'].$dirty && couponForm['coupon[max_usages]'].$error.min" translate>{{ 'max_usages_must_be_equal_or_greater_than_0' }}</span>
|
||||
<span class="help-block error" ng-show="couponForm['coupon[max_usages]'].$dirty && couponForm['coupon[max_usages]'].$error.min" translate>{{ 'app.shared.coupon.max_usages_must_be_equal_or_greater_than_0' }}</span>
|
||||
|
||||
<span class="text-info text-xs">
|
||||
<i class="fa fa-lightbulb-o"></i> {{ 'leave_empty_for_no_limit' | translate }}
|
||||
<i class="fa fa-lightbulb-o"></i> {{ 'app.shared.coupon.leave_empty_for_no_limit' | translate }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="coupon[active]" translate>{{ 'enabled' }}</label>
|
||||
<label for="coupon[active]" translate>{{ 'app.shared.coupon.enabled' }}</label>
|
||||
<input bs-switch
|
||||
ng-model="coupon.active"
|
||||
id="coupon[active]"
|
||||
type="checkbox"
|
||||
class="form-control"
|
||||
switch-on-text="{{ 'yes' | translate }}"
|
||||
switch-off-text="{{ 'no' | translate }}"
|
||||
switch-on-text="{{ 'app.shared.buttons.yes' | translate }}"
|
||||
switch-off-text="{{ 'app.shared.buttons.no' | translate }}"
|
||||
switch-animate="true" />
|
||||
<input type="hidden" name="coupon[active]" value="{{coupon.active}}"/>
|
||||
</div>
|
||||
|
@ -2,18 +2,18 @@
|
||||
<div class="row no-gutter">
|
||||
<div class="col-xs-2 col-sm-2 col-md-1">
|
||||
<section class="heading-btn">
|
||||
<a href="#" ng-click="backPrevLocation($event)"><i class="fa fa-long-arrow-left "></i></a>
|
||||
<a ng-click="backPrevLocation($event)"><i class="fa fa-long-arrow-left pointer"></i></a>
|
||||
</section>
|
||||
</div>
|
||||
<div class="col-xs-7 col-sm-7 col-md-8 b-l">
|
||||
<section class="heading-title">
|
||||
<h1>{{ 'coupon' | translate }} : {{ coupon.name }}</h1>
|
||||
<h1>{{ 'app.admin.coupons_edit.coupon' | translate }} {{ coupon.name }}</h1>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-3 col-md-3">
|
||||
<section class="heading-actions wrapper">
|
||||
<a class="btn btn-lg btn-block btn-default m-t-xs" ui-sref="app.admin.pricing" translate>{{ 'cancel' }}</a>
|
||||
<a class="btn btn-lg btn-block btn-default m-t-xs" ui-sref="app.admin.pricing" translate>{{ 'app.shared.buttons.cancel' }}</a>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
@ -28,10 +28,10 @@
|
||||
<div id="couponForm">
|
||||
<form name="couponForm" novalidate="novalidate" class="col-lg-7 col-lg-offset-2 m-t-lg form-group">
|
||||
|
||||
<ng-include src="'<%= asset_path 'admin/coupons/_form.html' %>'"></ng-include>
|
||||
<ng-include src="'<%= asset_path "admin/coupons/_form.html" %>'"></ng-include>
|
||||
|
||||
<div class="panel-footer no-padder">
|
||||
<input type="button" value="{{ 'confirm_changes' | translate }}" class="r-b btn-valid btn btn-warning btn-block p-lg btn-lg text-u-c" ng-disabled="couponForm.$invalid" ng-click="updateCoupon()"/>
|
||||
<input type="button" value="{{ 'app.shared.buttons.confirm_changes' | translate }}" class="r-b btn-valid btn btn-warning btn-block p-lg btn-lg text-u-c" ng-disabled="couponForm.$invalid" ng-click="updateCoupon()"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -2,12 +2,12 @@
|
||||
<div class="row no-gutter">
|
||||
<div class="col-xs-2 col-sm-2 col-md-1">
|
||||
<section class="heading-btn">
|
||||
<a href="#" ng-click="backPrevLocation($event)"><i class="fa fa-long-arrow-left "></i></a>
|
||||
<a ng-click="backPrevLocation($event)"><i class="fa fa-long-arrow-left pointer"></i></a>
|
||||
</section>
|
||||
</div>
|
||||
<div class="col-xs-10 col-sm-10 col-md-8 b-l">
|
||||
<section class="heading-title">
|
||||
<h1 translate>{{ 'add_a_coupon' }}</h1>
|
||||
<h1 translate>{{ 'app.admin.coupons_new.add_a_coupon' }}</h1>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@ -20,10 +20,10 @@
|
||||
<div id="couponForm">
|
||||
<form name="couponForm" novalidate="novalidate" class="col-lg-10 col-lg-offset-2 m-t-lg form-group">
|
||||
|
||||
<ng-include src="'<%= asset_path 'admin/coupons/_form.html' %>'"></ng-include>
|
||||
<ng-include src="'<%= asset_path "admin/coupons/_form.html" %>'"></ng-include>
|
||||
|
||||
<div class="panel-footer no-padder">
|
||||
<input type="button" value="{{ 'save' | translate }}" class="r-b btn-valid btn btn-warning btn-block p-lg btn-lg text-u-c" ng-disabled="couponForm.$invalid" ng-click="saveCoupon()"/>
|
||||
<input type="button" value="{{ 'app.shared.buttons.save' | translate }}" class="r-b btn-valid btn btn-warning btn-block p-lg btn-lg text-u-c" ng-disabled="couponForm.$invalid" ng-click="saveCoupon()"/>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
@ -1,11 +1,11 @@
|
||||
<div class="m-t">
|
||||
<h3 translate>{{ 'categories' }}</h3>
|
||||
<p translate>{{ 'at_least_one_category_is_required' }}</p>
|
||||
<button type="button" class="btn btn-warning m-b m-t" ng-click="addElement('category')" translate>{{ 'add_a_category' }}</button>
|
||||
<h3 translate>{{ 'app.admin.events.categories' }}</h3>
|
||||
<p translate>{{ 'app.admin.events.at_least_one_category_is_required' }}</p>
|
||||
<button type="button" class="btn btn-warning m-b m-t" ng-click="addElement('category')" translate>{{ 'app.admin.events.add_a_category' }}</button>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:80%" translate>{{ 'name' }}</th>
|
||||
<th style="width:80%" translate>{{ 'app.admin.events.name' }}</th>
|
||||
<th style="width:20%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -28,7 +28,7 @@
|
||||
</form>
|
||||
<div class="buttons" ng-show="!rowform.$visible">
|
||||
<button class="btn btn-default" ng-click="rowform.$show()">
|
||||
<i class="fa fa-edit"></i> <span class="hidden-xs hidden-sm" translate>{{ 'edit' }}</span>
|
||||
<i class="fa fa-edit"></i> <span class="hidden-xs hidden-sm" translate>{{ 'app.shared.buttons.edit' }}</span>
|
||||
</button>
|
||||
<button class="btn btn-danger" ng-click="removeElement('category', $index)">
|
||||
<i class="fa fa-trash-o"></i>
|
||||
@ -39,12 +39,12 @@
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h3 translate>{{ 'themes' }}</h3>
|
||||
<button type="button" class="btn btn-warning m-b m-t" ng-click="addElement('theme')" translate>{{ 'add_a_theme' }}</button>
|
||||
<h3 translate>{{ 'app.admin.events.themes' }}</h3>
|
||||
<button type="button" class="btn btn-warning m-b m-t" ng-click="addElement('theme')" translate>{{ 'app.admin.events.add_a_theme' }}</button>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:80%" translate>{{ 'name' }}</th>
|
||||
<th style="width:80%" translate>{{ 'app.admin.events.name' }}</th>
|
||||
<th style="width:20%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -67,7 +67,7 @@
|
||||
</form>
|
||||
<div class="buttons" ng-show="!rowform.$visible">
|
||||
<button class="btn btn-default" ng-click="rowform.$show()">
|
||||
<i class="fa fa-edit"></i> <span class="hidden-xs hidden-sm" translate>{{ 'edit' }}</span>
|
||||
<i class="fa fa-edit"></i> <span class="hidden-xs hidden-sm" translate>{{ 'app.shared.buttons.edit' }}</span>
|
||||
</button>
|
||||
<button class="btn btn-danger" ng-click="removeElement('theme', $index)">
|
||||
<i class="fa fa-trash-o"></i>
|
||||
@ -78,12 +78,12 @@
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h3 translate>{{ 'age_ranges' }}</h3>
|
||||
<button type="button" class="btn btn-warning m-b m-t" ng-click="addElement('age_range')" translate>{{ 'add_a_range' }}</button>
|
||||
<h3 translate>{{ 'app.admin.events.age_ranges' }}</h3>
|
||||
<button type="button" class="btn btn-warning m-b m-t" ng-click="addElement('age_range')" translate>{{ 'app.admin.events.add_a_range' }}</button>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:80%" translate>{{ 'name' }}</th>
|
||||
<th style="width:80%" translate>{{ 'app.admin.events.name' }}</th>
|
||||
<th style="width:20%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -106,7 +106,7 @@
|
||||
</form>
|
||||
<div class="buttons" ng-show="!rowform.$visible">
|
||||
<button class="btn btn-default" ng-click="rowform.$show()">
|
||||
<i class="fa fa-edit"></i> <span class="hidden-xs hidden-sm" translate>{{ 'edit' }}</span>
|
||||
<i class="fa fa-edit"></i> <span class="hidden-xs hidden-sm" translate>{{ 'app.shared.buttons.edit' }}</span>
|
||||
</button>
|
||||
<button class="btn btn-danger" ng-click="removeElement('age_range', $index)">
|
||||
<i class="fa fa-trash-o"></i>
|
||||
|
@ -7,13 +7,13 @@
|
||||
</div>
|
||||
<div class="col-xs-10 col-sm-10 col-md-8 b-l b-r-md">
|
||||
<section class="heading-title">
|
||||
<h1 translate>{{ 'fablab_events' }}</h1>
|
||||
<h1 translate>{{ 'app.admin.events.fablab_events' }}</h1>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-sm-12 col-md-3 b-t hide-b-md" ng-if="isAuthorized(['admin'])">
|
||||
<section class="heading-actions wrapper">
|
||||
<a class="btn btn-lg btn-warning bg-white b-2x rounded m-t-sm upper text-sm" ui-sref="app.admin.events_new" role="button" translate>{{ 'add_an_event' }}</a>
|
||||
<a class="btn btn-lg btn-warning bg-white b-2x rounded m-t-sm upper text-sm" ui-sref="app.admin.events_new" role="button" translate>{{ 'app.admin.events.add_an_event' }}</a>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
@ -22,16 +22,16 @@
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<uib-tabset justified="true">
|
||||
<uib-tab heading="{{ 'events_monitoring' | translate }}">
|
||||
<ng-include src="'<%= asset_path 'admin/events/monitoring.html' %>'"></ng-include>
|
||||
<uib-tab heading="{{ 'app.admin.events.events_monitoring' | translate }}">
|
||||
<ng-include src="'<%= asset_path "admin/events/monitoring.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'manage_filters' | translate }}">
|
||||
<ng-include src="'<%= asset_path 'admin/events/filters.html' %>'"></ng-include>
|
||||
<uib-tab heading="{{ 'app.admin.events.manage_filters' | translate }}">
|
||||
<ng-include src="'<%= asset_path "admin/events/filters.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'manage_prices_categories' | translate }}">
|
||||
<ng-include src="'<%= asset_path 'admin/events/prices.html' %>'"></ng-include>
|
||||
<uib-tab heading="{{ 'app.admin.events.manage_prices_categories' | translate }}">
|
||||
<ng-include src="'<%= asset_path "admin/events/prices.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
</uib-tabset>
|
||||
</div>
|
||||
|
@ -1,18 +1,18 @@
|
||||
<div class="col-md-6 m-b m-t">
|
||||
<select ng-model="eventsScope.selected" class="form-control" ng-change="changeScope()">
|
||||
<option value="" translate>{{ 'all_events' }}</option>
|
||||
<option value="passed" translate>{{ 'passed_events' }}</option>
|
||||
<option value="future" translate>{{ 'events_to_come' }}</option>
|
||||
<option value="future_asc" translate>{{ 'events_to_come_asc' }}</option>
|
||||
<option value="" translate>{{ 'app.admin.events.all_events' }}</option>
|
||||
<option value="passed" translate>{{ 'app.admin.events.passed_events' }}</option>
|
||||
<option value="future" translate>{{ 'app.admin.events.events_to_come' }}</option>
|
||||
<option value="future_asc" translate>{{ 'app.admin.events.events_to_come_asc' }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:30%" translate>{{ 'title' }}</th>
|
||||
<th style="width:30%" translate>{{ 'dates' }}</th>
|
||||
<th style="width:10%" translate>{{ 'booking' }}</th>
|
||||
<th style="width:30%" translate>{{ 'app.admin.events.title' }}</th>
|
||||
<th style="width:30%" translate>{{ 'app.admin.events.dates' }}</th>
|
||||
<th style="width:10%" translate>{{ 'app.admin.events.booking' }}</th>
|
||||
<th style="width:30%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -27,22 +27,22 @@
|
||||
|
||||
<!--One day event-->
|
||||
<span ng-if="(event.start_date | amDateFormat:'LL')==(event.end_date | amDateFormat:'LL')">
|
||||
{{ 'on_DATE' | translate:{DATE:(event.start_date | amDateFormat:'LL')} }}
|
||||
{{ 'app.admin.events.on_DATE' | translate:{DATE:(event.start_date | amDateFormat:'LL')} }}
|
||||
<span ng-if="event.all_day == 'false'">
|
||||
{{ 'from_TIME' | translate:{TIME:(event.start_date | amDateFormat:'LT')} }}
|
||||
<span class="text-sm font-thin" translate>{{ 'to_time' }}</span>
|
||||
{{ 'app.admin.events.from_TIME' | translate:{TIME:(event.start_date | amDateFormat:'LT')} }}
|
||||
<span class="text-sm font-thin" translate>{{ 'app.admin.events.to_time' }}</span>
|
||||
{{event.end_date | amDateFormat:'LT'}}
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<!--Multiple days event-->
|
||||
<span ng-if="(event.start_date | amDateFormat:'LL')!=(event.end_date | amDateFormat:'LL')">
|
||||
{{'from_DATE' | translate:{DATE:(event.start_date | amDateFormat:'LL')} }}
|
||||
{{'to_date' | translate}} {{event.end_date | amDateFormat:'LL'}}
|
||||
{{'app.admin.events.from_DATE' | translate:{DATE:(event.start_date | amDateFormat:'LL')} }}
|
||||
{{'app.admin.events.to_date' | translate}} {{event.end_date | amDateFormat:'LL'}}
|
||||
<br ng-if="event.all_day == 'false'"/>
|
||||
<span ng-if="event.all_day == 'false'">
|
||||
{{ 'from_TIME' | translate:{TIME:(event.start_date | amDateFormat:'LT')} }}
|
||||
<span class="text-sm font-thin" translate>{{ 'to_time' }}</span>
|
||||
{{ 'app.admin.events.from_TIME' | translate:{TIME:(event.start_date | amDateFormat:'LT')} }}
|
||||
<span class="text-sm font-thin" translate>{{ 'app.admin.events.to_time' }}</span>
|
||||
{{event.end_date | amDateFormat:'LT'}}
|
||||
</span>
|
||||
</span>
|
||||
@ -50,17 +50,17 @@
|
||||
|
||||
<td style="vertical-align:middle">
|
||||
<span class="ng-binding" ng-if="event.nb_total_places > 0">{{ event.nb_total_places - event.nb_free_places }} / {{ event.nb_total_places }}</span>
|
||||
<span class="badge font-sbold cancelled" ng-if="event.nb_total_places == -1" translate>{{ 'cancelled' }}</span>
|
||||
<span class="badge font-sbold" ng-if="!event.nb_total_places" translate>{{ 'free_entry' }}</span>
|
||||
<span class="badge font-sbold cancelled" ng-if="event.nb_total_places == -1" translate>{{ 'app.admin.events.cancelled' }}</span>
|
||||
<span class="badge font-sbold" ng-if="!event.nb_total_places" translate>{{ 'app.admin.events.free_entry' }}</span>
|
||||
</td>
|
||||
|
||||
<td style="vertical-align:middle">
|
||||
<div class="buttons">
|
||||
<a class="btn btn-default" ui-sref="app.admin.event_reservations({id: event.id})">
|
||||
<i class="fa fa-bookmark"></i> {{ 'view_reservations' | translate }}
|
||||
<i class="fa fa-bookmark"></i> {{ 'app.admin.events.view_reservations' | translate }}
|
||||
</a>
|
||||
<a class="btn btn-default" ui-sref="app.admin.events_edit({id: event.id})">
|
||||
<i class="fa fa-edit"></i> {{ 'edit' | translate }}
|
||||
<i class="fa fa-edit"></i> {{ 'app.shared.buttons.edit' | translate }}
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
@ -70,6 +70,6 @@
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<a class="btn btn-warning" ng-click="loadMoreEvents()" ng-if="paginateActive" translate>{{ 'load_the_next_events' }}</a>
|
||||
<a class="btn btn-warning" ng-click="loadMoreEvents()" ng-if="paginateActive" translate>{{ 'app.admin.events.load_the_next_events' }}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<div class="modal-header">
|
||||
<img ng-src="{{logoBlack.custom_asset_file_attributes.attachment_url}}" alt="{{logo.custom_asset_file_attributes.attachment}}" class="modal-logo"/>
|
||||
<h1 translate>{{ 'price_category' }}</h1>
|
||||
<h1 translate>{{ 'app.admin.events.price_category' }}</h1>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form role="form" name="priceCategoryForm" class="form-horizontal" novalidate autocomplete="off" ng-keydown="priceCategoryForm.$valid && $event.which == 13 && ok()">
|
||||
@ -12,10 +12,10 @@
|
||||
name="name"
|
||||
ng-model="category.name"
|
||||
class="form-control"
|
||||
placeholder="{{ 'category_name' | translate }}"
|
||||
placeholder="{{ 'app.admin.events.category_name' | translate }}"
|
||||
required />
|
||||
</div>
|
||||
<span class="help-block" ng-show="priceCategoryForm.name.$dirty && priceCategoryForm.name.$error.required" translate>{{ 'category_name_is_required' }}</span>
|
||||
<span class="help-block" ng-show="priceCategoryForm.name.$dirty && priceCategoryForm.name.$error.required" translate>{{ 'app.admin.events.category_name_is_required' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -25,16 +25,16 @@
|
||||
rows="10"
|
||||
class="form-control"
|
||||
id="conditions"
|
||||
placeholder="{{ 'enter_here_the_conditions_under_which_this_price_is_applicable' | translate }}"
|
||||
placeholder="{{ 'app.admin.events.enter_here_the_conditions_under_which_this_price_is_applicable' | translate }}"
|
||||
name="conditions"
|
||||
required>
|
||||
</textarea>
|
||||
<span class="help-block" ng-show="priceCategoryForm.conditions.$dirty && priceCategoryForm.conditions.$error.required" translate>{{ 'conditions_are_required' }}</span>
|
||||
<span class="help-block" ng-show="priceCategoryForm.conditions.$dirty && priceCategoryForm.conditions.$error.required" translate>{{ 'app.admin.events.conditions_are_required' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-info" ng-click="ok()" ng-disabled="priceCategoryForm.$invalid" translate>{{ 'confirm' }}</button>
|
||||
<button class="btn btn-default" ng-click="cancel()" translate>{{ 'cancel' }}</button>
|
||||
<button class="btn btn-info" ng-click="ok()" ng-disabled="priceCategoryForm.$invalid" translate>{{ 'app.shared.buttons.confirm' }}</button>
|
||||
<button class="btn btn-default" ng-click="cancel()" translate>{{ 'app.shared.buttons.cancel' }}</button>
|
||||
</div>
|
||||
|
@ -1,12 +1,12 @@
|
||||
<div class="m-t">
|
||||
<h3 translate>{{ 'prices_categories' }}</h3>
|
||||
<h3 translate>{{ 'app.admin.events.prices_categories' }}</h3>
|
||||
|
||||
<button type="button" class="btn btn-warning m-b m-t" ng-click="newPriceCategory()" translate>{{ 'add_a_price_category' }}</button>
|
||||
<button type="button" class="btn btn-warning m-b m-t" ng-click="newPriceCategory()" translate>{{ 'app.admin.events.add_a_price_category' }}</button>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:40%" translate>{{ 'name' }}</th>
|
||||
<th style="width:40%" translate>{{ 'usages_count' }}</th>
|
||||
<th style="width:40%" translate>{{ 'app.admin.events.name' }}</th>
|
||||
<th style="width:40%" translate>{{ 'app.admin.events.usages_count' }}</th>
|
||||
<th style="width:20%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -17,7 +17,7 @@
|
||||
<td>
|
||||
<div class="buttons">
|
||||
<button class="btn btn-default" ng-click="editPriceCategory(category.id, $index)">
|
||||
<i class="fa fa-edit"></i> <span class="hidden-xs hidden-sm" translate>{{ 'edit' }}</span>
|
||||
<i class="fa fa-edit"></i> <span class="hidden-xs hidden-sm" translate>{{ 'app.shared.buttons.edit' }}</span>
|
||||
</button>
|
||||
<button class="btn btn-danger" ng-click="removePriceCategory(category.id, $index)">
|
||||
<i class="fa fa-trash-o"></i>
|
||||
|
@ -7,7 +7,7 @@
|
||||
</div>
|
||||
<div class="col-xs-10 col-sm-10 col-md-8 b-l">
|
||||
<section class="heading-title">
|
||||
<h1>{{ 'the_reservations' | translate }} {{event.title}}</h1>
|
||||
<h1>{{ 'app.admin.event_reservations.the_reservations' | translate }} {{event.title}}</h1>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
@ -20,35 +20,36 @@
|
||||
<table class="table" ng-if="reservations.length > 0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:25%" translate>{{ 'user' }}</th>
|
||||
<th style="width:25%" translate>{{ 'payment_date' }}</th>
|
||||
<th style="width:25%" translate>{{ 'reserved_tickets' }}</th>
|
||||
<th style="width:25%" translate>{{ 'app.admin.event_reservations.user' }}</th>
|
||||
<th style="width:25%" translate>{{ 'app.admin.event_reservations.payment_date' }}</th>
|
||||
<th style="width:25%" translate>{{ 'app.admin.event_reservations.reserved_tickets' }}</th>
|
||||
<th style="width:25%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="reservation in reservations">
|
||||
<tr ng-repeat="reservation in reservations" ng-class="{'disabled': isCancelled(reservation)}">
|
||||
<td class="text-c">
|
||||
<a ui-sref="app.logged.members_show({id: reservation.user_id})">{{ reservation.user_full_name }} </a>
|
||||
</td>
|
||||
<td>{{ reservation.created_at | amDateFormat:'LL LTS' }}</td>
|
||||
<td>
|
||||
<span ng-if="reservation.nb_reserve_places > 0">{{ 'full_price_' | translate }} {{reservation.nb_reserve_places}}<br/></span>
|
||||
<span ng-if="reservation.nb_reserve_places > 0">{{ 'app.admin.event_reservations.full_price_' | translate }} {{reservation.nb_reserve_places}}<br/></span>
|
||||
<span ng-repeat="ticket in reservation.tickets">{{ticket.event_price_category.price_category.name}} : {{ticket.booked}}</span>
|
||||
<div ng-show="isCancelled(reservation)" class="canceled-marker" translate>{{ 'app.admin.event_reservations.canceled' }}</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="buttons">
|
||||
<button class="btn btn-default" ui-sref="app.public.events_show({id: event.id})">
|
||||
<i class="fa fa-tag"></i> {{ 'show_the_event' | translate }}
|
||||
<i class="fa fa-tag"></i> {{ 'app.admin.event_reservations.show_the_event' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p ng-if="reservations.length == 0" translate>{{ 'no_reservations_for_now' }}</p>
|
||||
<p ng-if="reservations.length == 0" translate>{{ 'app.admin.event_reservations.no_reservations_for_now' }}</p>
|
||||
|
||||
<button type="button" class="btn btn-warning m-t m-b" ui-sref="app.admin.events" translate>{{ 'back_to_monitoring' }}</button>
|
||||
<button type="button" class="btn btn-warning m-t m-b" ui-sref="app.admin.events" translate>{{ 'app.admin.event_reservations.back_to_monitoring' }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
@ -1,13 +1,13 @@
|
||||
<div class="m-t-lg m-b">
|
||||
<button type="button" class="btn btn-warning" ng-click="addGroup()">
|
||||
<i class="fa fa-plus m-r"></i>
|
||||
<span translate>{{ 'group_form.add_a_group' }}</span>
|
||||
<span translate>{{ 'app.admin.members.group_form.add_a_group' }}</span>
|
||||
</button>
|
||||
<div class="form-group pull-right">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="fa fa-filter"></i></span>
|
||||
<select ng-model="groupFiltering" class="form-control">
|
||||
<option ng-repeat="status in filterDisabled" value="{{status}}" translate>{{ 'group_form.status_'+status }}</option>
|
||||
<option ng-repeat="status in filterDisabled" value="{{status}}" translate>{{ 'app.admin.members.group_form.status_'+status }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@ -16,7 +16,7 @@
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 75%;" translate>{{ 'group_form.group_name' }}</th>
|
||||
<th style="width: 75%;" translate>{{ 'app.admin.members.group_form.group_name' }}</th>
|
||||
<th style="width: 25%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -39,11 +39,11 @@
|
||||
</form>
|
||||
<div class="buttons" ng-hide="rowform.$visible || group.slug === 'admins'">
|
||||
<button class="btn btn-default" ng-click="rowform.$show()">
|
||||
<i class="fa fa-edit"></i> <span class="hidden-xs hidden-sm" translate>{{ 'edit' }}</span>
|
||||
<i class="fa fa-edit"></i> <span class="hidden-xs hidden-sm" translate>{{ 'app.shared.buttons.edit' }}</span>
|
||||
</button>
|
||||
<button class="btn btn-default" ng-click="toggleDisableGroup($index)">
|
||||
<span ng-hide="group.disabled"><i class="fa fa-eye-slash"></i> <span translate>{{ 'group_form.disable' }}</span></span>
|
||||
<span ng-show="group.disabled"><i class="fa fa-eye"></i> <span translate>{{ 'group_form.enable' }}</span></span>
|
||||
<span ng-hide="group.disabled"><i class="fa fa-eye-slash"></i> <span translate>{{ 'app.admin.members.group_form.disable' }}</span></span>
|
||||
<span ng-show="group.disabled"><i class="fa fa-eye"></i> <span translate>{{ 'app.admin.members.group_form.enable' }}</span></span>
|
||||
</button>
|
||||
<button class="btn btn-danger" ng-click="removeGroup($index)">
|
||||
<i class="fa fa-trash-o"></i>
|
||||
|
@ -1,10 +1,10 @@
|
||||
<ul>
|
||||
<li><span class="period-info-title" translate>{{ 'invoices.closed_at' }}</span> : <span>{{period.closed_at | amDateFormat:'L'}}</span></li>
|
||||
<li><span class="period-info-title" translate>{{ 'invoices.closed_by' }}</span> : <span>{{period.user_name}}</span></li>
|
||||
<li><span class="period-info-title" translate>{{ 'invoices.period_total' }}</span> : <span>{{period.period_total | currency}}</span></li>
|
||||
<li><span class="period-info-title" translate>{{ 'invoices.perpetual_total' }}</span> : <span>{{period.perpetual_total | currency}}</span></li>
|
||||
<li><span class="period-info-title" translate>{{ 'app.admin.invoices.closed_at' }}</span> : <span>{{period.closed_at | amDateFormat:'L'}}</span></li>
|
||||
<li><span class="period-info-title" translate>{{ 'app.admin.invoices.closed_by' }}</span> : <span>{{period.user_name}}</span></li>
|
||||
<li><span class="period-info-title" translate>{{ 'app.admin.invoices.period_total' }}</span> : <span>{{period.period_total | currency}}</span></li>
|
||||
<li><span class="period-info-title" translate>{{ 'app.admin.invoices.perpetual_total' }}</span> : <span>{{period.perpetual_total | currency}}</span></li>
|
||||
<li>
|
||||
<span class="period-info-title" translate>{{ 'invoices.integrity' }}</span> :
|
||||
<span class="period-info-title" translate>{{ 'app.admin.invoices.integrity' }}</span> :
|
||||
<i class="fa fa-link chained" ng-show="period.chained_footprint"></i>
|
||||
<i class="fa fa-chain-broken broken" ng-hide="period.chained_footprint"></i>
|
||||
</li>
|
||||
|
@ -1,11 +1,11 @@
|
||||
<div class="modal-header">
|
||||
<h3 class="text-center red" translate>{{ 'invoices.export_accounting_data' }}</h3>
|
||||
<h3 class="text-center red" translate>{{ 'app.admin.invoices.export_accounting_data' }}</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form role="form" name="exportForm">
|
||||
<div class="row">
|
||||
<div class="form-group col-md-6">
|
||||
<label for="start_date" translate>{{ 'invoices.export_form_date' }}</label>
|
||||
<label for="start_date" translate>{{ 'app.admin.invoices.export_form_date' }}</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
|
||||
<input type="text"
|
||||
@ -23,7 +23,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="end_date" translate>{{ 'invoices.export_to_date' }}</label>
|
||||
<label for="end_date" translate>{{ 'app.admin.invoices.export_to_date' }}</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
|
||||
<input type="text"
|
||||
@ -42,36 +42,36 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<h4 class="control-label m-l" translate>{{ 'invoices.export_to' }}</h4>
|
||||
<h4 class="control-label m-l" translate>{{ 'app.admin.invoices.export_to' }}</h4>
|
||||
<div class="form-group m-l-lg">
|
||||
<label for="acd">
|
||||
<input type="radio" name="acd" id="acd" ng-model="exportTarget.software" ng-value="'acd'" ng-click="fillSettings()" required/>
|
||||
{{ 'invoices.acd' | translate }}
|
||||
{{ 'app.admin.invoices.acd' | translate }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" ng-show="exportTarget.settings">
|
||||
<div class="col-md-4 font-bold" translate>{{ 'invoices.format' }}</div>
|
||||
<div class="col-md-4 font-bold" translate>{{ 'app.admin.invoices.format' }}</div>
|
||||
<div class="col-md-8">{{ exportTarget.settings.format }}</div>
|
||||
<div class="col-md-4 font-bold" translate>{{ 'invoices.encoding' }}</div>
|
||||
<div class="col-md-4 font-bold" translate>{{ 'app.admin.invoices.encoding' }}</div>
|
||||
<div class="col-md-8">{{ exportTarget.settings.encoding }}</div>
|
||||
<div class="col-md-4 font-bold" translate>{{ 'invoices.separator' }}</div>
|
||||
<div class="col-md-4 font-bold" translate>{{ 'app.admin.invoices.separator' }}</div>
|
||||
<div class="col-md-8">{{ exportTarget.settings.separator }}</div>
|
||||
<div class="col-md-4 font-bold" translate>{{ 'invoices.dateFormat' }}</div>
|
||||
<div class="col-md-4 font-bold" translate>{{ 'app.admin.invoices.dateFormat' }}</div>
|
||||
<div class="col-md-8">
|
||||
<a href="https://apidock.com/ruby/DateTime/strftime" class="help-cursor" target="_blank">{{ exportTarget.settings.dateFormat }}</a>
|
||||
</div>
|
||||
<div class="col-md-4 font-bold" translate>{{ 'invoices.labelMaxLength' }}</div>
|
||||
<div class="col-md-4 font-bold" translate>{{ 'app.admin.invoices.labelMaxLength' }}</div>
|
||||
<div class="col-md-8">{{ exportTarget.settings.labelMaxLength }}</div>
|
||||
<div class="col-md-4 font-bold" translate>{{ 'invoices.decimalSeparator' }}</div>
|
||||
<div class="col-md-4 font-bold" translate>{{ 'app.admin.invoices.decimalSeparator' }}</div>
|
||||
<div class="col-md-8">{{ exportTarget.settings.decimalSeparator }}</div>
|
||||
<div class="col-md-4 font-bold" translate>{{ 'invoices.exportInvoicesAtZero' }}</div>
|
||||
<div class="col-md-4 font-bold" translate>{{ 'app.admin.invoices.exportInvoicesAtZero' }}</div>
|
||||
<div class="col-md-8" translate>{{ exportTarget.settings.exportInvoicesAtZero ? 'yes' : 'no' }}</div>
|
||||
<div class="col-md-4 font-bold" translate>{{ 'invoices.columns' }}</div>
|
||||
<div class="col-md-4 font-bold" translate>{{ 'app.admin.invoices.columns' }}</div>
|
||||
<table class="col-md-12 export-table-template">
|
||||
<thead>
|
||||
<tr>
|
||||
<td ng-repeat="column in exportTarget.settings.columns" translate>{{ 'invoices.exportColumns.' + column }}</td>
|
||||
<td ng-repeat="column in exportTarget.settings.columns" translate>{{ 'app.admin.invoices.exportColumns.' + column }}</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -91,7 +91,7 @@
|
||||
<input name="type" type="hidden" ng-value="exportTarget.software"/>
|
||||
<input name="key" type="hidden" ng-value="query.key"/>
|
||||
<input name="query" type="hidden" ng-value="query.query"/>
|
||||
<input type="submit" class="btn btn-warning" value="{{ 'confirm' | translate }}" formtarget="export-frame"/>
|
||||
<input type="submit" class="btn btn-warning" value="{{ 'app.shared.buttons.confirm' | translate }}" formtarget="export-frame"/>
|
||||
</form>
|
||||
<button class="btn btn-default" ng-click="cancel()" translate>{{ 'cancel' }}</button>
|
||||
<button class="btn btn-default" ng-click="cancel()" translate>{{ 'app.shared.buttons.cancel' }}</button>
|
||||
</div>
|
||||
|
@ -1,10 +1,10 @@
|
||||
<div class="modal-header">
|
||||
<h3 class="text-center red" translate>{{ 'invoices.create_a_refund_on_this_invoice' }}</h3>
|
||||
<h3 class="text-center red" translate>{{ 'app.admin.invoices.create_a_refund_on_this_invoice' }}</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form name="avoirForm" novalidate="novalidate">
|
||||
<div class="form-group" ng-class="{'has-error': avoirForm.avoir_date.$dirty && avoirForm.avoir_date.$invalid }">
|
||||
<label translate>{{ 'invoices.creation_date_for_the_refund' }}</label>
|
||||
<label translate>{{ 'app.admin.invoices.creation_date_for_the_refund' }}</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
|
||||
<input type="text"
|
||||
@ -19,24 +19,24 @@
|
||||
ng-click="openDatePicker($event)"
|
||||
required/>
|
||||
</div>
|
||||
<span class="help-block" ng-show="avoirForm.avoir_date.$dirty && avoirForm.avoir_date.$error.required" translate>{{ 'invoices.creation_date_is_required' }}</span>
|
||||
<span class="help-block" ng-show="avoirForm.avoir_date.$dirty && avoirForm.avoir_date.$error.required" translate>{{ 'app.admin.invoices.creation_date_is_required' }}</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label translate>{{ 'invoices.refund_mode' }}</label>
|
||||
<label translate>{{ 'app.admin.invoices.refund_mode' }}</label>
|
||||
<select class="form-control m-t-sm" name="payment_method" ng-model="avoir.payment_method" ng-options="mode.value as mode.name for mode in avoirModes" required></select>
|
||||
</div>
|
||||
<div class="form-group" ng-if="invoice.is_subscription_invoice">
|
||||
<label translate>{{ 'invoices.do_you_want_to_disable_the_user_s_subscription' }}</label>
|
||||
<label translate>{{ 'app.admin.invoices.do_you_want_to_disable_the_user_s_subscription' }}</label>
|
||||
<select class="form-control m-t-sm" name="subscription_to_expire" ng-model="avoir.subscription_to_expire" ng-options="value as key for (key, value) in subscriptionExpireOptions" required></select>
|
||||
</div>
|
||||
<div ng-show="!invoice.is_subscription_invoice && invoice.items.length > 1" class="form-group">
|
||||
<label translate>{{ 'invoices.elements_to_refund' }}</label>
|
||||
<label translate>{{ 'app.admin.invoices.elements_to_refund' }}</label>
|
||||
<table class="table partial-avoir-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="input-col"></th>
|
||||
<th class="label-col" translate>{{ 'invoices.description' }}</th>
|
||||
<th class="amount-col" translate>{{ 'invoices.price' }}</th>
|
||||
<th class="label-col" translate>{{ 'app.admin.invoices.description' }}</th>
|
||||
<th class="amount-col" translate>{{ 'app.admin.invoices.price' }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -49,13 +49,13 @@
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
<label for="description" translate>{{ 'invoices.description_optional' }}</label>
|
||||
<p translate>{{ 'invoices.will_appear_on_the_refund_invoice' }}</p>
|
||||
<label for="description" translate>{{ 'app.admin.invoices.description_optional' }}</label>
|
||||
<p translate>{{ 'app.admin.invoices.will_appear_on_the_refund_invoice' }}</p>
|
||||
<textarea class="form-control m-t-sm" name="description" ng-model="avoir.description"></textarea>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-warning" ng-click="ok()" ng-disabled="avoirForm.$invalid" translate>{{ 'confirm' }}</button>
|
||||
<button class="btn btn-default" ng-click="cancel()" translate>{{ 'cancel' }}</button>
|
||||
<button class="btn btn-warning" ng-click="ok()" ng-disabled="avoirForm.$invalid" translate>{{ 'app.shared.buttons.confirm' }}</button>
|
||||
<button class="btn btn-default" ng-click="cancel()" translate>{{ 'app.shared.buttons.cancel' }}</button>
|
||||
</div>
|
||||
|
@ -1,10 +1,10 @@
|
||||
<div class="modal-header">
|
||||
<h3 class="text-center red" translate>{{ 'invoices.close_accounting_period' }}</h3>
|
||||
<h3 class="text-center red" translate>{{ 'app.admin.invoices.close_accounting_period' }}</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form name="closePeriodForm" novalidate="novalidate" class="row">
|
||||
<div class="form-group col-md-6" ng-class="{'has-error': closePeriodForm.start_at.$dirty && closePeriodForm.start_at.$invalid }">
|
||||
<label translate>{{ 'invoices.close_from_date' }}</label>
|
||||
<label translate>{{ 'app.admin.invoices.close_from_date' }}</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
|
||||
<input type="text"
|
||||
@ -21,11 +21,11 @@
|
||||
readonly
|
||||
required/>
|
||||
</div>
|
||||
<span class="help-block" ng-show="closePeriodForm.start_at.$dirty && closePeriodForm.start_at.$error.required" translate>{{ 'invoices.start_date_is_required' }}</span>
|
||||
<span class="help-block" ng-show="closePeriodForm.start_at.$dirty && closePeriodForm.start_at.$error.required" translate>{{ 'app.admin.invoices.start_date_is_required' }}</span>
|
||||
<span class="help-block error" ng-show="errors.start_at">{{ errors.start_at[0] }}</span>
|
||||
</div>
|
||||
<div class="form-group col-md-6" ng-class="{'has-error': closePeriodForm.end_at.$dirty && closePeriodForm.end_at.$invalid }">
|
||||
<label translate>{{ 'invoices.close_until_date' }}</label>
|
||||
<label translate>{{ 'app.admin.invoices.close_until_date' }}</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
|
||||
<input type="text"
|
||||
@ -43,7 +43,7 @@
|
||||
required
|
||||
readonly/>
|
||||
</div>
|
||||
<span class="help-block" ng-show="closePeriodForm.end_at.$dirty && closePeriodForm.end_at.$error.required" translate>{{ 'invoices.end_date_is_required' }}</span>
|
||||
<span class="help-block" ng-show="closePeriodForm.end_at.$dirty && closePeriodForm.end_at.$error.required" translate>{{ 'app.admin.invoices.end_date_is_required' }}</span>
|
||||
<span class="help-block error" ng-show="errors.end_at">{{ errors.end_at[0] }}</span>
|
||||
</div>
|
||||
</form>
|
||||
@ -51,12 +51,12 @@
|
||||
<span class="help-block error">{{ $parent.invoiceErrorRE.exec(key)[1] }} : {{ value[0] }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<h4 translate>{{ 'invoices.previous_closings' }}</h4>
|
||||
<h4 translate>{{ 'app.admin.invoices.previous_closings' }}</h4>
|
||||
<table class="table closings-table" ng-show="accountingPeriods.length > 0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th translate>{{ 'invoices.start_date' }}</th>
|
||||
<th translate>{{ 'invoices.end_date' }}</th>
|
||||
<th translate>{{ 'app.admin.invoices.start_date' }}</th>
|
||||
<th translate>{{ 'app.admin.invoices.end_date' }}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -72,10 +72,10 @@
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div ng-show="accountingPeriods.length === 0" translate>{{ 'invoices.no_periods'}}</div>
|
||||
<div ng-show="accountingPeriods.length === 0" translate>{{ 'app.admin.invoices.no_periods'}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-warning" ng-click="ok()" ng-disabled="closePeriodForm.$invalid || pendingCreation" translate>{{ 'confirm' }}</button>
|
||||
<button class="btn btn-default" ng-click="cancel()" ng-disabled="pendingCreation" translate>{{ 'cancel' }}</button>
|
||||
<button class="btn btn-warning" ng-click="ok()" ng-disabled="closePeriodForm.$invalid || pendingCreation" translate>{{ 'app.shared.buttons.confirm' }}</button>
|
||||
<button class="btn btn-default" ng-click="cancel()" ng-disabled="pendingCreation" translate>{{ 'app.shared.buttons.cancel' }}</button>
|
||||
</div>
|
||||
|
@ -7,14 +7,14 @@
|
||||
</div>
|
||||
<div class="col-xs-10 col-sm-10 col-md-8 b-l">
|
||||
<section class="heading-title">
|
||||
<h1 translate>{{ 'invoices.invoices' }}</h1>
|
||||
<h1 translate>{{ 'app.admin.invoices.invoices' }}</h1>
|
||||
</section>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-12 col-md-3 b-t hide-b-md">
|
||||
<section class="heading-actions wrapper">
|
||||
<a class="btn btn-default rounded m-t-sm" ng-click="toggleExportModal()"><i class="fa fa-book"></i></a>
|
||||
<iframe name="export-frame" height="0" width="0" class="none" id="accounting-export-frame"></iframe>
|
||||
<a class="btn btn-lg btn-default rounded m-t-sm text-sm" ng-click="closeAnAccountingPeriod()"><i class="fa fa-calendar-check-o"></i> {{ 'invoices.accounting_periods' | translate }}</a>
|
||||
<a class="btn btn-lg btn-default rounded m-t-sm text-sm" ng-click="closeAnAccountingPeriod()"><i class="fa fa-calendar-check-o"></i> {{ 'app.admin.invoices.accounting_periods' | translate }}</a>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
@ -24,14 +24,14 @@
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<uib-tabset justified="true">
|
||||
<uib-tab heading="{{ 'invoices.invoices_list' | translate }}" ng-hide="fablabWithoutInvoices" active="tabs.listing.active">
|
||||
<h3 class="m-t-xs"><i class="fa fa-filter"></i> {{ 'invoices.filter_invoices' | translate }}</h3>
|
||||
<uib-tab heading="{{ 'app.admin.invoices.invoices_list' | translate }}" ng-hide="fablabWithoutInvoices" active="tabs.listing.active">
|
||||
<h3 class="m-t-xs"><i class="fa fa-filter"></i> {{ 'app.admin.invoices.filter_invoices' | translate }}</h3>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon" translate>{{ 'invoices.invoice_num_' }}</span>
|
||||
<span class="input-group-addon" translate>{{ 'app.admin.invoices.invoice_num_' }}</span>
|
||||
<input type="text" ng-model="searchInvoice.reference" class="form-control" placeholder="" ng-change="handleFilterChange()">
|
||||
</div>
|
||||
</div>
|
||||
@ -40,7 +40,7 @@
|
||||
<div class="col-md-4">
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon" translate>{{ 'invoices.customer_' }}</span>
|
||||
<span class="input-group-addon" translate>{{ 'app.admin.invoices.customer_' }}</span>
|
||||
<input type="text" ng-model="searchInvoice.name" class="form-control" placeholder="" ng-change="handleFilterChange()">
|
||||
</div>
|
||||
</div>
|
||||
@ -49,7 +49,7 @@
|
||||
<div class="col-md-4">
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon">{{ "invoices.date_" | translate }}</span>
|
||||
<span class="input-group-addon">{{ "app.admin.invoices.date_" | translate }}</span>
|
||||
<input type="date" ng-model="searchInvoice.date" class="form-control" ng-change="handleFilterChange()">
|
||||
</div>
|
||||
</div>
|
||||
@ -64,13 +64,13 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:5%"></th>
|
||||
<th style="width:15%"><a href="" ng-click="setOrderInvoice('reference')">{{ 'invoices.invoice_num' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-numeric-asc': orderInvoice=='reference', 'fa fa-sort-numeric-desc': orderInvoice=='-reference', 'fa fa-arrows-v': orderInvoice }"></i></a></th>
|
||||
<th style="width:15%"><a href="" ng-click="setOrderInvoice('reference')">{{ 'app.admin.invoices.invoice_num' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-numeric-asc': orderInvoice=='reference', 'fa fa-sort-numeric-desc': orderInvoice=='-reference', 'fa fa-arrows-v': orderInvoice }"></i></a></th>
|
||||
|
||||
<th style="width:20%"><a href="" ng-click="setOrderInvoice('date')">{{ 'invoices.date' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-numeric-asc': orderInvoice=='date', 'fa fa-sort-numeric-desc': orderInvoice=='-date', 'fa fa-arrows-v': orderInvoice }"></i></a></th>
|
||||
<th style="width:20%"><a href="" ng-click="setOrderInvoice('date')">{{ 'app.admin.invoices.date' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-numeric-asc': orderInvoice=='date', 'fa fa-sort-numeric-desc': orderInvoice=='-date', 'fa fa-arrows-v': orderInvoice }"></i></a></th>
|
||||
|
||||
<th style="width:10%"><a href="" ng-click="setOrderInvoice('total')"> {{ 'invoices.price' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-numeric-asc': orderInvoice=='total', 'fa fa-sort-numeric-desc': orderInvoice=='-total', 'fa fa-arrows-v': orderInvoice }"></i></a></th>
|
||||
<th style="width:10%"><a href="" ng-click="setOrderInvoice('total')"> {{ 'app.admin.invoices.price' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-numeric-asc': orderInvoice=='total', 'fa fa-sort-numeric-desc': orderInvoice=='-total', 'fa fa-arrows-v': orderInvoice }"></i></a></th>
|
||||
|
||||
<th style="width:20%"><a href="" ng-click="setOrderInvoice('name')">{{ 'invoices.customer' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': orderInvoice=='name', 'fa fa-sort-alpha-desc': orderInvoice=='-name', 'fa fa-arrows-v': orderInvoice }"></i></a></th>
|
||||
<th style="width:20%"><a href="" ng-click="setOrderInvoice('name')">{{ 'app.admin.invoices.customer' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': orderInvoice=='name', 'fa fa-sort-alpha-desc': orderInvoice=='-name', 'fa fa-arrows-v': orderInvoice }"></i></a></th>
|
||||
|
||||
<th style="width:30%"></th>
|
||||
</tr>
|
||||
@ -91,13 +91,13 @@
|
||||
<td>
|
||||
<div class="buttons">
|
||||
<a class="btn btn-default" ng-href="api/invoices/{{invoice.id}}/download" target="_blank" ng-if="!invoice.is_avoir">
|
||||
<i class="fa fa-file-pdf-o"></i> {{ 'invoices.download_the_invoice' | translate }}
|
||||
<i class="fa fa-file-pdf-o"></i> {{ 'app.admin.invoices.download_the_invoice' | translate }}
|
||||
</a>
|
||||
<a class="btn btn-default" ng-href="api/invoices/{{invoice.id}}/download" target="_blank" ng-if="invoice.is_avoir">
|
||||
<i class="fa fa-file-pdf-o"></i> {{ 'invoices.download_the_credit_note' | translate }}
|
||||
<i class="fa fa-file-pdf-o"></i> {{ 'app.admin.invoices.download_the_credit_note' | translate }}
|
||||
</a>
|
||||
<a class="btn btn-default" ng-click="generateAvoirForInvoice(invoice)" ng-if="(!invoice.has_avoir || invoice.has_avoir == 'partial') && !invoice.is_avoir && !invoice.prevent_refund && !isDateClosed(invoice.created_at)">
|
||||
<i class="fa fa-reply"></i> {{ 'invoices.credit_note' | translate }}
|
||||
<i class="fa fa-reply"></i> {{ 'app.admin.invoices.credit_note' | translate }}
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
@ -105,9 +105,9 @@
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="text-center">
|
||||
<button class="btn btn-warning" ng-click="showNextInvoices()" ng-hide="noMoreResults"><i class="fa fa-search-plus" aria-hidden="true"></i> {{ 'invoices.display_more_invoices' | translate }}</button>
|
||||
<button class="btn btn-warning" ng-click="showNextInvoices()" ng-hide="noMoreResults"><i class="fa fa-search-plus" aria-hidden="true"></i> {{ 'app.admin.invoices.display_more_invoices' | translate }}</button>
|
||||
</div>
|
||||
<p ng-if="invoices.length == 0" translate>{{ 'invoices.no_invoices_for_now' }}</p>
|
||||
<p ng-if="invoices.length == 0" translate>{{ 'app.admin.invoices.no_invoices_for_now' }}</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@ -116,10 +116,10 @@
|
||||
|
||||
|
||||
|
||||
<uib-tab heading="{{ 'invoices.invoicing_settings' | translate }}" active="tabs.settings.active">
|
||||
<uib-tab heading="{{ 'app.admin.invoices.invoicing_settings' | translate }}" active="tabs.settings.active">
|
||||
<div class="alert alert-warning p-md m-t" role="alert" ng-show="fablabWithoutInvoices">
|
||||
<i class="fa fa-warning m-r"></i>
|
||||
<span translate>{{ 'invoices.warning_invoices_disabled' }}</span>
|
||||
<span translate>{{ 'app.admin.invoices.warning_invoices_disabled' }}</span>
|
||||
</div>
|
||||
<form class="invoice-placeholder">
|
||||
<div class="invoice-logo">
|
||||
@ -128,79 +128,79 @@
|
||||
<div class="tools-box">
|
||||
<div class="btn-group">
|
||||
<div class="btn btn-default btn-file">
|
||||
<i class="fa fa-edit"></i> {{ 'invoices.change_logo' | translate }}
|
||||
<i class="fa fa-edit"></i> {{ 'app.admin.invoices.change_logo' | translate }}
|
||||
<input type="file" accept="image/png,image/jpeg,image/x-png,image/pjpeg" name="invoice[logo][attachment]" ng-model="invoice.logo" base-sixty-four-input>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="invoice-buyer-infos">
|
||||
<strong translate>{{ 'invoices.john_smith' }}</strong>
|
||||
<div translate>{{ 'invoices.john_smith_at_example_com' }}</div>
|
||||
<strong translate>{{ 'app.admin.invoices.john_smith' }}</strong>
|
||||
<div translate>{{ 'app.admin.invoices.john_smith_at_example_com' }}</div>
|
||||
</div>
|
||||
<div class="invoice-reference invoice-editable" ng-click="openEditReference()">{{ 'invoices.invoice_reference_' | translate }} {{mkReference()}}</div>
|
||||
<div class="invoice-code invoice-editable" ng-show="invoice.code.active" ng-click="openEditCode()">{{ 'invoices.code_' | translate }} {{invoice.code.model}}</div>
|
||||
<div class="invoice-code invoice-activable" ng-show="!invoice.code.active" ng-click="openEditCode()" translate>{{ 'invoices.code_disabled' }}</div>
|
||||
<div class="invoice-order invoice-editable" ng-click="openEditInvoiceNb()"> {{ 'invoices.order_num' | translate }} {{mkNumber()}}</div>
|
||||
<div class="invoice-date">{{ 'invoices.invoice_issued_on_DATE_at_TIME' | translate:{DATE:(today | amDateFormat:'L'), TIME:(today | amDateFormat:'LT')} }}</div>
|
||||
<div class="invoice-reference invoice-editable" ng-click="openEditReference()">{{ 'app.admin.invoices.invoice_reference_' | translate }} {{mkReference()}}</div>
|
||||
<div class="invoice-code invoice-editable" ng-show="invoice.code.active" ng-click="openEditCode()">{{ 'app.admin.invoices.code_' | translate }} {{invoice.code.model}}</div>
|
||||
<div class="invoice-code invoice-activable" ng-show="!invoice.code.active" ng-click="openEditCode()" translate>{{ 'app.admin.invoices.code_disabled' }}</div>
|
||||
<div class="invoice-order invoice-editable" ng-click="openEditInvoiceNb()"> {{ 'app.admin.invoices.order_num' | translate }} {{mkNumber()}}</div>
|
||||
<div class="invoice-date">{{ 'app.admin.invoices.invoice_issued_on_DATE_at_TIME' | translate:{DATE:(today | amDateFormat:'L'), TIME:(today | amDateFormat:'LT')} }}</div>
|
||||
<div class="invoice-object">
|
||||
{{ 'invoices.object_reservation_of_john_smith_on_DATE_at_TIME' | translate:{DATE:(inOneWeek | amDateFormat:'L'), TIME:(inOneWeek | amDateFormat:'LT')} }}
|
||||
{{ 'app.admin.invoices.object_reservation_of_john_smith_on_DATE_at_TIME' | translate:{DATE:(inOneWeek | amDateFormat:'L'), TIME:(inOneWeek | amDateFormat:'LT')} }}
|
||||
</div>
|
||||
<div class="invoice-data">
|
||||
{{ 'invoices.order_summary' | translate }}
|
||||
{{ 'app.admin.invoices.order_summary' | translate }}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th translate>{{ 'invoices.details' }}</th>
|
||||
<th class="right" translate>{{ 'invoices.amount' }}</th>
|
||||
<th translate>{{ 'app.admin.invoices.details' }}</th>
|
||||
<th class="right" translate>{{ 'app.admin.invoices.amount' }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{ 'invoices.machine_booking-3D_printer' | translate }} {{inOneWeek | amDateFormat:'LLL'}} - {{inOneWeekAndOneHour | amDateFormat:'LT'}}</td>
|
||||
<td>{{ 'app.admin.invoices.machine_booking-3D_printer' | translate }} {{inOneWeek | amDateFormat:'LLL'}} - {{inOneWeekAndOneHour | amDateFormat:'LT'}}</td>
|
||||
<td class="right">{{30.0 | currency}}</td>
|
||||
</tr>
|
||||
|
||||
<tr class="invoice-total" ng-class="{'bold vat-line':invoice.VAT.active}">
|
||||
<td ng-show="!invoice.VAT.active" translate>{{ 'invoices.total_amount' }}</td>
|
||||
<td ng-show="invoice.VAT.active" translate>{{ 'invoices.total_including_all_taxes' }}</td>
|
||||
<td ng-show="!invoice.VAT.active" translate>{{ 'app.admin.invoices.total_amount' }}</td>
|
||||
<td ng-show="invoice.VAT.active" translate>{{ 'app.admin.invoices.total_including_all_taxes' }}</td>
|
||||
<td class="right">{{30.0 | currency}}</td>
|
||||
</tr>
|
||||
|
||||
<tr class="invoice-vat invoice-activable" ng-click="openEditVAT()" ng-show="!invoice.VAT.active">
|
||||
<td translate>{{ 'invoices.VAT_disabled' }}</td>
|
||||
<td translate>{{ 'app.admin.invoices.VAT_disabled' }}</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr class="invoice-vat invoice-editable vat-line italic" ng-click="openEditVAT()" ng-show="invoice.VAT.active">
|
||||
<td>{{ 'invoices.including_VAT' | translate }} {{invoice.VAT.rate}} %</td>
|
||||
<td>{{ 'app.admin.invoices.including_VAT' | translate }} {{invoice.VAT.rate}} %</td>
|
||||
<td>{{30-(30/(invoice.VAT.rate/100+1)) | currency}}</td>
|
||||
</tr>
|
||||
<tr class="invoice-ht vat-line italic" ng-show="invoice.VAT.active">
|
||||
<td translate>{{ 'invoices.including_total_excluding_taxes' }}</td>
|
||||
<td translate>{{ 'app.admin.invoices.including_total_excluding_taxes' }}</td>
|
||||
<td>{{30/(invoice.VAT.rate/100+1) | currency}}</td>
|
||||
</tr>
|
||||
<tr class="invoice-payed vat-line bold" ng-show="invoice.VAT.active">
|
||||
<td translate>{{ 'invoices.including_amount_payed_on_ordering' }}</td>
|
||||
<td translate>{{ 'app.admin.invoices.including_amount_payed_on_ordering' }}</td>
|
||||
<td>{{30.0 | currency}}</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
<p class="invoice-payment" translate translate-values="{DATE:(today | amDateFormat:'L'), TIME:(today | amDateFormat:'LT'), AMOUNT:(30.0 | currency)}">
|
||||
{{ 'invoices.settlement_by_debit_card_on_DATE_at_TIME_for_an_amount_of_AMOUNT' }}
|
||||
{{ 'app.admin.invoices.settlement_by_debit_card_on_DATE_at_TIME_for_an_amount_of_AMOUNT' }}
|
||||
</p>
|
||||
</div>
|
||||
<div medium-editor class="invoice-text invoice-editable" ng-model="invoice.text.content"
|
||||
options='{
|
||||
"placeholder": "{{ "invoices.important_notes" | translate }}",
|
||||
"placeholder": "{{ "app.admin.invoices.important_notes" | translate }}",
|
||||
"buttons": ["underline"]
|
||||
}'
|
||||
ng-blur="textEditEnd($event)">
|
||||
</div>
|
||||
<div medium-editor class="invoice-legals invoice-editable" ng-model="invoice.legals.content"
|
||||
options='{
|
||||
"placeholder": "{{ "invoices.address_and_legal_information" | translate }}",
|
||||
"placeholder": "{{ "app.admin.invoices.address_and_legal_information" | translate }}",
|
||||
"buttons": ["bold", "underline"]
|
||||
}'
|
||||
ng-blur="legalsEditEnd($event)">
|
||||
@ -211,116 +211,116 @@
|
||||
|
||||
|
||||
|
||||
<uib-tab heading="{{ 'invoices.accounting_codes' | translate }}">
|
||||
<uib-tab heading="{{ 'app.admin.invoices.accounting_codes' | translate }}">
|
||||
<div class="panel panel-default m-t-md accounting-codes">
|
||||
<div class="panel-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label for="journalCode" translate>{{ 'invoices.accounting_journal_code' }}</label>
|
||||
<input type="text" id="journalCode" ng-model="settings.journalCode.value" class="form-control" placeholder="{{ 'invoices.general_journal_code' | translate }}"/>
|
||||
<label for="journalCode" translate>{{ 'app.admin.invoices.accounting_journal_code' }}</label>
|
||||
<input type="text" id="journalCode" ng-model="settings.journalCode.value" class="form-control" placeholder="{{ 'app.admin.invoices.general_journal_code' | translate }}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label for="cardClientCode" translate>{{ 'invoices.accounting_card_client_code' }}</label>
|
||||
<input type="text" id="cardClientCode" ng-model="settings.cardClientCode.value" class="form-control" placeholder="{{ 'invoices.card_client_code' | translate }}" />
|
||||
<label for="cardClientCode" translate>{{ 'app.admin.invoices.accounting_card_client_code' }}</label>
|
||||
<input type="text" id="cardClientCode" ng-model="settings.cardClientCode.value" class="form-control" placeholder="{{ 'app.admin.invoices.card_client_code' | translate }}" />
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="cardClientLabel" translate>{{ 'invoices.accounting_card_client_label' }}</label>
|
||||
<input type="text" id="cardClientLabel" ng-model="settings.cardClientLabel.value" class="form-control" placeholder="{{ 'invoices.card_client_label' | translate }}"/>
|
||||
<label for="cardClientLabel" translate>{{ 'app.admin.invoices.accounting_card_client_label' }}</label>
|
||||
<input type="text" id="cardClientLabel" ng-model="settings.cardClientLabel.value" class="form-control" placeholder="{{ 'app.admin.invoices.card_client_label' | translate }}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label for="walletClientCode" translate>{{ 'invoices.accounting_wallet_client_code' }}</label>
|
||||
<input type="text" id="walletClientCode" ng-model="settings.walletClientCode.value" class="form-control" placeholder="{{ 'invoices.wallet_client_code' | translate }}" />
|
||||
<label for="walletClientCode" translate>{{ 'app.admin.invoices.accounting_wallet_client_code' }}</label>
|
||||
<input type="text" id="walletClientCode" ng-model="settings.walletClientCode.value" class="form-control" placeholder="{{ 'app.admin.invoices.wallet_client_code' | translate }}" />
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="walletClientLabel" translate>{{ 'invoices.accounting_wallet_client_label' }}</label>
|
||||
<input type="text" id="walletClientLabel" ng-model="settings.walletClientLabel.value" class="form-control" placeholder="{{ 'invoices.wallet_client_label' | translate }}"/>
|
||||
<label for="walletClientLabel" translate>{{ 'app.admin.invoices.accounting_wallet_client_label' }}</label>
|
||||
<input type="text" id="walletClientLabel" ng-model="settings.walletClientLabel.value" class="form-control" placeholder="{{ 'app.admin.invoices.wallet_client_label' | translate }}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label for="otherClientCode" translate>{{ 'invoices.accounting_other_client_code' }}</label>
|
||||
<input type="text" id="otherClientCode" ng-model="settings.otherClientCode.value" class="form-control" placeholder="{{ 'invoices.other_client_code' | translate }}" />
|
||||
<label for="otherClientCode" translate>{{ 'app.admin.invoices.accounting_other_client_code' }}</label>
|
||||
<input type="text" id="otherClientCode" ng-model="settings.otherClientCode.value" class="form-control" placeholder="{{ 'app.admin.invoices.other_client_code' | translate }}" />
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="otherClientLabel" translate>{{ 'invoices.accounting_other_client_label' }}</label>
|
||||
<input type="text" id="otherClientLabel" ng-model="settings.otherClientLabel.value" class="form-control" placeholder="{{ 'invoices.other_client_label' | translate }}"/>
|
||||
<label for="otherClientLabel" translate>{{ 'app.admin.invoices.accounting_other_client_label' }}</label>
|
||||
<input type="text" id="otherClientLabel" ng-model="settings.otherClientLabel.value" class="form-control" placeholder="{{ 'app.admin.invoices.other_client_label' | translate }}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label for="walletCode" translate>{{ 'invoices.accounting_wallet_code' }}</label>
|
||||
<input type="text" id="walletCode" ng-model="settings.walletCode.value" class="form-control" placeholder="{{ 'invoices.general_wallet_code' | translate }}" />
|
||||
<label for="walletCode" translate>{{ 'app.admin.invoices.accounting_wallet_code' }}</label>
|
||||
<input type="text" id="walletCode" ng-model="settings.walletCode.value" class="form-control" placeholder="{{ 'app.admin.invoices.general_wallet_code' | translate }}" />
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="walletLabel" translate>{{ 'invoices.accounting_wallet_label' }}</label>
|
||||
<input type="text" id="walletLabel" ng-model="settings.walletLabel.value" class="form-control" placeholder="{{ 'invoices.general_wallet_label' | translate }}"/>
|
||||
<label for="walletLabel" translate>{{ 'app.admin.invoices.accounting_wallet_label' }}</label>
|
||||
<input type="text" id="walletLabel" ng-model="settings.walletLabel.value" class="form-control" placeholder="{{ 'app.admin.invoices.general_wallet_label' | translate }}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label for="vatCode" translate>{{ 'invoices.accounting_vat_code' }}</label>
|
||||
<input type="text" id="vatCode" ng-model="settings.vatCode.value" class="form-control" placeholder="{{ 'invoices.general_vat_code' | translate }}"/>
|
||||
<label for="vatCode" translate>{{ 'app.admin.invoices.accounting_vat_code' }}</label>
|
||||
<input type="text" id="vatCode" ng-model="settings.vatCode.value" class="form-control" placeholder="{{ 'app.admin.invoices.general_vat_code' | translate }}"/>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="vatLabel" translate>{{ 'invoices.accounting_vat_label' }}</label>
|
||||
<input type="text" id="vatLabel" ng-model="settings.vatLabel.value" class="form-control" placeholder="{{ 'invoices.general_vat_label' | translate }}"/>
|
||||
<label for="vatLabel" translate>{{ 'app.admin.invoices.accounting_vat_label' }}</label>
|
||||
<input type="text" id="vatLabel" ng-model="settings.vatLabel.value" class="form-control" placeholder="{{ 'app.admin.invoices.general_vat_label' | translate }}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label for="subscriptionCode" translate>{{ 'invoices.accounting_subscription_code' }}</label>
|
||||
<input type="text" id="subscriptionCode" ng-model="settings.subscriptionCode.value" class="form-control" placeholder="{{ 'invoices.general_subscription_code' | translate }}" />
|
||||
<label for="subscriptionCode" translate>{{ 'app.admin.invoices.accounting_subscription_code' }}</label>
|
||||
<input type="text" id="subscriptionCode" ng-model="settings.subscriptionCode.value" class="form-control" placeholder="{{ 'app.admin.invoices.general_subscription_code' | translate }}" />
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="subscriptionLabel" translate>{{ 'invoices.accounting_subscription_label' }}</label>
|
||||
<input type="text" id="subscriptionLabel" ng-model="settings.subscriptionLabel.value" class="form-control" placeholder="{{ 'invoices.general_subscription_label' | translate }}"/>
|
||||
<label for="subscriptionLabel" translate>{{ 'app.admin.invoices.accounting_subscription_label' }}</label>
|
||||
<input type="text" id="subscriptionLabel" ng-model="settings.subscriptionLabel.value" class="form-control" placeholder="{{ 'app.admin.invoices.general_subscription_label' | translate }}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label for="machineCode" translate>{{ 'invoices.accounting_Machine_code' }}</label>
|
||||
<input type="text" id="machineCode" ng-model="settings.machineCode.value" class="form-control" placeholder="{{ 'invoices.general_machine_code' | translate }}"/>
|
||||
<label for="machineCode" translate>{{ 'app.admin.invoices.accounting_Machine_code' }}</label>
|
||||
<input type="text" id="machineCode" ng-model="settings.machineCode.value" class="form-control" placeholder="{{ 'app.admin.invoices.general_machine_code' | translate }}"/>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="machineLabel" translate>{{ 'invoices.accounting_Machine_label' }}</label>
|
||||
<input type="text" id="machineLabel" ng-model="settings.machineLabel.value" class="form-control" placeholder="{{ 'invoices.general_machine_label' | translate }}"/>
|
||||
<label for="machineLabel" translate>{{ 'app.admin.invoices.accounting_Machine_label' }}</label>
|
||||
<input type="text" id="machineLabel" ng-model="settings.machineLabel.value" class="form-control" placeholder="{{ 'app.admin.invoices.general_machine_label' | translate }}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label for="trainingCode" translate>{{ 'invoices.accounting_Training_code' }}</label>
|
||||
<input type="text" id="trainingCode" ng-model="settings.trainingCode.value" class="form-control" placeholder="{{ 'invoices.general_training_code' | translate }}" />
|
||||
<label for="trainingCode" translate>{{ 'app.admin.invoices.accounting_Training_code' }}</label>
|
||||
<input type="text" id="trainingCode" ng-model="settings.trainingCode.value" class="form-control" placeholder="{{ 'app.admin.invoices.general_training_code' | translate }}" />
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="trainingLabel" translate>{{ 'invoices.accounting_Training_label' }}</label>
|
||||
<input type="text" id="trainingLabel" ng-model="settings.trainingLabel.value" class="form-control" placeholder="{{ 'invoices.general_training_label' | translate }}"/>
|
||||
<label for="trainingLabel" translate>{{ 'app.admin.invoices.accounting_Training_label' }}</label>
|
||||
<input type="text" id="trainingLabel" ng-model="settings.trainingLabel.value" class="form-control" placeholder="{{ 'app.admin.invoices.general_training_label' | translate }}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label for="eventCode" translate>{{ 'invoices.accounting_Event_code' }}</label>
|
||||
<input type="text" id="eventCode" ng-model="settings.eventCode.value" class="form-control" placeholder="{{ 'invoices.general_event_code' | translate }}"/>
|
||||
<label for="eventCode" translate>{{ 'app.admin.invoices.accounting_Event_code' }}</label>
|
||||
<input type="text" id="eventCode" ng-model="settings.eventCode.value" class="form-control" placeholder="{{ 'app.admin.invoices.general_event_code' | translate }}"/>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="eventLabel" translate>{{ 'invoices.accounting_Event_label' }}</label>
|
||||
<input type="text" id="eventLabel" ng-model="settings.eventLabel.value" class="form-control" placeholder="{{ 'invoices.general_event_label' | translate }}"/>
|
||||
<label for="eventLabel" translate>{{ 'app.admin.invoices.accounting_Event_label' }}</label>
|
||||
<input type="text" id="eventLabel" ng-model="settings.eventLabel.value" class="form-control" placeholder="{{ 'app.admin.invoices.general_event_label' | translate }}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label for="spaceCode" translate>{{ 'invoices.accounting_Space_code' }}</label>
|
||||
<input type="text" id="spaceCode" ng-model="settings.spaceCode.value" class="form-control" placeholder="{{ 'invoices.general_space_code' | translate }}" />
|
||||
<label for="spaceCode" translate>{{ 'app.admin.invoices.accounting_Space_code' }}</label>
|
||||
<input type="text" id="spaceCode" ng-model="settings.spaceCode.value" class="form-control" placeholder="{{ 'app.admin.invoices.general_space_code' | translate }}" />
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="spaceLabel" translate>{{ 'invoices.accounting_Space_label' }}</label>
|
||||
<input type="text" id="spaceLabel" ng-model="settings.spaceLabel.value" class="form-control" placeholder="{{ 'invoices.general_space_label' | translate }}"/>
|
||||
<label for="spaceLabel" translate>{{ 'app.admin.invoices.accounting_Space_label' }}</label>
|
||||
<input type="text" id="spaceLabel" ng-model="settings.spaceLabel.value" class="form-control" placeholder="{{ 'app.admin.invoices.general_space_label' | translate }}"/>
|
||||
</div>
|
||||
</div>
|
||||
<button name="button" class="btn btn-warning m-t-lg" ng-click="save()" translate>{{ 'save' }}</button>
|
||||
<button name="button" class="btn btn-warning m-t-lg" ng-click="save()" translate>{{ 'app.shared.buttons.save' }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</uib-tab>
|
||||
@ -333,125 +333,125 @@
|
||||
<script type="text/ng-template" id="editReference.html">
|
||||
<div class="custom-invoice">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title" translate>{{ 'invoices.invoice_reference' }}</h3>
|
||||
<h3 class="modal-title" translate>{{ 'app.admin.invoices.invoice_reference' }}</h3>
|
||||
</div>
|
||||
<div class="modal-body row">
|
||||
<div class="elements col-md-4">
|
||||
<h4>Éléments</h4>
|
||||
<ul>
|
||||
<li ng-click="invoice.reference.help = 'addYear.html'">{{ 'invoices.year' | translate }}</li>
|
||||
<li ng-click="invoice.reference.help = 'addMonth.html'">{{ 'invoices.month' | translate }}</li>
|
||||
<li ng-click="invoice.reference.help = 'addDay.html'">{{ 'invoices.day' | translate }}</li>
|
||||
<li ng-click="invoice.reference.help = 'addInvoiceNumber.html'">{{ 'invoices.num_of_invoice' | translate }}</li>
|
||||
<li ng-click="invoice.reference.help = 'addOnlineInfo.html'">{{ 'invoices.online_sales' | translate }}</li>
|
||||
<%# <li ng-click="invoice.reference.help = 'addWalletInfo.html'">{{ 'invoices.wallet' | translate }}</li> %>
|
||||
<li ng-click="invoice.reference.help = 'addRefundInfo.html'">{{ 'invoices.refund' | translate }}</li>
|
||||
<li ng-click="invoice.reference.help = 'addYear.html'">{{ 'app.admin.invoices.year' | translate }}</li>
|
||||
<li ng-click="invoice.reference.help = 'addMonth.html'">{{ 'app.admin.invoices.month' | translate }}</li>
|
||||
<li ng-click="invoice.reference.help = 'addDay.html'">{{ 'app.admin.invoices.day' | translate }}</li>
|
||||
<li ng-click="invoice.reference.help = 'addInvoiceNumber.html'">{{ 'app.admin.invoices.num_of_invoice' | translate }}</li>
|
||||
<li ng-click="invoice.reference.help = 'addOnlineInfo.html'">{{ 'app.admin.invoices.online_sales' | translate }}</li>
|
||||
<%# <li ng-click="invoice.reference.help = 'addWalletInfo.html'">{{ 'app.admin.invoices.wallet' | translate }}</li> %>
|
||||
<li ng-click="invoice.reference.help = 'addRefundInfo.html'">{{ 'app.admin.invoices.refund' | translate }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<div class="model">
|
||||
<h4 translate>{{ 'invoices.model' }}</h4>
|
||||
<h4 translate>{{ 'app.admin.invoices.model' }}</h4>
|
||||
<input type="text" class="form-control" ng-model="model">
|
||||
</div>
|
||||
<div class="help">
|
||||
<h4 translate>{{ 'invoices.documentation' }}</h4>
|
||||
<h4 translate>{{ 'app.admin.invoices.documentation' }}</h4>
|
||||
<ng-include src="invoice.reference.help" autoscroll="true">
|
||||
</ng-include>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-warning" ng-click="ok()" translate>{{ 'confirm' }}</button>
|
||||
<button class="btn btn-default" ng-click="cancel()" translate>{{ 'cancel' }}</button>
|
||||
<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>
|
||||
|
||||
<script type="text/ng-template" id="addYear.html">
|
||||
<table class="invoice-element-legend">
|
||||
<tr><td><strong>YY</strong></td><td translate>{{ 'invoices.2_digits_year' }}</td></tr>
|
||||
<tr><td><strong>YYYY</strong></td><td translate>{{ 'invoices.4_digits_year' }}</td></tr>
|
||||
<tr><td><strong>YY</strong></td><td translate>{{ 'app.admin.invoices.2_digits_year' }}</td></tr>
|
||||
<tr><td><strong>YYYY</strong></td><td translate>{{ 'app.admin.invoices.4_digits_year' }}</td></tr>
|
||||
</table>
|
||||
</script>
|
||||
|
||||
<script type="text/ng-template" id="addMonth.html">
|
||||
<table class="invoice-element-legend">
|
||||
<tr><td><strong>M</strong></td><td translate>{{ 'invoices.month_number' }}</td></tr>
|
||||
<tr><td><strong>MM</strong></td><td translate>{{ 'invoices.2_digits_month_number' }}</td></tr>
|
||||
<tr><td><strong>MMM</strong></td><td translate>{{ 'invoices.3_characters_month_name' }}</td></tr>
|
||||
<tr><td><strong>M</strong></td><td translate>{{ 'app.admin.invoices.month_number' }}</td></tr>
|
||||
<tr><td><strong>MM</strong></td><td translate>{{ 'app.admin.invoices.2_digits_month_number' }}</td></tr>
|
||||
<tr><td><strong>MMM</strong></td><td translate>{{ 'app.admin.invoices.3_characters_month_name' }}</td></tr>
|
||||
</table>
|
||||
</script>
|
||||
|
||||
<script type="text/ng-template" id="addDay.html">
|
||||
<table class="invoice-element-legend">
|
||||
<tr><td><strong>D</strong></td><td translate>{{ 'invoices.day_in_the_month' }}</td></tr>
|
||||
<tr><td><strong>DD</strong></td><td translate>{{ 'invoices.2_digits_day_in_the_month' }}</td></tr>
|
||||
<tr><td><strong>D</strong></td><td translate>{{ 'app.admin.invoices.day_in_the_month' }}</td></tr>
|
||||
<tr><td><strong>DD</strong></td><td translate>{{ 'app.admin.invoices.2_digits_day_in_the_month' }}</td></tr>
|
||||
</table>
|
||||
</script>
|
||||
|
||||
<script type="text/ng-template" id="addInvoiceNumber.html">
|
||||
<table class="invoice-element-legend">
|
||||
<tr><td><strong>dd...dd</strong></td><td translate>{{ 'invoices.n_digits_daily_count_of_invoices' }}</td></tr>
|
||||
<tr><td><strong>mm...mm</strong></td><td translate>{{ 'invoices.n_digits_monthly_count_of_invoices' }}</td></tr>
|
||||
<tr><td><strong>yy...yy</strong></td><td translate>{{ 'invoices.n_digits_annual_amount_of_invoices' }}</td></tr>
|
||||
<tr><td><strong>dd...dd</strong></td><td translate>{{ 'app.admin.invoices.n_digits_daily_count_of_invoices' }}</td></tr>
|
||||
<tr><td><strong>mm...mm</strong></td><td translate>{{ 'app.admin.invoices.n_digits_monthly_count_of_invoices' }}</td></tr>
|
||||
<tr><td><strong>yy...yy</strong></td><td translate>{{ 'app.admin.invoices.n_digits_annual_amount_of_invoices' }}</td></tr>
|
||||
</table>
|
||||
<span class="bottom-notes" translate>{{ 'invoices.beware_if_the_number_exceed_the_specified_length_it_will_be_truncated_by_the_left' }}</span>
|
||||
<span class="bottom-notes" translate>{{ 'app.admin.invoices.beware_if_the_number_exceed_the_specified_length_it_will_be_truncated_by_the_left' }}</span>
|
||||
</script>
|
||||
|
||||
<script type="text/ng-template" id="addOrderNumber.html">
|
||||
<table class="invoice-element-legend">
|
||||
<tr><td><strong>nn...nn</strong></td><td translate>{{ 'invoices.n_digits_count_of_orders' }}</td></tr>
|
||||
<tr><td><strong>dd...dd</strong></td><td translate>{{ 'invoices.n_digits_daily_count_of_orders' }}</td></tr>
|
||||
<tr><td><strong>mm...mm</strong></td><td translate>{{ 'invoices.n_digits_monthly_count_of_orders' }}</td></tr>
|
||||
<tr><td><strong>yy...yy</strong></td><td translate>{{ 'invoices.n_digits_annual_amount_of_orders' }}</td></tr>
|
||||
<tr><td><strong>nn...nn</strong></td><td translate>{{ 'app.admin.invoices.n_digits_count_of_orders' }}</td></tr>
|
||||
<tr><td><strong>dd...dd</strong></td><td translate>{{ 'app.admin.invoices.n_digits_daily_count_of_orders' }}</td></tr>
|
||||
<tr><td><strong>mm...mm</strong></td><td translate>{{ 'app.admin.invoices.n_digits_monthly_count_of_orders' }}</td></tr>
|
||||
<tr><td><strong>yy...yy</strong></td><td translate>{{ 'app.admin.invoices.n_digits_annual_amount_of_orders' }}</td></tr>
|
||||
</table>
|
||||
<span class="bottom-notes" translate>{{ 'invoices.beware_if_the_number_exceed_the_specified_length_it_will_be_truncated_by_the_left' }}</span>
|
||||
<span class="bottom-notes" translate>{{ 'app.admin.invoices.beware_if_the_number_exceed_the_specified_length_it_will_be_truncated_by_the_left' }}</span>
|
||||
</script>
|
||||
|
||||
<script type="text/ng-template" id="addOnlineInfo.html">
|
||||
<table class="invoice-element-legend">
|
||||
<tr><td><strong>X[texte]</strong></td><td>{{ 'invoices.add_a_notice_regarding_the_online_sales_only_if_the_invoice_is_concerned' | translate }} <mark translate>{{ 'invoices.this_will_never_be_added_when_a_refund_notice_is_present' }}</mark> {{ 'invoices.eg_XVL_will_add_VL_to_the_invoices_settled_with_stripe' | translate }}</td></tr>
|
||||
<tr><td><strong>X[texte]</strong></td><td>{{ 'app.admin.invoices.add_a_notice_regarding_the_online_sales_only_if_the_invoice_is_concerned' | translate }} <mark translate>{{ 'app.admin.invoices.this_will_never_be_added_when_a_refund_notice_is_present' }}</mark> {{ 'app.admin.invoices.eg_XVL_will_add_VL_to_the_invoices_settled_with_stripe' | translate }}</td></tr>
|
||||
</table>
|
||||
</script>
|
||||
|
||||
<script type="text/ng-template" id="addWalletInfo.html">
|
||||
<table class="invoice-element-legend">
|
||||
<tr><td><strong>W[texte]</strong></td><td>{{ 'invoices.add_a_notice_regarding_the_wallet_only_if_the_invoice_is_concerned' | translate }} <mark translate>{{ 'invoices.this_will_never_be_added_when_a_refund_notice_is_present' }}</mark> {{ 'invoices.eg_WPM_will_add_PM_to_the_invoices_settled_with_wallet' | translate }}</td></tr>
|
||||
<tr><td><strong>W[texte]</strong></td><td>{{ 'app.admin.invoices.add_a_notice_regarding_the_wallet_only_if_the_invoice_is_concerned' | translate }} <mark translate>{{ 'app.admin.invoices.this_will_never_be_added_when_a_refund_notice_is_present' }}</mark> {{ 'app.admin.invoices.eg_WPM_will_add_PM_to_the_invoices_settled_with_wallet' | translate }}</td></tr>
|
||||
</table>
|
||||
</script>
|
||||
|
||||
<script type="text/ng-template" id="addRefundInfo.html">
|
||||
<table class="invoice-element-legend">
|
||||
<tr><td><strong>R[texte]</strong></td><td>{{ 'invoices.add_a_notice_regarding_refunds_only_if_the_invoice_is_concerned' | translate }}<mark translate>{{ 'invoices.this_will_never_be_added_when_an_online_sales_notice_is_present' }}</mark> {{ 'invoices.eg_RA_will_add_A_to_the_refund_invoices' | translate }}</td></tr>
|
||||
<tr><td><strong>R[texte]</strong></td><td>{{ 'app.admin.invoices.add_a_notice_regarding_refunds_only_if_the_invoice_is_concerned' | translate }}<mark translate>{{ 'app.admin.invoices.this_will_never_be_added_when_an_online_sales_notice_is_present' }}</mark> {{ 'app.admin.invoices.eg_RA_will_add_A_to_the_refund_invoices' | translate }}</td></tr>
|
||||
</table>
|
||||
</script>
|
||||
|
||||
<script type="text/ng-template" id="editCode.html">
|
||||
<div class="custom-invoice">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title" translate>{{ 'invoices.code' }}</h3>
|
||||
<h3 class="modal-title" translate>{{ 'app.admin.invoices.code' }}</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label for="enableCode" class="control-label" translate>{{ 'invoices.enable_the_code' }}</label>
|
||||
<label for="enableCode" class="control-label" translate>{{ 'app.admin.invoices.enable_the_code' }}</label>
|
||||
<input bs-switch
|
||||
ng-model="isSelected"
|
||||
id="enableCode"
|
||||
type="checkbox"
|
||||
class="form-control m-l-sm"
|
||||
switch-on-text="{{ 'invoices.enabled' | translate }}"
|
||||
switch-off-text="{{ 'invoices.disabled' | translate }}"
|
||||
switch-on-text="{{ 'app.admin.invoices.enabled' | translate }}"
|
||||
switch-off-text="{{ 'app.admin.invoices.disabled' | translate }}"
|
||||
switch-animate="true"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-show="isSelected">
|
||||
<label for="codeModel" class="control-label" translate>{{ 'invoices.code' }}</label>
|
||||
<label for="codeModel" class="control-label" translate>{{ 'app.admin.invoices.code' }}</label>
|
||||
<input id="codeModel" type="text" ng-model="codeModel" class="form-control"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-warning" ng-click="ok()" translate>{{ 'confirm' }}</button>
|
||||
<button class="btn btn-default" ng-click="cancel()" translate>{{ 'cancel' }}</button>
|
||||
<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>
|
||||
@ -461,33 +461,33 @@
|
||||
<script type="text/ng-template" id="editNumber.html">
|
||||
<div class="custom-invoice">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title" translate>{{ 'invoices.order_number' }}</h3>
|
||||
<h3 class="modal-title" translate>{{ 'app.admin.invoices.order_number' }}</h3>
|
||||
</div>
|
||||
<div class="modal-body row">
|
||||
<div class="elements col-md-4">
|
||||
<h4 translate>{{ 'invoices.elements' }}</h4>
|
||||
<h4 translate>{{ 'app.admin.invoices.elements' }}</h4>
|
||||
<ul>
|
||||
<li ng-click="invoice.number.help = 'addYear.html'">{{ 'invoices.year' | translate }}</li>
|
||||
<li ng-click="invoice.number.help = 'addMonth.html'">{{ 'invoices.month' | translate }}</li>
|
||||
<li ng-click="invoice.number.help = 'addDay.html'">{{ 'invoices.day' | translate }}</li>
|
||||
<li ng-click="invoice.number.help = 'addOrderNumber.html'">{{ 'invoices.order_num' | translate }}</li>
|
||||
<li ng-click="invoice.number.help = 'addYear.html'">{{ 'app.admin.invoices.year' | translate }}</li>
|
||||
<li ng-click="invoice.number.help = 'addMonth.html'">{{ 'app.admin.invoices.month' | translate }}</li>
|
||||
<li ng-click="invoice.number.help = 'addDay.html'">{{ 'app.admin.invoices.day' | translate }}</li>
|
||||
<li ng-click="invoice.number.help = 'addOrderNumber.html'">{{ 'app.admin.invoices.order_num' | translate }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<div class="model">
|
||||
<h4 translate>{{ 'invoices.model' }}</h4>
|
||||
<h4 translate>{{ 'app.admin.invoices.model' }}</h4>
|
||||
<input type="text" class="form-control" ng-model="model">
|
||||
</div>
|
||||
<div class="help">
|
||||
<h4 translate>{{ 'invoices.documentation' }}</h4>
|
||||
<h4 translate>{{ 'app.admin.invoices.documentation' }}</h4>
|
||||
<ng-include src="invoice.number.help" autoscroll="true">
|
||||
</ng-include>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-warning" ng-click="ok()" translate>{{ 'confirm' }}</button>
|
||||
<button class="btn btn-default" ng-click="cancel()" translate>{{ 'cancel' }}</button>
|
||||
<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>
|
||||
@ -496,23 +496,23 @@
|
||||
<script type="text/ng-template" id="editVAT.html">
|
||||
<div class="custom-invoice">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title" translate>{{ 'invoices.VAT' }}</h3>
|
||||
<h3 class="modal-title" translate>{{ 'app.admin.invoices.VAT' }}</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label for="enableVAT" class="control-label" translate>{{ 'invoices.enable_VAT' }}</label>
|
||||
<label for="enableVAT" class="control-label" translate>{{ 'app.admin.invoices.enable_VAT' }}</label>
|
||||
<input bs-switch
|
||||
ng-model="isSelected"
|
||||
id="enableVAT"
|
||||
type="checkbox"
|
||||
class="form-control m-l-sm"
|
||||
switch-on-text="{{ 'invoices.enabled' | translate }}"
|
||||
switch-off-text="{{ 'invoices.disabled' | translate }}"
|
||||
switch-on-text="{{ 'app.admin.invoices.enabled' | translate }}"
|
||||
switch-off-text="{{ 'app.admin.invoices.disabled' | translate }}"
|
||||
switch-animate="true"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-show="isSelected">
|
||||
<label for="vatRate" class="control-label" translate>{{ 'invoices.VAT_rate' }}</label>
|
||||
<label for="vatRate" class="control-label" translate>{{ 'app.admin.invoices.VAT_rate' }}</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon">% </span>
|
||||
<input id="vatRate" type="number" ng-model="rate" class="form-control" min="0" max="100"/>
|
||||
@ -520,32 +520,32 @@
|
||||
</div>
|
||||
|
||||
<div class="m-t-lg">
|
||||
<h4 translate>{{ 'invoices.VAT_history' }}</h4>
|
||||
<h4 translate>{{ 'app.admin.invoices.VAT_history' }}</h4>
|
||||
<table class="table scrollable-3-cols">
|
||||
<thead>
|
||||
<tr>
|
||||
<th translate>{{ 'invoices.VAT_rate' }}</th>
|
||||
<th translate>{{ 'invoices.changed_at' }}</th>
|
||||
<th translate>{{ 'invoices.changed_by' }}</th>
|
||||
<th translate>{{ 'app.admin.invoices.VAT_rate' }}</th>
|
||||
<th translate>{{ 'app.admin.invoices.changed_at' }}</th>
|
||||
<th translate>{{ 'app.admin.invoices.changed_by' }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="value in history | orderBy:'-date'">
|
||||
<td>
|
||||
<span class="no-user-label" ng-show="value.enabled === false" translate>{{'invoices.VAT_disabled'}}</span>
|
||||
<span class="no-user-label" ng-show="value.enabled === true" translate>{{'invoices.VAT_enabled'}}</span>
|
||||
<span class="no-user-label" ng-show="value.enabled === false" translate>{{'app.admin.invoices.VAT_disabled'}}</span>
|
||||
<span class="no-user-label" ng-show="value.enabled === true" translate>{{'app.admin.invoices.VAT_enabled'}}</span>
|
||||
<span ng-show="value.rate">{{value.rate}}</span>
|
||||
</td>
|
||||
<td>{{value.date | amDateFormat:'L LT'}}</td>
|
||||
<td>{{value.user.name}}<span class="no-user-label" ng-hide="value.user" translate>{{ 'invoices.deleted_user' }}</span></td>
|
||||
<td>{{value.user.name}}<span class="no-user-label" ng-hide="value.user" translate>{{ 'app.admin.invoices.deleted_user' }}</span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-warning" ng-click="ok()" translate>{{ 'confirm' }}</button>
|
||||
<button class="btn btn-default" ng-click="cancel()" translate>{{ 'cancel' }}</button>
|
||||
<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>
|
||||
|
@ -1,18 +1,18 @@
|
||||
<div class="form-group" ng-class="{'has-error': userForm['user[group_id]'].$dirty && userForm['user[group_id]'].$invalid}">
|
||||
<label for="user_group_id" class="col-sm-3 control-label">
|
||||
<span translate>{{ 'group' }}</span>
|
||||
<span translate>{{ 'app.shared.user_admin.group' }}</span>
|
||||
<span class="exponent"><i class="fa fa-asterisk" aria-hidden="true"></i></span>
|
||||
</label>
|
||||
<div class="col-sm-9">
|
||||
<select ng-model="user.group_id" ng-disabled="user.subscribed_plan" class="form-control" name="user[group_id]" id="user_group_id" ng-options="g.id as g.name for g in groups" required>
|
||||
</select>
|
||||
<input type="hidden" name="user[group_id]" ng-value="user.group_id" />
|
||||
<span class="help-block" ng-show="userForm['user[group_id]'].$dirty && userForm['user[group_id]'].$error.required" translate>{{ 'group_is_required' }}</span>
|
||||
<span class="help-block" ng-show="userForm['user[group_id]'].$dirty && userForm['user[group_id]'].$error.required" translate>{{ 'app.shared.user_admin.group_is_required' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label" translate>{{ 'trainings' }}</label>
|
||||
<label class="col-sm-2 control-label" translate>{{ 'app.shared.user_admin.trainings' }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="hidden" name="user[statistic_profile_attributes][training_ids][]" value="" />
|
||||
<ui-select multiple ng-model="user.training_ids" class="form-control">
|
||||
@ -28,7 +28,7 @@
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label" translate>{{ 'tags' }}</label>
|
||||
<label class="col-sm-2 control-label" translate>{{ 'app.shared.user_admin.tags' }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="hidden" name="user[tag_ids][]" value="" />
|
||||
<ui-select multiple ng-model="user.tag_ids" name="user[tag_ids][]" class="form-control">
|
||||
|
@ -2,23 +2,23 @@
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="fa fa-filter"></i></span>
|
||||
<input type="text" ng-model="searchFilter" class="form-control" placeholder="{{ 'search_for_an_administrator' | translate }}">
|
||||
<input type="text" ng-model="searchFilter" class="form-control" placeholder="{{ 'app.admin.members.search_for_an_administrator' | translate }}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<button type="button" class="btn btn-warning m-t m-b" ui-sref="app.admin.admins_new" translate>{{ 'add_a_new_administrator' }}</button>
|
||||
<button type="button" class="btn btn-warning m-t m-b" ui-sref="app.admin.admins_new" translate>{{ 'app.admin.members.add_a_new_administrator' }}</button>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:15%"><a href="" ng-click="setOrderAdmin('profile_attributes.last_name')">{{ 'surname' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': orderAdmin =='profile_attributes.last_name', 'fa fa-sort-alpha-desc': orderAdmin =='-profile_attributes.last_name', 'fa fa-arrows-v': orderAdmin }"></i></a></th>
|
||||
<th style="width:15%"><a href="" ng-click="setOrderAdmin('profile_attributes.last_name')">{{ 'app.admin.members.surname' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': orderAdmin =='profile_attributes.last_name', 'fa fa-sort-alpha-desc': orderAdmin =='-profile_attributes.last_name', 'fa fa-arrows-v': orderAdmin }"></i></a></th>
|
||||
|
||||
<th style="width:15%"><a href="" ng-click="setOrderAdmin('profile_attributes.first_name')">{{ 'first_name' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': orderAdmin =='profile_attributes.first_name', 'fa fa-sort-alpha-desc': orderAdmin =='-profile_attributes.first_name', 'fa fa-arrows-v': orderAdmin }"></i></a></th>
|
||||
<th style="width:15%"><a href="" ng-click="setOrderAdmin('profile_attributes.first_name')">{{ 'app.admin.members.first_name' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': orderAdmin =='profile_attributes.first_name', 'fa fa-sort-alpha-desc': orderAdmin =='-profile_attributes.first_name', 'fa fa-arrows-v': orderAdmin }"></i></a></th>
|
||||
|
||||
<th style="width:15%"><a href="" ng-click="setOrderAdmin('email')">{{ 'email' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': orderAdmin =='email', 'fa fa-sort-alpha-desc': orderAdmin =='-email', 'fa fa-arrows-v': orderAdmin }"></i></a></th>
|
||||
<th style="width:15%"><a href="" ng-click="setOrderAdmin('email')">{{ 'app.admin.members.email' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': orderAdmin =='email', 'fa fa-sort-alpha-desc': orderAdmin =='-email', 'fa fa-arrows-v': orderAdmin }"></i></a></th>
|
||||
|
||||
<th style="width:10%"><a href="" ng-click="setOrderAdmin('profile_attributes.phone')">{{ 'phone' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-numeric-asc': orderAdmin =='profile_attributes.phone', 'fa fa-sort-numeric-desc': orderAdmin =='-profile_attributes.phone', 'fa fa-arrows-v': orderAdmin }"></i></a></th>
|
||||
<th style="width:10%"><a href="" ng-click="setOrderAdmin('profile_attributes.phone')">{{ 'app.admin.members.phone' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-numeric-asc': orderAdmin =='profile_attributes.phone', 'fa fa-sort-numeric-desc': orderAdmin =='-profile_attributes.phone', 'fa fa-arrows-v': orderAdmin }"></i></a></th>
|
||||
<th style="width:10%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -9,8 +9,8 @@
|
||||
</div>
|
||||
<div class="col-md-8 b-l b-r">
|
||||
<section class="heading-title">
|
||||
<h1 class="inline">{{ 'user' | translate }} {{ user.name }}</h1>
|
||||
<span class="label label-danger text-white" ng-show="user.need_completion" translate>{{ 'incomplete_profile' }}</span>
|
||||
<h1 class="inline">{{ 'app.shared.user_admin.user' | translate }} {{ user.name }}</h1>
|
||||
<span class="label label-danger text-white" ng-show="user.need_completion" translate>{{ 'app.shared.user_admin.incomplete_profile' }}</span>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
@ -18,7 +18,7 @@
|
||||
<div class="col-md-3">
|
||||
<section class="heading-actions wrapper">
|
||||
<div class="btn btn-lg btn-block btn-default m-t-xs" ng-click="cancel()" translate>
|
||||
{{ 'cancel' }}
|
||||
{{ 'app.shared.buttons.cancel' }}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@ -34,11 +34,11 @@
|
||||
|
||||
<uib-tabset justified="true" class="m-t">
|
||||
|
||||
<uib-tab heading="{{ 'user_profile' | translate }}">
|
||||
<uib-tab heading="{{ 'app.shared.user_admin.user_profile' | translate }}">
|
||||
|
||||
<section class="panel panel-danger m-lg" ng-show="user.need_completion && activeProvider.providable_type !== 'DatabaseProvider'">
|
||||
<div class="panel-body m-r" translate>
|
||||
{{ 'warning_incomplete_user_profile_probably_imported_from_sso' }}
|
||||
{{ 'app.shared.user_admin.warning_incomplete_user_profile_probably_imported_from_sso' }}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@ -46,21 +46,21 @@
|
||||
|
||||
<section class="panel panel-default bg-light m-lg">
|
||||
<div class="panel-body m-r">
|
||||
<ng-include src="'<%= asset_path 'shared/_member_form.html' %>'"></ng-include>
|
||||
<ng-include src="'<%= asset_path "shared/_member_form.html" %>'"></ng-include>
|
||||
|
||||
<ng-include src="'<%= asset_path 'admin/members/_form.html' %>'"></ng-include>
|
||||
<ng-include src="'<%= asset_path "admin/members/_form.html" %>'"></ng-include>
|
||||
|
||||
</div> <!-- ./panel-body -->
|
||||
|
||||
|
||||
<div class="panel-footer no-padder">
|
||||
<input type="submit" value="{{ 'confirm_changes' | translate }}" class="r-b btn-valid btn btn-warning btn-block p-lg btn-lg text-u-c" ng-disabled="userForm.$invalid"/>
|
||||
<input type="submit" value="{{ 'app.shared.buttons.confirm_changes' | translate }}" class="r-b btn-valid btn btn-warning btn-block p-lg btn-lg text-u-c" ng-disabled="userForm.$invalid"/>
|
||||
</div>
|
||||
</section>
|
||||
</form>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'subscription' | translate }}" ng-if="!fablabWithoutPlans">
|
||||
<uib-tab heading="{{ 'app.admin.members_edit.subscription' | translate }}" ng-if="!fablabWithoutPlans">
|
||||
|
||||
|
||||
<section class="panel panel-default bg-light m-lg">
|
||||
@ -68,24 +68,24 @@
|
||||
<div class="" ng-show="subscription">
|
||||
<h3>{{ subscription.plan | humanReadablePlanName }}</h3>
|
||||
<p>
|
||||
{{ 'duration' | translate }} {{ subscription.plan.interval | planIntervalFilter: subscription.plan.interval_count }}
|
||||
{{ 'app.admin.members_edit.duration' | translate }} {{ subscription.plan.interval | planIntervalFilter: subscription.plan.interval_count }}
|
||||
</p>
|
||||
<p>
|
||||
{{ 'expires_at' | translate }} {{ subscription.expired_at | amDateFormat: 'L' }}
|
||||
{{ 'app.admin.members_edit.expires_at' | translate }} {{ subscription.expired_at | amDateFormat: 'L' }}
|
||||
</p>
|
||||
<p>
|
||||
{{ 'price_' | translate }} {{ subscription.plan.amount | currency}}
|
||||
{{ 'app.admin.members_edit.price_' | translate }} {{ subscription.plan.amount | currency}}
|
||||
</p>
|
||||
<button class="btn btn-default" ng-click="updateSubscriptionModal(subscription, true)" translate>{{ 'offer_free_days' }}</button>
|
||||
<button class="btn btn-default" ng-click="updateSubscriptionModal(subscription, false)" translate>{{ 'extend_subscription' }}</button>
|
||||
<button class="btn btn-default" ng-click="updateSubscriptionModal(subscription, true)" translate>{{ 'app.admin.members_edit.offer_free_days' }}</button>
|
||||
<button class="btn btn-default" ng-click="updateSubscriptionModal(subscription, false)" translate>{{ 'app.admin.members_edit.extend_subscription' }}</button>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="" ng-hide="subscription">
|
||||
<p translate>
|
||||
{{ 'user_has_no_current_subscription' }}
|
||||
{{ 'app.admin.members_edit.user_has_no_current_subscription' }}
|
||||
</p>
|
||||
<button class="btn btn-default" ng-click="createSubscriptionModal(user, plans.filter(filterDisabledPlans))" translate>{{ 'subscribe_to_a_plan' }}</button>
|
||||
<button class="btn btn-default" ng-click="createSubscriptionModal(user, plans.filter(filterDisabledPlans))" translate>{{ 'app.admin.members_edit.subscribe_to_a_plan' }}</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@ -93,11 +93,11 @@
|
||||
</section>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'trainings' | translate }}">
|
||||
<uib-tab heading="{{ 'app.admin.members_edit.trainings' | translate }}">
|
||||
<div class="col-md-4">
|
||||
<div class="widget panel b-a m-t-lg">
|
||||
<div class="panel-heading b-b ">
|
||||
<h4 class="text-u-c"><i class="fa fa-tag m-r-xs"></i> {{ 'next_trainings' | translate }}</h4>
|
||||
<h4 class="text-u-c"><i class="fa fa-tag m-r-xs"></i> {{ 'app.admin.members_edit.next_trainings' | translate }}</h4>
|
||||
</div>
|
||||
<div class="widget-content bg-light wrapper r-b">
|
||||
<ul class="list-unstyled" ng-if="user.training_reservations.length > 0">
|
||||
@ -105,14 +105,14 @@
|
||||
<span class="font-sbold">{{r.reservable.name}}</span> - <span class="label label-warning wrapper-sm">{{ r.start_at | amDateFormat:'LLL' }} - {{ r.end_at | amDateFormat:'LT' }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div ng-if="user.training_reservations.length == 0" translate>{{ 'no_trainings' }}</div>
|
||||
<div ng-if="user.training_reservations.length == 0" translate>{{ 'app.admin.members_edit.no_trainings' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="widget panel b-a m-t-lg">
|
||||
<div class="panel-heading b-b">
|
||||
<h4 class="text-u-c"><i class="fa fa-tag m-r-xs"></i> {{ 'passed_trainings' | translate }}</h4>
|
||||
<h4 class="text-u-c"><i class="fa fa-tag m-r-xs"></i> {{ 'app.admin.members_edit.passed_trainings' | translate }}</h4>
|
||||
</div>
|
||||
<div class="widget-content bg-light wrapper r-b">
|
||||
<ul class="list-unstyled" ng-if="user.training_reservations.length > 0">
|
||||
@ -125,14 +125,14 @@
|
||||
</div> -->
|
||||
</li>
|
||||
</ul>
|
||||
<div ng-if="user.training_reservations.length == 0" translate>{{ 'no_trainings' }}</div>
|
||||
<div ng-if="user.training_reservations.length == 0" translate>{{ 'app.admin.members_edit.no_trainings' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="widget panel b-a m-t-lg">
|
||||
<div class="panel-heading b-b">
|
||||
<h4 class="text-u-c"><i class="fa fa-tag m-r-xs"></i> {{ 'validated_trainings' | translate }}</h4>
|
||||
<h4 class="text-u-c"><i class="fa fa-tag m-r-xs"></i> {{ 'app.admin.members_edit.validated_trainings' | translate }}</h4>
|
||||
</div>
|
||||
<div class="widget-content bg-light wrapper r-b">
|
||||
<ul class="list-unstyled" ng-if="user.trainings.length > 0">
|
||||
@ -140,17 +140,17 @@
|
||||
<span class="font-sbold">{{t.name}}</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div ng-if="user.trainings.length == 0" translate>{{ 'no_trainings' }}</div>
|
||||
<div ng-if="user.trainings.length == 0" translate>{{ 'app.admin.members_edit.no_trainings' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'events' | translate }}">
|
||||
<uib-tab heading="{{ 'app.admin.members_edit.events' | translate }}">
|
||||
<div class="col-md-6">
|
||||
<div class="widget panel b-a m m-t-lg">
|
||||
<div class="panel-heading b-b">
|
||||
<h4 class="text-u-c"><i class="fa fa-tag m-r-xs"></i> {{ 'next_events' | translate }}</h4>
|
||||
<h4 class="text-u-c"><i class="fa fa-tag m-r-xs"></i> {{ 'app.admin.members_edit.next_events' | translate }}</h4>
|
||||
</div>
|
||||
<div class="widget-content bg-light wrapper r-b">
|
||||
<ul class="list-unstyled" ng-if="user.events_reservations.length > 0">
|
||||
@ -158,22 +158,22 @@
|
||||
<a class="font-sbold" ui-sref="app.public.events_show({id: r.reservable.id})">{{r.reservable.title}}</a> - <span class="label label-warning wrapper-sm">{{ r.start_at | amDateFormat:'LLL' }} - {{ r.end_at | amDateFormat:'LT' }}</span>
|
||||
<span ng-if="r.nb_reserve_places > 0">
|
||||
<br/>
|
||||
<span translate translate-values="{ NUMBER: r.nb_reserve_places}" translate-interpolation="messageformat">{{ 'NUMBER_full_price_tickets_reserved' }}</span>
|
||||
<span translate translate-values="{ NUMBER: r.nb_reserve_places }">{{ 'app.admin.members_edit.NUMBER_full_price_tickets_reserved' }}</span>
|
||||
</span>
|
||||
<span ng-repeat="ticket in r.tickets">
|
||||
<br/>
|
||||
<span translate translate-values="{ NUMBER: ticket.booked, NAME: ticket.price_category.name }" translate-interpolation="messageformat">{{ 'NUMBER_NAME_tickets_reserved' }}</span>
|
||||
<span translate translate-values="{ NUMBER: ticket.booked, NAME: ticket.price_category.name }">{{ 'app.admin.members_edit.NUMBER_NAME_tickets_reserved' }}</span>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div ng-if="(user.events_reservations | eventsReservationsFilter:'future').length == 0" translate>{{ 'no_upcoming_events' }}</div>
|
||||
<div ng-if="(user.events_reservations | eventsReservationsFilter:'future').length == 0" translate>{{ 'app.admin.members_edit.no_upcoming_events' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="widget panel b-a m m-t-lg">
|
||||
<div class="panel-heading b-b">
|
||||
<h4 class="text-u-c"><i class="fa fa-tag m-r-xs"></i> {{ 'passed_events' | translate }}</h4>
|
||||
<h4 class="text-u-c"><i class="fa fa-tag m-r-xs"></i> {{ 'app.admin.members_edit.passed_events' | translate }}</h4>
|
||||
</div>
|
||||
<div class="widget-content bg-light auto wrapper r-b">
|
||||
<ul class="list-unstyled" ng-if="user.events_reservations.length > 0">
|
||||
@ -181,22 +181,22 @@
|
||||
<span class="font-sbold">{{r.reservable.title}}</span> - <span class="label label-info text-white wrapper-sm">{{ r.start_at | amDateFormat:'LLL' }} - {{ r.end_at | amDateFormat:'LT' }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div ng-if="(user.events_reservations | eventsReservationsFilter:'passed').length == 0" translate>{{ 'no_passed_events' }}</div>
|
||||
<div ng-if="(user.events_reservations | eventsReservationsFilter:'passed').length == 0" translate>{{ 'app.admin.members_edit.no_passed_events' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'invoices' | translate }}" ng-hide="fablabWithoutInvoices">
|
||||
<uib-tab heading="{{ 'app.admin.members_edit.invoices' | translate }}" ng-hide="fablabWithoutInvoices">
|
||||
<div class="col-md-12 m m-t-lg">
|
||||
|
||||
|
||||
<table class="table" ng-if="user.invoices.length > 0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:25%" translate>{{ 'invoice_num' }}</th>
|
||||
<th style="width:25%" translate>{{ 'date' }}</th>
|
||||
<th style="width:25%" translate>{{ 'price' }}</th>
|
||||
<th style="width:25%" translate>{{ 'app.admin.members_edit.invoice_num' }}</th>
|
||||
<th style="width:25%" translate>{{ 'app.admin.members_edit.date' }}</th>
|
||||
<th style="width:25%" translate>{{ 'app.admin.members_edit.price' }}</th>
|
||||
<th style="width:25%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -209,34 +209,34 @@
|
||||
<td>
|
||||
<div class="buttons">
|
||||
<a class="btn btn-default" ng-href="api/invoices/{{invoice.id}}/download" target="_blank" ng-if="!invoice.is_avoir">
|
||||
<i class="fa fa-file-pdf-o"></i> {{ 'download_the_invoice' | translate }}
|
||||
<i class="fa fa-file-pdf-o"></i> {{ 'app.admin.members_edit.download_the_invoice' | translate }}
|
||||
</a>
|
||||
<a class="btn btn-default" ng-href="api/invoices/{{invoice.id}}/download" target="_blank" ng-if="invoice.is_avoir">
|
||||
<i class="fa fa-file-pdf-o"></i> {{ 'download_the_refund_invoice' | translate }}
|
||||
<i class="fa fa-file-pdf-o"></i> {{ 'app.admin.members_edit.download_the_refund_invoice' | translate }}
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p ng-if="user.invoices.length == 0" translate>{{ 'no_invoices_for_now' }}</p>
|
||||
<p ng-if="user.invoices.length == 0" translate>{{ 'app.admin.members_edit.no_invoices_for_now' }}</p>
|
||||
|
||||
</div>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'wallet' | translate }}">
|
||||
<uib-tab heading="{{ 'app.admin.members_edit.wallet' | translate }}">
|
||||
<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>
|
||||
|
||||
<div class="clearfix"></div>
|
||||
<div class="col-sm-4 text-center">
|
||||
<button type="button" class="btn btn-warning m-t m-b" ng-click="createWalletCreditModal(user, wallet)" translate>{{ 'to_credit' }}</button>
|
||||
<button type="button" class="btn btn-warning m-t m-b" ng-click="createWalletCreditModal(user, wallet)" translate>{{ 'app.admin.members_edit.to_credit' }}</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-md-12 m m-t-lg">
|
||||
<ng-include src="'<%= asset_path 'wallet/transactions.html' %>'"></ng-include>
|
||||
<ng-include src="'<%= asset_path "wallet/transactions.html" %>'"></ng-include>
|
||||
</div>
|
||||
</uib-tab>
|
||||
</uib-tabset>
|
||||
|
@ -11,14 +11,14 @@
|
||||
|
||||
<div class="col-md-8 b-l b-r">
|
||||
<section class="heading-title">
|
||||
<h1 translate>{{ 'members_import.import_members' }}</h1>
|
||||
<h1 translate>{{ 'app.admin.members_import.import_members' }}</h1>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<section class="heading-actions wrapper">
|
||||
<a class="btn btn-lg btn-block btn-default m-t-xs" target="_blank" href="example.csv" translate>
|
||||
{{ 'members_import.download_example' }}
|
||||
{{ 'app.admin.members_import.download_example' }}
|
||||
</a>
|
||||
</section>
|
||||
</div>
|
||||
@ -29,7 +29,7 @@
|
||||
<div class="row p-sm">
|
||||
<div class="col-md-12">
|
||||
<p class="alert alert-info" translate>
|
||||
{{ 'members_import.info' }}
|
||||
{{ 'app.admin.members_import.info' }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -37,12 +37,12 @@
|
||||
<div class="row m-h-sm">
|
||||
|
||||
<div class="col-md-6 p-h-s">
|
||||
<h3 translate>{{ 'members_import.groups' }}</h3>
|
||||
<h3 translate>{{ 'app.admin.members_import.groups' }}</h3>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th translate>{{ 'members_import.group_name' }}</th>
|
||||
<th translate>{{ 'members_import.group_identifier' }}</th>
|
||||
<th translate>{{ 'app.admin.members_import.group_name' }}</th>
|
||||
<th translate>{{ 'app.admin.members_import.group_identifier' }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -59,12 +59,12 @@
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 p-h-s">
|
||||
<h3 translate>{{ 'members_import.trainings' }}</h3>
|
||||
<h3 translate>{{ 'app.admin.members_import.trainings' }}</h3>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th translate>{{ 'members_import.training_name' }}</th>
|
||||
<th translate>{{ 'members_import.training_identifier' }}</th>
|
||||
<th translate>{{ 'app.admin.members_import.training_name' }}</th>
|
||||
<th translate>{{ 'app.admin.members_import.training_identifier' }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -86,12 +86,12 @@
|
||||
<div class="row m-h-sm">
|
||||
|
||||
<div class="col-md-6 p-h-s" ng-hide="tags.length == 0">
|
||||
<h3 translate>{{ 'members_import.tags' }}</h3>
|
||||
<h3 translate>{{ 'app.admin.members_import.tags' }}</h3>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th translate>{{ 'members_import.tag_name' }}</th>
|
||||
<th translate>{{ 'members_import.tag_identifier' }}</th>
|
||||
<th translate>{{ 'app.admin.members_import.tag_name' }}</th>
|
||||
<th translate>{{ 'app.admin.members_import.tag_identifier' }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -119,10 +119,10 @@
|
||||
|
||||
<div class="m-t">
|
||||
<p class="alert alert-warning m-h" translate>
|
||||
{{ 'members_import.required_fields' }}
|
||||
{{ 'app.admin.members_import.required_fields' }}
|
||||
</p>
|
||||
<p class="alert alert-warning m-h" translate>
|
||||
{{ 'members_import.about_example' }}
|
||||
{{ 'app.admin.members_import.about_example' }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@ -130,8 +130,8 @@
|
||||
<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>{{ 'members_import.select_file' }}</span>
|
||||
<span class="fileinput-exists" translate>{{ 'change' }}</span>
|
||||
<span class="input-group-addon btn btn-default btn-file"><span class="fileinput-new" translate>{{ 'app.admin.members_import.select_file' }}</span>
|
||||
<span class="fileinput-exists" translate>{{ 'app.shared.buttons.change' }}</span>
|
||||
<input type="file"
|
||||
name="import_members"
|
||||
accept="text/csv"
|
||||
@ -140,23 +140,23 @@
|
||||
</div>
|
||||
|
||||
<div class="m-h">
|
||||
<span translate>{{ 'members_import.update_field' }}</span>
|
||||
<span translate>{{ 'app.admin.members_import.update_field' }}</span>
|
||||
<div class="radio m-l-md">
|
||||
<label class="control-label">
|
||||
<input type="radio" id="update_field" name="update_field" value="id" checked>
|
||||
<span translate>{{ 'members_import.update_on_id' }}</span>
|
||||
<span translate>{{ 'app.admin.members_import.update_on_id' }}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio m-l-md">
|
||||
<label class="control-label">
|
||||
<input type="radio" id="update_field" name="update_field" value="username">
|
||||
<span translate>{{ 'members_import.update_on_username' }}</span>
|
||||
<span translate>{{ 'app.admin.members_import.update_on_username' }}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio m-l-md">
|
||||
<label class="control-label">
|
||||
<input type="radio" id="update_field" name="update_field" value="email">
|
||||
<span translate>{{ 'members_import.update_on_email' }}</span>
|
||||
<span translate>{{ 'app.admin.members_import.update_on_email' }}</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@ -165,7 +165,7 @@
|
||||
|
||||
|
||||
<div class="panel-footer no-padder">
|
||||
<input type="submit" value="{{ 'members_import.import' | translate }}" class="r-b btn-valid btn btn-warning btn-block p-lg btn-lg text-u-c" ng-disabled="importForm.$invalid"/>
|
||||
<input type="submit" value="{{ 'app.admin.members_import.import' | translate }}" class="r-b btn-valid btn btn-warning btn-block p-lg btn-lg text-u-c" ng-disabled="importForm.$invalid"/>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
<div class="col-md-8 b-l">
|
||||
<section class="heading-title">
|
||||
<h1 translate>{{ 'members_import_result.import_results' }}</h1>
|
||||
<h1 translate>{{ 'app.admin.members_import_result.import_results' }}</h1>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@ -22,11 +22,11 @@
|
||||
<div class="row no-gutter">
|
||||
<div class="col-sm-12 col-md-12">
|
||||
|
||||
<h2 class="m-l-lg">{{ 'members_import_result.import_details' | translate:{DATE:(import.created_at | amDateFormat:'L'), USER:import.user.full_name, ID:import.id} }}</h2>
|
||||
<h2 class="m-l-lg">{{ 'app.admin.members_import_result.import_details' | translate:{DATE:(import.created_at | amDateFormat:'L'), USER:import.user.full_name, ID:import.id} }}</h2>
|
||||
|
||||
<h3 class="m-l-lg" ng-hide="results"><i class="fa fa-spinner fa-pulse"></i> <span translate>{{ 'members_import_result.pending' }}</span></h3>
|
||||
<h3 class="m-l-lg" ng-hide="results"><i class="fa fa-spinner fa-pulse"></i> <span translate>{{ 'app.admin.members_import_result.pending' }}</span></h3>
|
||||
<div ng-show="results">
|
||||
<h3 class="m-l-lg" translate>{{ 'members_import_result.results' }}</h3>
|
||||
<h3 class="m-l-lg" translate>{{ 'app.admin.members_import_result.results' }}</h3>
|
||||
|
||||
<div class="row p-h-lg" ng-repeat="resultRow in results track by $index">
|
||||
<div class="scroll-x">
|
||||
@ -41,21 +41,21 @@
|
||||
</div>
|
||||
<div ng-if="resultRow.status">
|
||||
<i class="fa fa-arrow-right m-l-lg m-r"></i>
|
||||
<span class="m-r-md">{{ 'members_import_result.status_' + resultRow.status | translate:{ID:resultRow.user} }}</span>
|
||||
<span class="m-r-md">{{ 'app.admin.members_import_result.status_' + resultRow.status | translate:{ID:resultRow.user} }}</span>
|
||||
<span ng-show="resultRow.result" class="green font-bold">
|
||||
<i class="fa fa-check-square-o fa-stack-outside"></i>
|
||||
<span class="m-l" translate>{{ 'members_import_result.success' }}</span>
|
||||
<span class="m-l" translate>{{ 'app.admin.members_import_result.success' }}</span>
|
||||
</span>
|
||||
<span ng-hide="resultRow.result" class="text-red-only font-bold">
|
||||
<span class="fa-stack v-bottom">
|
||||
<i class="fa fa-square-o fa-stack-1x fa-stack-outside"></i>
|
||||
<i class="fa fa-times fa-stack-1x fa-stack-inside"></i>
|
||||
</span>
|
||||
<span class="m-l" translate>{{ 'members_import_result.failed' }}</span>
|
||||
<span class="m-l" translate>{{ 'app.admin.members_import_result.failed' }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="m-l-lg text-red-only" ng-if="!resultRow.row && !resultRow.status">
|
||||
<span class="m-r" translate>{{ 'members_import_result.error_details' }}</span>{{resultRow}}
|
||||
<span class="m-r" translate>{{ 'app.admin.members_import_result.error_details' }}</span>{{resultRow}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -7,7 +7,7 @@
|
||||
</div>
|
||||
<div class="col-xs-8 col-sm-8 col-md-8 b-l">
|
||||
<section class="heading-title">
|
||||
<h1 translate>{{ 'users_management' }}</h1>
|
||||
<h1 translate>{{ 'app.admin.members.users_management' }}</h1>
|
||||
</section>
|
||||
</div>
|
||||
<div class="col-xs-1 col-xs-offset-1 col-md-offset-2 b-l">
|
||||
@ -26,23 +26,23 @@
|
||||
<div class="col-md-12">
|
||||
<uib-tabset justified="true">
|
||||
|
||||
<uib-tab heading="{{ 'members' | translate }}">
|
||||
<ng-include src="'<%= asset_path 'admin/members/members.html' %>'"></ng-include>
|
||||
<uib-tab heading="{{ 'app.admin.members.members' | translate }}">
|
||||
<ng-include src="'<%= asset_path "admin/members/members.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'administrators' | translate }}">
|
||||
<ng-include src="'<%= asset_path 'admin/members/administrators.html' %>'"></ng-include>
|
||||
<uib-tab heading="{{ 'app.admin.members.administrators' | translate }}">
|
||||
<ng-include src="'<%= asset_path "admin/members/administrators.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'groups' | translate }}">
|
||||
<uib-tab heading="{{ 'app.admin.members.groups' | translate }}">
|
||||
<div ui-view="groups"></div>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'tags' | translate }}">
|
||||
<uib-tab heading="{{ 'app.admin.members.tags' | translate }}">
|
||||
<div ui-view="tags"></div>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'authentication' | translate }}">
|
||||
<uib-tab heading="{{ 'app.admin.members.authentication' | translate }}">
|
||||
<div ui-view="authentification"></div>
|
||||
</uib-tab>
|
||||
</uib-tabset>
|
||||
|
@ -2,21 +2,21 @@
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="fa fa-filter"></i></span>
|
||||
<input type="text" ng-model="member.searchText" class="form-control" placeholder="{{ 'search_for_an_user' | translate }}" ng-change="updateTextSearch()">
|
||||
<input type="text" ng-model="member.searchText" class="form-control" placeholder="{{ 'app.admin.members.search_for_an_user' | translate }}" ng-change="updateTextSearch()">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<button type="button" class="btn btn-warning m-t m-b" ui-sref="app.admin.members_new" translate>{{ 'add_a_new_member' }}</button>
|
||||
<button type="button" class="btn btn-warning m-t m-b" ui-sref="app.admin.members_new" translate>{{ 'app.admin.members.add_a_new_member' }}</button>
|
||||
<div class="pull-right">
|
||||
<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> {{ 'members' | translate }}
|
||||
<i class="fa fa-file-excel-o"></i> {{ 'app.admin.members.members' | translate }}
|
||||
</a>
|
||||
<a class="btn btn-default" ng-href="api/members/export_subscriptions.xlsx" target="export-frame" ng-if="!fablabWithoutPlans" ng-click="alertExport('subscriptions')">
|
||||
<i class="fa fa-file-excel-o"></i> {{ 'subscriptions' | translate }}
|
||||
<i class="fa fa-file-excel-o"></i> {{ 'app.admin.members.subscriptions' | translate }}
|
||||
</a>
|
||||
<a class="btn btn-default" ng-href="api/members/export_reservations.xlsx" target="export-frame" ng-click="alertExport('reservations')">
|
||||
<i class="fa fa-file-excel-o"></i> {{ 'reservations' | translate }}
|
||||
<i class="fa fa-file-excel-o"></i> {{ 'app.admin.members.reservations' | translate }}
|
||||
</a>
|
||||
<iframe name="export-frame" height="0" width="0" class="none"></iframe>
|
||||
</div>
|
||||
@ -25,12 +25,12 @@
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:15%"><a href="" ng-click="setOrderMember('last_name')">{{ 'surname' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': member.order=='last_name', 'fa fa-sort-alpha-desc': member.order=='-last_name', 'fa fa-arrows-v': member.order }"></i></a></th>
|
||||
<th style="width:15%"><a href="" ng-click="setOrderMember('first_name')">{{ 'first_name' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': member.order=='first_name', 'fa fa-sort-alpha-desc': member.order=='-first_name', 'fa fa-arrows-v': member.order }"></i></a></th>
|
||||
<th style="width:15%" class="hidden-xs"><a href="" ng-click="setOrderMember('email')">{{ 'email' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': member.order=='email', 'fa fa-sort-alpha-desc': member.order=='-email', 'fa fa-arrows-v': member.order }"></i></a></th>
|
||||
<th style="width:10%" class="hidden-xs hidden-sm hidden-md"><a href="" ng-click="setOrderMember('phone')">{{ 'phone' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-numeric-asc': member.order=='phone', 'fa fa-sort-numeric-desc': member.order=='-phone', 'fa fa-arrows-v': member.order }"></i></a></th>
|
||||
<th style="width:20%" class="hidden-xs hidden-sm"><a href="" ng-click="setOrderMember('group')">{{ 'user_type' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': member.order=='group', 'fa fa-sort-alpha-desc': member.order=='-group', 'fa fa-arrows-v': member.order }"></i></a></th>
|
||||
<th style="width:15%" class="hidden-xs hidden-sm hidden-md"><a href="" ng-click="setOrderMember('plan')">{{ 'subscription' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': member.order=='plan', 'fa fa-sort-alpha-desc': member.order=='-plan', 'fa fa-arrows-v': member.order }"></i></a></th>
|
||||
<th style="width:15%"><a href="" ng-click="setOrderMember('last_name')">{{ 'app.admin.members.surname' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': member.order=='last_name', 'fa fa-sort-alpha-desc': member.order=='-last_name', 'fa fa-arrows-v': member.order }"></i></a></th>
|
||||
<th style="width:15%"><a href="" ng-click="setOrderMember('first_name')">{{ 'app.admin.members.first_name' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': member.order=='first_name', 'fa fa-sort-alpha-desc': member.order=='-first_name', 'fa fa-arrows-v': member.order }"></i></a></th>
|
||||
<th style="width:15%" class="hidden-xs"><a href="" ng-click="setOrderMember('email')">{{ 'app.admin.members.email' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': member.order=='email', 'fa fa-sort-alpha-desc': member.order=='-email', 'fa fa-arrows-v': member.order }"></i></a></th>
|
||||
<th style="width:10%" class="hidden-xs hidden-sm hidden-md"><a href="" ng-click="setOrderMember('phone')">{{ 'app.admin.members.phone' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-numeric-asc': member.order=='phone', 'fa fa-sort-numeric-desc': member.order=='-phone', 'fa fa-arrows-v': member.order }"></i></a></th>
|
||||
<th style="width:20%" class="hidden-xs hidden-sm"><a href="" ng-click="setOrderMember('group')">{{ 'app.admin.members.user_type' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': member.order=='group', 'fa fa-sort-alpha-desc': member.order=='-group', 'fa fa-arrows-v': member.order }"></i></a></th>
|
||||
<th style="width:15%" class="hidden-xs hidden-sm hidden-md"><a href="" ng-click="setOrderMember('plan')">{{ 'app.admin.members.subscription' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': member.order=='plan', 'fa fa-sort-alpha-desc': member.order=='-plan', 'fa fa-arrows-v': member.order }"></i></a></th>
|
||||
<th style="width:10%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -45,15 +45,18 @@
|
||||
<td>
|
||||
<div class="buttons">
|
||||
<button class="btn btn-default" ui-sref="app.admin.members_edit({id: m.id})">
|
||||
<i class="fa fa-edit"></i> {{ 'edit' | translate }}
|
||||
<i class="fa fa-edit"></i>
|
||||
</button>
|
||||
<span class="label label-danger text-white" ng-show="m.need_completion" translate>{{ 'incomplete_profile' }}</span>
|
||||
<button class="btn btn-danger" ng-click="deleteMember(m.id)">
|
||||
<i class="fa fa-trash"></i>
|
||||
</button>
|
||||
<span class="label label-danger text-white" ng-show="m.need_completion" translate>{{ 'app.admin.members.incomplete_profile' }}</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="text-center">
|
||||
<button class="btn btn-warning" ng-click="showNextMembers()" ng-hide="member.noMore"><i class="fa fa-search-plus" aria-hidden="true"></i> {{ 'display_more_users' | translate }}</button>
|
||||
<button class="btn btn-warning" ng-click="showNextMembers()" ng-hide="member.noMore"><i class="fa fa-search-plus" aria-hidden="true"></i> {{ 'app.admin.members.display_more_users' | translate }}</button>
|
||||
</div>
|
||||
</div>
|
@ -9,7 +9,7 @@
|
||||
</div>
|
||||
<div class="col-md-8 b-l b-r">
|
||||
<section class="heading-title">
|
||||
<h1 translate>{{ 'members_new.add_a_member' }}</h1>
|
||||
<h1 translate>{{ 'app.admin.members_new.add_a_member' }}</h1>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
@ -17,7 +17,7 @@
|
||||
<div class="col-md-3">
|
||||
<section class="heading-actions wrapper">
|
||||
<div class="btn btn-lg btn-block btn-default m-t-xs" ng-click="cancel()" translate>
|
||||
{{ 'cancel' }}
|
||||
{{ 'app.shared.buttons.cancel' }}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@ -45,19 +45,19 @@
|
||||
ng-model="user.organization"
|
||||
ng-change="toggleOrganization()"
|
||||
value="false"/>
|
||||
<label for="organization" translate>{{ 'members_new.user_is_an_organization' }}</label>
|
||||
<label for="organization" translate>{{ 'app.admin.members_new.user_is_an_organization' }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ng-include src="'<%= asset_path 'shared/_member_form.html' %>'"></ng-include>
|
||||
<ng-include src="'<%= asset_path "shared/_member_form.html" %>'"></ng-include>
|
||||
|
||||
<ng-include src="'<%= asset_path 'admin/members/_form.html' %>'"></ng-include>
|
||||
<ng-include src="'<%= asset_path "admin/members/_form.html" %>'"></ng-include>
|
||||
</div> <!-- ./panel-body -->
|
||||
|
||||
|
||||
<div class="panel-footer no-padder">
|
||||
<input type="submit" value="{{ 'save' | translate }}" class="r-b btn-valid btn btn-warning btn-block p-lg btn-lg text-u-c" ng-disabled="userForm.$invalid"/>
|
||||
<input type="submit" value="{{ 'app.shared.buttons.save' | translate }}" class="r-b btn-valid btn btn-warning btn-block p-lg btn-lg text-u-c" ng-disabled="userForm.$invalid"/>
|
||||
</div>
|
||||
</section>
|
||||
</form>
|
||||
|
@ -7,7 +7,7 @@
|
||||
</div>
|
||||
<div class="col-xs-10 col-sm-10 col-md-7 b-l b-r-md">
|
||||
<section class="heading-title">
|
||||
<h1 translate>{{ 'open_api_clients' }}</h1>
|
||||
<h1 translate>{{ 'app.admin.open_api_clients.open_api_clients' }}</h1>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
<section class="heading-actions wrapper">
|
||||
<a href="<%= apipie_apipie_path({version: 'v1'}) %>" target="_blank" class="btn btn-info b-2x rounded m-t-sm">
|
||||
<i class="fa fa-book" aria-hidden="true"></i>
|
||||
<span translate>{{ 'api_documentation' }}</span>
|
||||
<span translate>{{ 'app.admin.open_api_clients.api_documentation' }}</span>
|
||||
<span class="exponent"><i class="fa fa-external-link" aria-hidden="true"></i></span>
|
||||
</a>
|
||||
</section>
|
||||
@ -28,27 +28,27 @@
|
||||
<div class="col-md-12">
|
||||
<div class="col-md-12">
|
||||
|
||||
<button type="button" class="btn btn-warning m-t m-b" ng-click="toggleForm()" ng-show="!clientFormVisible" translate>{{ 'add_new_client' | translate }}</button>
|
||||
<button type="button" class="btn btn-warning m-t m-b" ng-click="toggleForm()" ng-show="!clientFormVisible" translate>{{ 'app.admin.open_api_clients.add_new_client' | translate }}</button>
|
||||
|
||||
<form role="form" id="clientForm" ng-show="clientFormVisible" name="clientForm" class="form-inline m-b m-t" novalidate>
|
||||
<div class="form-group" ng-class="{'has-error': clientForm['client[name]'].$dirty && clientForm['client[name]'].$invalid}">
|
||||
<input class="form-control" type="text" name="client[name]" ng-model="client.name" value="" placeholder="{{ 'client_name' | translate }}" required>
|
||||
<input class="form-control" type="text" name="client[name]" ng-model="client.name" value="" placeholder="{{ 'app.admin.open_api_clients.client_name' | translate }}" required>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-default" ng-click="toggleForm()" name="button">{{ 'cancel' | translate }}</button>
|
||||
<input type="submit" class="btn btn-warning" ng-disabled="!client.name || client.name.length == 0" ng-click="saveClient(client)" value="{{ 'save' | translate }}">
|
||||
<button class="btn btn-default" ng-click="toggleForm()" name="button">{{ 'app.shared.buttons.cancel' | translate }}</button>
|
||||
<input type="submit" class="btn btn-warning" ng-disabled="!client.name || client.name.length == 0" ng-click="saveClient(client)" value="{{ 'app.shared.buttons.save' | translate }}">
|
||||
</form>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:20%"><a href="" ng-click="setOrder('name')">{{ 'name' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': order == 'name', 'fa fa-sort-alpha-desc': order == '-name', 'fa fa-arrows-v': order }"></i></a></th>
|
||||
<th style="width:20%"><a href="" ng-click="setOrder('name')">{{ 'app.admin.open_api_clients.name' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': order == 'name', 'fa fa-sort-alpha-desc': order == '-name', 'fa fa-arrows-v': order }"></i></a></th>
|
||||
|
||||
<th style="width:15%"><a href="" ng-click="setOrder('calls_count')">{{ 'calls_count' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-numeric-asc': order == 'calls_count', 'fa fa-sort-numeric-desc': order == '-calls_count', 'fa fa-arrows-v': order }"></i></a></th>
|
||||
<th style="width:15%"><a href="" ng-click="setOrder('calls_count')">{{ 'app.admin.open_api_clients.calls_count' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-numeric-asc': order == 'calls_count', 'fa fa-sort-numeric-desc': order == '-calls_count', 'fa fa-arrows-v': order }"></i></a></th>
|
||||
|
||||
<th style="width:20%"><a href="">{{ 'token' | translate }}</a></th>
|
||||
<th style="width:20%"><a href="">{{ 'app.admin.open_api_clients.token' | translate }}</a></th>
|
||||
|
||||
<th style="width:20%"><a href="" ng-click="setOrder('created_at')">{{ 'created_at' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-numeric-asc': order == 'created_at', 'fa fa-sort-numeric-desc': order == '-created_at', 'fa fa-arrows-v': order }"></i></a></th>
|
||||
<th style="width:20%"><a href="" ng-click="setOrder('created_at')">{{ 'app.admin.open_api_clients.created_at' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-numeric-asc': order == 'created_at', 'fa fa-sort-numeric-desc': order == '-created_at', 'fa fa-arrows-v': order }"></i></a></th>
|
||||
|
||||
<th style="width:25%"></th>
|
||||
</tr>
|
||||
@ -62,11 +62,11 @@
|
||||
<td>
|
||||
<div class="buttons">
|
||||
<button class="btn btn-default" ng-click="editClient(client)">
|
||||
<i class="fa fa-pencil"></i> {{ 'edit' | translate }}
|
||||
<i class="fa fa-pencil"></i> {{ 'app.shared.buttons.edit' | translate }}
|
||||
</button>
|
||||
|
||||
<button class="btn btn-default" ng-click="resetToken(client)">
|
||||
<i class="fa fa-times"></i> {{ 'reset_token' | translate }}
|
||||
<i class="fa fa-times"></i> {{ 'app.admin.open_api_clients.reset_token' | translate }}
|
||||
</button>
|
||||
|
||||
<button class="btn btn-danger" ng-click="deleteClient($index)" ng-show="client.calls_count == 0">
|
||||
|
@ -1,63 +1,63 @@
|
||||
<h2 translate>{{ 'plan_form.general_information' }}</h2>
|
||||
<h2 translate>{{ 'app.shared.plan.general_information' }}</h2>
|
||||
<input type="hidden" name="_method" value="{{method}}">
|
||||
|
||||
<div class="form-group" ng-class="{'has-error': planForm['plan[base_name]'].$dirty && planForm['plan[base_name]'].$invalid}">
|
||||
<label for="plan[base_name]">{{ 'plan_form.name' | translate }} *</label>
|
||||
<label for="plan[base_name]">{{ 'app.shared.plan.name' | translate }} *</label>
|
||||
<input type="text" id="plan[base_name]"
|
||||
name="plan[base_name]"
|
||||
class="form-control"
|
||||
ng-maxlength="24"
|
||||
ng-model="plan.base_name"
|
||||
required="required"/>
|
||||
<span class="help-block error" ng-show="planForm['plan[base_name]'].$dirty && planForm['plan[base_name]'].$error.required" translate>{{ 'plan_form.name_is_required' }}</span>
|
||||
<span class="help-block error" ng-show="planForm['plan[base_name]'].$dirty && planForm['plan[base_name]'].$error.maxlength" translate>{{ 'plan_form.name_length_must_be_less_than_24_characters' }}</span>
|
||||
<span class="help-block error" ng-show="planForm['plan[base_name]'].$dirty && planForm['plan[base_name]'].$error.required" translate>{{ 'app.shared.plan.name_is_required' }}</span>
|
||||
<span class="help-block error" ng-show="planForm['plan[base_name]'].$dirty && planForm['plan[base_name]'].$error.maxlength" translate>{{ 'app.shared.plan.name_length_must_be_less_than_24_characters' }}</span>
|
||||
</div>
|
||||
<div class="form-group" ng-class="{'has-error': planForm['plan[type]'].$dirty && planForm['plan[type]'].$invalid}">
|
||||
<label for="plan[type]">{{ 'plan_form.type' | translate }} *</label>
|
||||
<label for="plan[type]">{{ 'app.shared.plan.type' | translate }} *</label>
|
||||
<select id="plan[type]"
|
||||
name="plan[type]"
|
||||
class="form-control"
|
||||
ng-model="plan.type"
|
||||
required="required"
|
||||
ng-disabled="method == 'PATCH'">
|
||||
<option value="Plan" ng-selected="plan.type == 'Plan'" translate>{{ 'standard' }}</option>
|
||||
<option value="PartnerPlan" ng-selected="plan.type == 'PartnerPlan'" translate>{{ 'partner' }}</option>
|
||||
<option value="Plan" ng-selected="plan.type == 'Plan'" translate>{{ 'app.shared.plan.standard' }}</option>
|
||||
<option value="PartnerPlan" ng-selected="plan.type == 'PartnerPlan'" translate>{{ 'app.shared.plan.partner' }}</option>
|
||||
</select>
|
||||
<span class="help-block error" ng-show="planForm['plan[type]'].$dirty && planForm['plan[type]'].$error.required" translate>{{ 'plan_form.type_is_required' }}</span>
|
||||
<span class="help-block error" ng-show="planForm['plan[type]'].$dirty && planForm['plan[type]'].$error.required" translate>{{ 'app.shared.plan.type_is_required' }}</span>
|
||||
</div>
|
||||
<div class="form-group" ng-class="{'has-error': planForm['plan[group_id]'].$dirty && planForm['plan[group_id]'].$invalid}">
|
||||
<label for="plan[group_id]">{{ 'plan_form.group' | translate }} *</label>
|
||||
<label for="plan[group_id]">{{ 'app.shared.plan.group' | translate }} *</label>
|
||||
<select id="plan[group_id]"
|
||||
name="plan[group_id]"
|
||||
class="form-control"
|
||||
ng-model="plan.group_id"
|
||||
required="required"
|
||||
ng-disabled="method == 'PATCH'">
|
||||
<option value="all" translate>{{ 'plan_form.transversal_all_groups' }}</option>
|
||||
<option value="all" translate>{{ 'app.shared.plan.transversal_all_groups' }}</option>
|
||||
<optgroup label="Groupes">
|
||||
<option ng-repeat="group in groups" value="{{group.id}}" ng-selected="plan.group_id == group.id">{{group.name}}</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
<span class="help-block" ng-show="planForm['plan[group_id]'].$dirty && planForm['plan[group_id]'].$error.required" translate>{{ 'plan_form.group_is_required' }}</span>
|
||||
<span class="help-block" ng-show="planForm['plan[group_id]'].$dirty && planForm['plan[group_id]'].$error.required" translate>{{ 'app.shared.plan.group_is_required' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{'has-error': planForm['plan[interval]'].$dirty && planForm['plan[interval]'].$invalid}">
|
||||
<label for="plan[interval]">{{ 'plan_form.period' | translate }} *</label>
|
||||
<label for="plan[interval]">{{ 'app.shared.plan.period' | translate }} *</label>
|
||||
<select id="plan[interval]"
|
||||
name="plan[interval]"
|
||||
class="form-control"
|
||||
ng-model="plan.interval"
|
||||
ng-disabled="method == 'PATCH'"
|
||||
required="required">
|
||||
<option value="week" ng-selected="plan.interval == 'week'" translate>{{ 'plan_form.week' }}</option>
|
||||
<option value="month" ng-selected="plan.interval == 'month'" translate>{{ 'plan_form.month' }}</option>
|
||||
<option value="year" ng-selected="plan.interval == 'year'" translate>{{ 'plan_form.year' }}</option>
|
||||
<option value="week" ng-selected="plan.interval == 'week'" translate>{{ 'app.shared.plan.week' }}</option>
|
||||
<option value="month" ng-selected="plan.interval == 'month'" translate>{{ 'app.shared.plan.month' }}</option>
|
||||
<option value="year" ng-selected="plan.interval == 'year'" translate>{{ 'app.shared.plan.year' }}</option>
|
||||
</select>
|
||||
<span class="help-block" ng-show="planForm['plan[interval]'].$dirty && planForm['plan[interval]'].$error.required" translate>{{ 'plan_form.period_is_required' }}</span>
|
||||
<span class="help-block" ng-show="planForm['plan[interval]'].$dirty && planForm['plan[interval]'].$error.required" translate>{{ 'app.shared.plan.period_is_required' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{'has-error': planForm['plan[interval_count]'].$dirty && planForm['plan[interval_count]'].$invalid}">
|
||||
<label for="plan[interval]">{{ 'plan_form.number_of_periods' | translate }} *</label>
|
||||
<label for="plan[interval]">{{ 'app.shared.plan.number_of_periods' | translate }} *</label>
|
||||
<input id="plan[interval_count]"
|
||||
name="plan[interval_count]"
|
||||
class="form-control"
|
||||
@ -66,12 +66,12 @@
|
||||
ng-disabled="method == 'PATCH'"
|
||||
required="required"
|
||||
min="1"/>
|
||||
<span class="help-block" ng-show="planForm['plan[interval_count]'].$dirty && planForm['plan[interval_count]'].$error.required" translate>{{ 'plan_form.number_of_periods_is_required' }}</span>
|
||||
<span class="help-block" ng-show="planForm['plan[interval_count]'].$dirty && planForm['plan[interval_count]'].$error.required" translate>{{ 'app.shared.plan.number_of_periods_is_required' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group" ng-class="{'has-error': planForm['plan[amount]'].$dirty && planForm['plan[amount]'].$invalid}">
|
||||
<label for="plan[amount]">{{ 'plan_form.subscription_price' | translate }} *</label>
|
||||
<label for="plan[amount]">{{ 'app.shared.plan.subscription_price' | translate }} *</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon">{{currencySymbol}}</span>
|
||||
<input id="plan[amount]"
|
||||
@ -81,40 +81,40 @@
|
||||
ng-required="true"
|
||||
ng-model="plan.amount"/>
|
||||
</div>
|
||||
<span class="help-block" ng-show="planForm['plan[amount]'].$dirty && planForm['plan[amount]'].$error.required" translate>{{ 'plan_form.price_is_required' }}</span>
|
||||
<span class="help-block" ng-show="planForm['plan[amount]'].$dirty && planForm['plan[amount]'].$error.required" translate>{{ 'app.shared.plan.price_is_required' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label translate>{{ 'plan_form.visual_prominence_of_the_subscription' }}</label>
|
||||
<label translate>{{ 'app.shared.plan.visual_prominence_of_the_subscription' }}</label>
|
||||
<input ng-model="plan.ui_weight"
|
||||
type="number"
|
||||
name="plan[ui_weight]"
|
||||
class="form-control">
|
||||
<span class="help-block">
|
||||
{{ 'plan_form.on_the_subscriptions_page_the_most_prominent_subscriptions_will_be_placed_at_the_top_of_the_list' | translate }}
|
||||
{{ 'plan_form.an_evelated_number_means_a_higher_prominence' | translate }}
|
||||
{{ 'app.shared.plan.on_the_subscriptions_page_the_most_prominent_subscriptions_will_be_placed_at_the_top_of_the_list' | translate }}
|
||||
{{ 'app.shared.plan.an_evelated_number_means_a_higher_prominence' | translate }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="input-group m-t-md">
|
||||
<label for="plan[is_rolling]" class="control-label m-r-md">{{ 'plan_form.rolling_subscription' | translate }} *</label>
|
||||
<label for="plan[is_rolling]" class="control-label m-r-md">{{ 'app.shared.plan.rolling_subscription' | translate }} *</label>
|
||||
<input bs-switch
|
||||
ng-model="plan.is_rolling"
|
||||
id="plan[is_rolling]"
|
||||
ng-if="method != 'PATCH'"
|
||||
type="checkbox"
|
||||
class="form-control"
|
||||
switch-on-text="{{ 'yes' | translate }}"
|
||||
switch-off-text="{{ 'no' | translate }}"
|
||||
switch-on-text="{{ 'app.shared.buttons.yes' | translate }}"
|
||||
switch-off-text="{{ 'app.shared.buttons.no' | translate }}"
|
||||
switch-animate="true"
|
||||
ng-true-value="'true'"
|
||||
ng-false-value="'false'"/>
|
||||
<span ng-if="method == 'PATCH'">{{ (plan.is_rolling ? 'yes' : 'no') | translate }}</span>
|
||||
<input type="hidden" name="plan[is_rolling]" value="{{plan.is_rolling}}"/>
|
||||
<span class="help-block">
|
||||
{{ 'plan_form.a_rolling_subscription_will_begin_the_day_of_the_first_training' | translate }}
|
||||
{{ 'plan_form.otherwise_it_will_begin_as_soon_as_it_is_bought' | translate }}
|
||||
{{ 'app.shared.plan.a_rolling_subscription_will_begin_the_day_of_the_first_training' | translate }}
|
||||
{{ 'app.shared.plan.otherwise_it_will_begin_as_soon_as_it_is_bought' | translate }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@ -122,13 +122,13 @@
|
||||
<!-- PDF description attachement -->
|
||||
<input type="hidden" ng-model="plan.plan_file_attributes.id" name="plan[plan_file_attributes][id]" ng-value="plan.plan_file_attributes.id" />
|
||||
<input type="hidden" ng-model="plan.plan_file_attributes._destroy" name="plan[plan_file_attributes][_destroy]" ng-value="plan.plan_file_attributes._destroy"/>
|
||||
<label class="m-t-md" translate>{{ 'plan_form.information_sheet' }}</label>
|
||||
<label class="m-t-md" translate>{{ 'app.shared.plan.information_sheet' }}</label>
|
||||
<div class="fileinput input-group" data-provides="fileinput" ng-class="fileinputClass(plan.plan_file_attributes)">
|
||||
<div class="form-control" data-trigger="fileinput">
|
||||
<i class="glyphicon glyphicon-file fileinput-exists"></i> <span class="fileinput-filename">{{file.attachment || plan.plan_file_attributes.attachment_identifier}}</span>
|
||||
</div>
|
||||
<span class="input-group-addon btn btn-default btn-file"><span class="fileinput-new" translate>{{ 'plan_form.attach_an_information_sheet' }}</span>
|
||||
<span class="fileinput-exists" translate>{{ 'change' }}</span><input type="file"
|
||||
<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"
|
||||
name="plan[plan_file_attributes][attachment]"
|
||||
accept="image/*, 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>
|
||||
@ -136,7 +136,7 @@
|
||||
|
||||
<div class="form-group m-t-md" ng-show="plan.type == 'PartnerPlan' && method != 'PATCH'">
|
||||
<input type="hidden" ng-model="plan.partnerId" name="plan[partner_id]" ng-value="plan.partnerId" />
|
||||
<label for="plan[partner_id]">{{ 'plan_form.notified_partner' | translate }} *</label>
|
||||
<label for="plan[partner_id]">{{ 'app.shared.plan.notified_partner' | translate }} *</label>
|
||||
<div class="input-group">
|
||||
<select class="form-control"
|
||||
ng-model="plan.partnerId"
|
||||
@ -145,10 +145,10 @@
|
||||
<option value=""></option>
|
||||
</select>
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" type="button" ng-click="openPartnerNewModal()"><i class="fa fa-user-plus"></i> {{ 'plan_form.new_user' | translate }}</button>
|
||||
<button class="btn btn-default" type="button" ng-click="openPartnerNewModal()"><i class="fa fa-user-plus"></i> {{ 'app.shared.plan.new_user' | translate }}</button>
|
||||
</span>
|
||||
</div>
|
||||
<span class="help-block" translate>{{ 'plan_form.as_part_of_a_partner_subscription_some_notifications_may_be_sent_to_this_user' }}</span>
|
||||
<span class="help-block" translate>{{ 'app.shared.plan.as_part_of_a_partner_subscription_some_notifications_may_be_sent_to_this_user' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-show="plan.partners">
|
||||
|
@ -7,13 +7,13 @@
|
||||
</div>
|
||||
<div class="col-xs-10 col-sm-10 col-md-8 b-l">
|
||||
<section class="heading-title">
|
||||
<h1>{{ 'edit_plan.subscription_plan' | translate }} {{ plan.base_name }}</h1>
|
||||
<h1>{{ 'app.admin.plans.edit.subscription_plan' | translate }} {{ plan.base_name }}</h1>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<section class="heading-actions wrapper">
|
||||
<a class="btn btn-lg btn-block btn-default m-t-xs" ui-sref="app.admin.pricing" translate>{{ 'cancel' }}</a>
|
||||
<a class="btn btn-lg btn-block btn-default m-t-xs" ui-sref="app.admin.pricing" translate>{{ 'app.shared.buttons.cancel' }}</a>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
@ -28,37 +28,37 @@
|
||||
<div id="planForm">
|
||||
<form name="planForm" novalidate="novalidate" class="col-lg-7 col-lg-offset-2 m-t-lg form-group" action="{{ actionUrl }}" ng-upload="afterSubmit(content)" upload-options-enable-rails-csrf="true">
|
||||
|
||||
<ng-include src="'<%= asset_path 'admin/plans/_form.html' %>'"></ng-include>
|
||||
<ng-include src="'<%= asset_path "admin/plans/_form.html" %>'"></ng-include>
|
||||
|
||||
<div class="input-group m-t-md">
|
||||
<label for="plan[disabled]" class="control-label m-r-md">{{ 'plan_form.disabled' | translate }}</label>
|
||||
<label for="plan[disabled]" class="control-label m-r-md">{{ 'app.shared.plans.disabled' | translate }}</label>
|
||||
<input bs-switch
|
||||
ng-model="plan.disabled"
|
||||
id="plan[disabled]"
|
||||
type="checkbox"
|
||||
class="form-control"
|
||||
switch-on-text="{{ 'yes' | translate }}"
|
||||
switch-off-text="{{ 'no' | translate }}"
|
||||
switch-on-text="{{ 'app.shared.buttons.yes' | translate }}"
|
||||
switch-off-text="{{ 'app.shared.buttons.no' | translate }}"
|
||||
switch-animate="true"
|
||||
ng-true-value="'true'"
|
||||
ng-false-value="'false'"/>
|
||||
<input type="hidden" name="plan[disabled]" value="{{plan.disabled}}"/>
|
||||
<span class="help-block" translate>{{ 'plan_form.disable_plan_will_not_unsubscribe_users' }}</span>
|
||||
<span class="help-block" translate>{{ 'app.shared.plans.disable_plan_will_not_unsubscribe_users' }}</span>
|
||||
</div>
|
||||
|
||||
<h2 class="m-t-xl" translate>{{ 'edit_plan.prices' }}</h2>
|
||||
<h2 class="m-t-xl" translate>{{ 'app.admin.plans.edit.prices' }}</h2>
|
||||
<div class="form-group col-md-6 col-lg-offset-6">
|
||||
<input type="hidden" ng-model="plan.parent" name="plan[parent_id]" ng-value="plan.parent"/>
|
||||
<label for="parentPlan" translate>{{ 'edit_plan.copy_prices_from' }}</label>
|
||||
<label for="parentPlan" translate>{{ 'app.admin.plans.edit.copy_prices_from' }}</label>
|
||||
<select id="parentPlan" ng-options="plan.id as humanReadablePlanName(plan, groups) for plan in plans" ng-model="plan.parent" ng-change="copyPricesFromPlan()" class="form-control">
|
||||
<option value=""></option>
|
||||
</select>
|
||||
</div>
|
||||
<h3 translate>{{ 'edit_plan.machines' }}</h3>
|
||||
<h3 translate>{{ 'app.admin.plans.edit.machines' }}</h3>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<th translate>{{ 'edit_plan.machine' }}</th>
|
||||
<th translate>{{ 'edit_plan.hourly_rate' }}</th>
|
||||
<th translate>{{ 'app.admin.plans.edit.machine' }}</th>
|
||||
<th translate>{{ 'app.admin.plans.edit.hourly_rate' }}</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
@ -75,11 +75,11 @@
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h3 ng-hide="fablabWithoutSpaces" translate>{{ 'edit_plan.spaces' }}</h3>
|
||||
<h3 ng-hide="fablabWithoutSpaces" translate>{{ 'app.admin.plans.edit.spaces' }}</h3>
|
||||
<table class="table" ng-hide="fablabWithoutSpaces">
|
||||
<thead>
|
||||
<th translate>{{ 'edit_plan.space' }}</th>
|
||||
<th translate>{{ 'edit_plan.hourly_rate' }}</th>
|
||||
<th translate>{{ 'app.admin.plans.edit.space' }}</th>
|
||||
<th translate>{{ 'app.admin.plans.edit.hourly_rate' }}</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
@ -97,7 +97,7 @@
|
||||
</table>
|
||||
|
||||
<div class="panel-footer no-padder">
|
||||
<input type="submit" value="{{ 'confirm_changes' | translate }}" class="r-b btn-valid btn btn-warning btn-block p-lg btn-lg text-u-c" ng-disabled="planForm.$invalid"/>
|
||||
<input type="submit" value="{{ 'app.shared.buttons.confirm_changes' | translate }}" class="r-b btn-valid btn btn-warning btn-block p-lg btn-lg text-u-c" ng-disabled="planForm.$invalid"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -7,7 +7,7 @@
|
||||
</div>
|
||||
<div class="col-xs-10 col-sm-10 col-md-8 b-l">
|
||||
<section class="heading-title">
|
||||
<h1 translate>{{ 'new_plan.add_a_subscription_plan' }}</h1>
|
||||
<h1 translate>{{ 'app.admin.plans.new.add_a_subscription_plan' }}</h1>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@ -20,10 +20,10 @@
|
||||
<div id="planForm">
|
||||
<form name="planForm" novalidate="novalidate" class="col-lg-10 col-lg-offset-2 m-t-lg form-group" action="{{ actionUrl }}" ng-upload="afterSubmit(content)" upload-options-enable-rails-csrf="true">
|
||||
|
||||
<ng-include src="'<%= asset_path 'admin/plans/_form.html' %>'"></ng-include>
|
||||
<ng-include src="'<%= asset_path "admin/plans/_form.html" %>'"></ng-include>
|
||||
|
||||
<div class="panel-footer no-padder">
|
||||
<input type="submit" value="{{ 'save' | translate }}" class="r-b btn-valid btn btn-warning btn-block p-lg btn-lg text-u-c" ng-disabled="planForm.$invalid || !partnerIsValid()"/>
|
||||
<input type="submit" value="{{ 'app.shared.buttons.save' | translate }}" class="r-b btn-valid btn btn-warning btn-block p-lg btn-lg text-u-c" ng-disabled="planForm.$invalid || !partnerIsValid()"/>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
@ -1,15 +1,15 @@
|
||||
<h2 translate>{{ 'pricing.list_of_the_coupons' }}</h2>
|
||||
<h2 translate>{{ 'app.admin.pricing.list_of_the_coupons' }}</h2>
|
||||
|
||||
<div class="m-t-lg m-b">
|
||||
<button type="button" class="btn btn-warning" ui-sref="app.admin.coupons_new">
|
||||
<i class="fa fa-plus m-r"></i>
|
||||
<span translate>{{ 'pricing.add_a_new_coupon' }}</span>
|
||||
<span translate>{{ 'app.admin.pricing.add_a_new_coupon' }}</span>
|
||||
</button>
|
||||
<div class="form-group pull-right">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="fa fa-filter"></i></span>
|
||||
<select ng-model="filter.coupon" class="form-control" ng-change="updateCouponFilter()">
|
||||
<option ng-repeat="status in couponStatus" value="{{status}}" translate>{{ 'pricing.'+status }}</option>
|
||||
<option ng-repeat="status in couponStatus" value="{{status}}" translate>{{ 'app.admin.pricing.'+status }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@ -18,10 +18,10 @@
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th translate>{{ 'pricing.name' }}</th>
|
||||
<th translate>{{ 'pricing.discount' }}</th>
|
||||
<th translate>{{ 'pricing.nb_of_usages' }}</th>
|
||||
<th translate>{{ 'pricing.status' }}</th>
|
||||
<th translate>{{ 'app.admin.pricing.name' }}</th>
|
||||
<th translate>{{ 'app.admin.pricing.discount' }}</th>
|
||||
<th translate>{{ 'app.admin.pricing.nb_of_usages' }}</th>
|
||||
<th translate>{{ 'app.admin.pricing.status' }}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -33,7 +33,7 @@
|
||||
<span ng-show="coupon.type == 'amount_off'">{{coupon.amount_off}} {{currencySymbol}}</span>
|
||||
</td>
|
||||
<td>{{coupon.usages}}</td>
|
||||
<td translate>{{'pricing.'+coupon.status}}</td>
|
||||
<td translate>{{'app.admin.pricing.'+coupon.status}}</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-default" ng-click="sendCouponToUser(coupon)"><i class="fa fa-send-o"></i> </button>
|
||||
<button type="button" class="btn btn-default" ui-sref="app.admin.coupons_edit({id:coupon.id})"><i class="fa fa-pencil-square-o"></i></button>
|
||||
@ -44,5 +44,5 @@
|
||||
</table>
|
||||
|
||||
<div class="text-center">
|
||||
<button class="btn btn-warning" ng-click="loadMore()" ng-hide="coupons.length === 0 || coupons.length >= coupons[0].total"><i class="fa fa-search-plus" aria-hidden="true"></i> {{ 'pricing.display_more_coupons' | translate }}</button>
|
||||
<button class="btn btn-warning" ng-click="loadMore()" ng-hide="coupons.length === 0 || coupons.length >= coupons[0].total"><i class="fa fa-search-plus" aria-hidden="true"></i> {{ 'app.admin.pricing.display_more_coupons' | translate }}</button>
|
||||
</div>
|
||||
|
@ -1,10 +1,10 @@
|
||||
<h2 class="m-t-lg" translate>{{ 'pricing.trainings' }}</h2>
|
||||
<h2 class="m-t-lg" translate>{{ 'app.admin.pricing.trainings' }}</h2>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:20%" translate>{{ 'pricing.subscription' }}</th>
|
||||
<th style="width:10%" translate>{{ 'pricing.credits' }}</th>
|
||||
<th style="width:50%" translate>{{ 'pricing.related_trainings' }}</th>
|
||||
<th style="width:20%" translate>{{ 'app.admin.pricing.subscription' }}</th>
|
||||
<th style="width:10%" translate>{{ 'app.admin.pricing.credits' }}</th>
|
||||
<th style="width:50%" translate>{{ 'app.admin.pricing.related_trainings' }}</th>
|
||||
<th style="width:20%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -35,7 +35,7 @@
|
||||
</form>
|
||||
<div class="buttons" ng-show="!rowform.$visible">
|
||||
<button class="btn btn-default" ng-click="rowform.$show()">
|
||||
<i class="fa fa-edit"></i> {{ 'edit' | translate }}
|
||||
<i class="fa fa-edit"></i> {{ 'app.shared.buttons.edit' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
@ -43,17 +43,17 @@
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2 class="m-t-lg" translate>{{ 'pricing.machines' }}</h2>
|
||||
<h2 class="m-t-lg" translate>{{ 'app.admin.pricing.machines' }}</h2>
|
||||
<div class="btn-group m-t-md m-b-md">
|
||||
<button type="button" class="btn btn-warning" ng-click="addMachineCredit($event)" translate>{{ 'pricing.add_a_machine_credit' }}</button>
|
||||
<button type="button" class="btn btn-warning" ng-click="addMachineCredit($event)" translate>{{ 'app.admin.pricing.add_a_machine_credit' }}</button>
|
||||
</div>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:20%" translate>{{ 'pricing.machine' }}</th>
|
||||
<th style="width:10%" translate>{{ 'pricing.hours' }}</th>
|
||||
<th style="width:50%" translate>{{ 'pricing.related_subscriptions' }}</th>
|
||||
<th style="width:20%" translate>{{ 'app.admin.pricing.machine' }}</th>
|
||||
<th style="width:10%">{{ 'app.admin.pricing.hours' | translate:{DURATION:slotDuration} }}</th>
|
||||
<th style="width:50%" translate>{{ 'app.admin.pricing.related_subscriptions' }}</th>
|
||||
<th style="width:20%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -85,10 +85,10 @@
|
||||
</form>
|
||||
<div class="buttons" ng-show="!rowform.$visible">
|
||||
<button class="btn btn-default" ng-click="rowform.$show()">
|
||||
<i class="fa fa-edit"></i> {{ 'edit' | translate }}
|
||||
<i class="fa fa-edit"></i> {{ 'app.shared.buttons.edit' | translate }}
|
||||
</button>
|
||||
<button class="btn btn-danger" ng-click="removeMachineCredit($index)">
|
||||
<i class="fa fa-trash-o"></i> {{ 'delete' | translate }} (!)
|
||||
<i class="fa fa-trash-o"></i> {{ 'app.shared.buttons.delete' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
@ -96,16 +96,16 @@
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2 ng-hide="fablabWithoutSpaces" class="m-t-lg" translate>{{ 'pricing.spaces' }}</h2>
|
||||
<h2 ng-hide="fablabWithoutSpaces" class="m-t-lg" translate>{{ 'app.admin.pricing.spaces' }}</h2>
|
||||
<div ng-hide="fablabWithoutSpaces" class="btn-group m-t-md m-b-md">
|
||||
<button type="button" class="btn btn-warning" ng-click="addSpaceCredit($event)" translate>{{ '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>
|
||||
<table ng-hide="fablabWithoutSpaces" class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:20%" translate>{{ 'pricing.space' }}</th>
|
||||
<th style="width:10%" translate>{{ 'pricing.hours' }}</th>
|
||||
<th style="width:50%" translate>{{ 'pricing.related_subscriptions' }}</th>
|
||||
<th style="width:20%" translate>{{ 'app.admin.pricing.space' }}</th>
|
||||
<th style="width:10%">{{ 'app.admin.pricing.hours' | translate:{DURATION:slotDuration} }}</th>
|
||||
<th style="width:50%" translate>{{ 'app.admin.pricing.related_subscriptions' }}</th>
|
||||
<th style="width:20%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -137,10 +137,10 @@
|
||||
</form>
|
||||
<div class="buttons" ng-show="!rowform.$visible">
|
||||
<button class="btn btn-default" ng-click="rowform.$show()">
|
||||
<i class="fa fa-edit"></i> {{ 'edit' | translate }}
|
||||
<i class="fa fa-edit"></i> {{ 'app.shared.buttons.edit' | translate }}
|
||||
</button>
|
||||
<button class="btn btn-danger" ng-click="removeSpaceCredit($index)">
|
||||
<i class="fa fa-trash-o"></i> {{ 'delete' | translate }} (!)
|
||||
<i class="fa fa-trash-o"></i> {{ 'app.shared.buttons.delete' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
|
@ -7,7 +7,7 @@
|
||||
</div>
|
||||
<div class="col-xs-10 col-sm-10 col-md-8 b-l">
|
||||
<section class="heading-title">
|
||||
<h1 translate>{{ 'pricing.pricing_management' }}</h1>
|
||||
<h1 translate>{{ 'app.admin.pricing.pricing_management' }}</h1>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@ -21,28 +21,28 @@
|
||||
<div class="col-md-12">
|
||||
<uib-tabset justified="true">
|
||||
|
||||
<uib-tab heading="{{ 'pricing.subscriptions' | translate }}">
|
||||
<ng-include src="'<%= asset_path 'admin/pricing/subscriptions.html' %>'"></ng-include>
|
||||
<uib-tab heading="{{ 'app.admin.pricing.subscriptions' | translate }}">
|
||||
<ng-include src="'<%= asset_path "admin/pricing/subscriptions.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'pricing.trainings' | translate }}">
|
||||
<ng-include src="'<%= asset_path 'admin/pricing/trainings.html' %>'"></ng-include>
|
||||
<uib-tab heading="{{ 'app.admin.pricing.trainings' | translate }}">
|
||||
<ng-include src="'<%= asset_path "admin/pricing/trainings.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'pricing.machine_hours' | translate }}">
|
||||
<ng-include src="'<%= asset_path 'admin/pricing/machine_hours.html' %>'"></ng-include>
|
||||
<uib-tab heading="{{ 'app.admin.pricing.machine_hours' | translate }}">
|
||||
<ng-include src="'<%= asset_path "admin/pricing/machine_hours.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'pricing.spaces' | translate }}" ng-hide="fablabWithoutSpaces">
|
||||
<ng-include src="'<%= asset_path 'admin/pricing/spaces.html' %>'"></ng-include>
|
||||
<uib-tab heading="{{ 'app.admin.pricing.spaces' | translate }}" ng-hide="fablabWithoutSpaces">
|
||||
<ng-include src="'<%= asset_path "admin/pricing/spaces.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'pricing.credits' | translate }}">
|
||||
<ng-include src="'<%= asset_path 'admin/pricing/credits.html' %>'"></ng-include>
|
||||
<uib-tab heading="{{ 'app.admin.pricing.credits' | translate }}">
|
||||
<ng-include src="'<%= asset_path "admin/pricing/credits.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab heading="{{ 'pricing.coupons' | translate }}">
|
||||
<ng-include src="'<%= asset_path 'admin/pricing/coupons.html' %>'"></ng-include>
|
||||
<uib-tab heading="{{ 'app.admin.pricing.coupons' | translate }}">
|
||||
<ng-include src="'<%= asset_path "admin/pricing/coupons.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
</uib-tabset>
|
||||
</div>
|
||||
|
@ -1,10 +1,10 @@
|
||||
<div class="alert alert-warning m-t">
|
||||
{{ 'pricing.these_prices_match_machine_hours_rates_' | translate }} <span class="font-bold" translate>{{ 'pricing._without_subscriptions' }}</span>.
|
||||
{{ 'app.admin.pricing.these_prices_match_machine_hours_rates_' | translate:{DURATION:slotDuration} }} <span class="font-bold" translate>{{ 'app.admin.pricing._without_subscriptions' }}</span>.
|
||||
</div>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:20%" translate>{{ 'pricing.machines' }}</th>
|
||||
<th style="width:20%" translate>{{ 'app.admin.pricing.machines' }}</th>
|
||||
<th style="width:20%" ng-repeat="group in enabledGroups">
|
||||
<span class="text-u-c text-sm">{{group.name}}</span>
|
||||
</th>
|
||||
|
@ -1,11 +1,11 @@
|
||||
<div class="modal-header">
|
||||
<h3 class="text-center red" translate>{{ 'pricing.send_a_coupon' }}</h3>
|
||||
<h3 class="text-center red" translate>{{ 'app.admin.pricing.send_a_coupon' }}</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<select-member></select-member>
|
||||
<div class="widget panel b-a m">
|
||||
<div class="panel-heading b-b small">
|
||||
<h3 class="panel-title" translate>{{ 'pricing.coupon' }}</h3>
|
||||
<h3 class="panel-title" translate>{{ 'app.admin.pricing.coupon' }}</h3>
|
||||
</div>
|
||||
<div class="widget-content no-bg auto wrapper">
|
||||
<table>
|
||||
@ -13,18 +13,18 @@
|
||||
<tr><th style="width:60%"></th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td translate>{{'pricing.code'}}</td> <td>{{coupon.code}}</td></tr>
|
||||
<tr><td translate>{{'pricing.discount'}}</td> <td><span ng-show="coupon.type == 'percent_off'">{{coupon.percent_off}} %</span><span ng-show="coupon.type == 'amount_off'">{{coupon.amount_off}} {{currencySymbol}}</span></td></tr>
|
||||
<tr><td translate>{{'pricing.validity_per_user'}}</td> <td translate>{{'pricing.'+coupon.validity_per_user}}</td></tr>
|
||||
<tr><td translate>{{'pricing.valid_until'}}</td> <td>{{coupon.valid_until | amDateFormat:'L'}}</td></tr>
|
||||
<tr><td translate>{{'pricing.usages'}}</td> <td>{{coupon.usages}} / {{coupon.max_usages | maxCount}}</td></tr>
|
||||
<tr><td translate>{{'pricing.enabled'}}</td> <td>{{coupon.active | booleanFormat}}</td></tr>
|
||||
<tr><td translate>{{'app.admin.pricing.code'}}</td> <td>{{coupon.code}}</td></tr>
|
||||
<tr><td translate>{{'app.admin.pricing.discount'}}</td> <td><span ng-show="coupon.type == 'percent_off'">{{coupon.percent_off}} %</span><span ng-show="coupon.type == 'amount_off'">{{coupon.amount_off}} {{currencySymbol}}</span></td></tr>
|
||||
<tr><td translate>{{'app.admin.pricing.validity_per_user'}}</td> <td translate>{{'app.admin.pricing.'+coupon.validity_per_user}}</td></tr>
|
||||
<tr><td translate>{{'app.admin.pricing.valid_until'}}</td> <td>{{coupon.valid_until | amDateFormat:'L'}}</td></tr>
|
||||
<tr><td translate>{{'app.admin.pricing.usages'}}</td> <td>{{coupon.usages}} / {{coupon.max_usages | maxCount}}</td></tr>
|
||||
<tr><td translate>{{'app.admin.pricing.enabled'}}</td> <td>{{coupon.active | booleanFormat}}</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-warning" ng-click="ok()" ng-disabled="ctrl.member == null" translate>{{ 'confirm' }}</button>
|
||||
<button class="btn btn-default" ng-click="cancel()" translate>{{ 'cancel' }}</button>
|
||||
<button class="btn btn-warning" ng-click="ok()" ng-disabled="ctrl.member == null" translate>{{ 'app.shared.buttons.confirm' }}</button>
|
||||
<button class="btn btn-default" ng-click="cancel()" translate>{{ 'app.shared.buttons.cancel' }}</button>
|
||||
</div>
|
@ -1,10 +1,10 @@
|
||||
<div class="alert alert-warning m-t">
|
||||
{{ 'pricing.these_prices_match_space_hours_rates_' | translate }} <span class="font-bold" translate>{{ 'pricing._without_subscriptions' }}</span>.
|
||||
{{ 'app.admin.pricing.these_prices_match_space_hours_rates_' | translate:{DURATION:slotDuration} }} <span class="font-bold" translate>{{ 'app.admin.pricing._without_subscriptions' }}</span>.
|
||||
</div>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:20%" translate>{{ 'pricing.spaces' }}</th>
|
||||
<th style="width:20%" translate>{{ 'app.admin.pricing.spaces' }}</th>
|
||||
<th style="width:20%" ng-repeat="group in enabledGroups">
|
||||
<span class="text-u-c text-sm">{{group.name}}</span>
|
||||
</th>
|
||||
|
@ -1,21 +1,21 @@
|
||||
<h2 translate>{{ '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">
|
||||
{{ 'pricing.beware_the_subscriptions_are_disabled_on_this_application' | translate }}
|
||||
{{ 'pricing.you_can_create_some_but_they_wont_be_available_until_the_project_is_redeployed_by_the_server_manager' | translate }}
|
||||
<br>{{ 'pricing.for_safety_reasons_please_dont_create_subscriptions_if_you_dont_want_intend_to_use_them_later' | translate }}
|
||||
{{ 'app.admin.pricing.beware_the_subscriptions_are_disabled_on_this_application' | translate }}
|
||||
{{ 'app.admin.pricing.you_can_create_some_but_they_wont_be_available_until_the_project_is_redeployed_by_the_server_manager' | translate }}
|
||||
<br>{{ 'app.admin.pricing.for_safety_reasons_please_dont_create_subscriptions_if_you_dont_want_intend_to_use_them_later' | translate }}
|
||||
</div>
|
||||
|
||||
<div class="m-t-lg">
|
||||
<button type="button" class="btn btn-warning" ui-sref="app.admin.plans.new">
|
||||
<i class="fa fa-plus m-r"></i>
|
||||
<span translate>{{ 'pricing.add_a_new_subscription_plan' }}</span>
|
||||
<span translate>{{ 'app.admin.pricing.add_a_new_subscription_plan' }}</span>
|
||||
</button>
|
||||
<div class="form-group pull-right">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="fa fa-filter"></i></span>
|
||||
<select ng-model="planFiltering" class="form-control">
|
||||
<option ng-repeat="status in filterDisabled" value="{{status}}" translate>{{ 'pricing.status_'+status }}</option>
|
||||
<option ng-repeat="status in filterDisabled" value="{{status}}" translate>{{ 'app.admin.pricing.status_'+status }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@ -24,12 +24,12 @@
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><a href="" ng-click="setOrderPlans('type')">{{ 'pricing.type' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': orderPlans=='type', 'fa fa-sort-alpha-desc': orderPlans=='-type', 'fa fa-arrows-v': orderPlans }"></i></a></th>
|
||||
<th><a href="" ng-click="setOrderPlans('name')">{{ 'pricing.name' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': orderPlans=='name', 'fa fa-sort-alpha-desc': orderPlans=='-name', 'fa fa-arrows-v': orderPlans }"></i></a></th>
|
||||
<th><a href="" ng-click="setOrderPlans('interval')">{{ 'pricing.duration' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-amount-asc': orderPlans=='interval', 'fa fa-sort-amount-desc': orderPlans=='-interval', 'fa fa-arrows-v': orderPlans }"></i></a></th>
|
||||
<th><a href="" ng-click="setOrderPlans('group_id')">{{ 'pricing.group' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': orderPlans=='group_id', 'fa fa-sort-alpha-desc': orderPlans=='-group_id', 'fa fa-arrows-v': orderPlans }"></i></a></th>
|
||||
<th class="hidden-xs"><a href="" ng-click="setOrderPlans('pricing.ui_weight')">{{ 'pricing.prominence' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-numeric-asc': orderPlans=='ui_weight', 'fa fa-sort-numeric-desc': orderPlans=='-ui_weight', 'fa fa-arrows-v': orderPlans }"></i></a></th>
|
||||
<th><a href="" ng-click="setOrderPlans('amount')">{{ 'pricing.price' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-numeric-asc': orderPlans=='amount', 'fa fa-sort-numeric-desc': orderPlans=='-amount', 'fa fa-arrows-v': orderPlans }"></i></a></th>
|
||||
<th><a href="" ng-click="setOrderPlans('type')">{{ 'app.admin.pricing.type' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': orderPlans=='type', 'fa fa-sort-alpha-desc': orderPlans=='-type', 'fa fa-arrows-v': orderPlans }"></i></a></th>
|
||||
<th><a href="" ng-click="setOrderPlans('name')">{{ 'app.admin.pricing.name' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': orderPlans=='name', 'fa fa-sort-alpha-desc': orderPlans=='-name', 'fa fa-arrows-v': orderPlans }"></i></a></th>
|
||||
<th><a href="" ng-click="setOrderPlans('interval')">{{ 'app.admin.pricing.duration' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-amount-asc': orderPlans=='interval', 'fa fa-sort-amount-desc': orderPlans=='-interval', 'fa fa-arrows-v': orderPlans }"></i></a></th>
|
||||
<th><a href="" ng-click="setOrderPlans('group_id')">{{ 'app.admin.pricing.group' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': orderPlans=='group_id', 'fa fa-sort-alpha-desc': orderPlans=='-group_id', 'fa fa-arrows-v': orderPlans }"></i></a></th>
|
||||
<th class="hidden-xs"><a href="" ng-click="setOrderPlans('app.admin.pricing.ui_weight')">{{ 'app.admin.pricing.prominence' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-numeric-asc': orderPlans=='ui_weight', 'fa fa-sort-numeric-desc': orderPlans=='-ui_weight', 'fa fa-arrows-v': orderPlans }"></i></a></th>
|
||||
<th><a href="" ng-click="setOrderPlans('amount')">{{ 'app.admin.pricing.price' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-numeric-asc': orderPlans=='amount', 'fa fa-sort-numeric-desc': orderPlans=='-amount', 'fa fa-arrows-v': orderPlans }"></i></a></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:20%" translate>{{ 'pricing.trainings' }}</th>
|
||||
<th style="width:20%" translate>{{ 'app.admin.pricing.trainings' }}</th>
|
||||
<th style="width:20%" ng-repeat="group in enabledGroups">
|
||||
<span class="text-u-c text-sm">{{group.name}}</span>
|
||||
</th>
|
||||
|
@ -7,12 +7,12 @@
|
||||
</div>
|
||||
<div class="col-xs-10 col-sm-10 col-md-8 b-l">
|
||||
<section class="heading-title">
|
||||
<h1 translate>{{ 'project_elements.projects_elements_management' }}</h1>
|
||||
<h1 translate>{{ 'app.admin.project_elements.projects_elements_management' }}</h1>
|
||||
</section>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-12 col-md-3 b-t hide-b-md">
|
||||
<section class="heading-actions wrapper">
|
||||
<a class="btn btn-ng btn-warning b-2x rounded m-t-sm upper text-sm" ui-sref="app.admin.manage_abuses" role="button" translate>{{ 'project_elements.manage_abuses' }}</a>
|
||||
<a class="btn btn-ng btn-warning b-2x rounded m-t-sm upper text-sm" ui-sref="app.admin.manage_abuses" role="button" translate>{{ 'app.admin.project_elements.manage_abuses' }}</a>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
@ -24,14 +24,14 @@
|
||||
|
||||
<div class="col-md-12">
|
||||
<uib-tabset justified="true">
|
||||
<uib-tab heading="{{ 'materials' | translate }}">
|
||||
<ng-include src="'<%= asset_path 'admin/project_elements/materials.html' %>'"></ng-include>
|
||||
<uib-tab heading="{{ 'app.admin.project_elements.materials' | translate }}">
|
||||
<ng-include src="'<%= asset_path "admin/project_elements/materials.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
<uib-tab heading="{{ 'themes' | translate }}">
|
||||
<ng-include src="'<%= asset_path 'admin/project_elements/themes.html' %>'"></ng-include>
|
||||
<uib-tab heading="{{ 'app.admin.project_elements.themes' | translate }}">
|
||||
<ng-include src="'<%= asset_path "admin/project_elements/themes.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
<uib-tab heading="{{ 'project_elements.licences' | translate }}">
|
||||
<ng-include src="'<%= asset_path 'admin/project_elements/licences.html' %>'"></ng-include>
|
||||
<uib-tab heading="{{ 'app.admin.project_elements.licences' | translate }}">
|
||||
<ng-include src="'<%= asset_path "admin/project_elements/licences.html" %>'"></ng-include>
|
||||
</uib-tab>
|
||||
</uib-tabset>
|
||||
</div>
|
||||
|
@ -1,10 +1,10 @@
|
||||
<button type="button" class="btn btn-warning m-t m-b" ng-click="addLicence()" translate>{{ 'project_elements.add_a_new_licence' }}</button>
|
||||
<button type="button" class="btn btn-warning m-t m-b" ng-click="addLicence()" translate>{{ 'app.admin.project_elements.add_a_new_licence' }}</button>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:30%" translate>{{ 'name' }}</th>
|
||||
<th style="width:50%" class="hidden-xs" translate>{{ 'description' }}</th>
|
||||
<th style="width:30%" translate>{{ 'app.admin.project_elements.name' }}</th>
|
||||
<th style="width:50%" class="hidden-xs" translate>{{ 'app.admin.project_elements.description' }}</th>
|
||||
<th style="width:20%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -32,7 +32,7 @@
|
||||
</form>
|
||||
<div class="buttons" ng-show="!rowform.$visible">
|
||||
<button class="btn btn-default" ng-click="rowform.$show()">
|
||||
<i class="fa fa-edit"></i> <span class="hidden-xs hidden-sm" translate>{{ 'edit' }}</span>
|
||||
<i class="fa fa-edit"></i> <span class="hidden-xs hidden-sm" translate>{{ 'app.shared.buttons.edit' }}</span>
|
||||
</button>
|
||||
<button class="btn btn-danger" ng-click="removeLicence($index)">
|
||||
<i class="fa fa-trash-o"></i>
|
||||
|
@ -1,9 +1,9 @@
|
||||
<button type="button" class="btn btn-warning m-b m-t" ng-click="addComponent()" translate>{{ 'project_elements.add_a_material' }}</button>
|
||||
<button type="button" class="btn btn-warning m-b m-t" ng-click="addComponent()" translate>{{ 'app.admin.project_elements.add_a_material' }}</button>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:80%" translate>{{ 'name' }}</th>
|
||||
<th style="width:80%" translate>{{ 'app.admin.project_elements.name' }}</th>
|
||||
<th style="width:20%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -26,7 +26,7 @@
|
||||
</form>
|
||||
<div class="buttons" ng-show="!rowform.$visible">
|
||||
<button class="btn btn-default" ng-click="rowform.$show()">
|
||||
<i class="fa fa-edit"></i> <span class="hidden-xs hidden-sm" translate>{{ 'edit' }}</span>
|
||||
<i class="fa fa-edit"></i> <span class="hidden-xs hidden-sm" translate>{{ 'app.shared.buttons.edit' }}</span>
|
||||
</button>
|
||||
<button class="btn btn-danger" ng-click="removeComponent($index)">
|
||||
<i class="fa fa-trash-o"></i>
|
||||
|
@ -1,9 +1,9 @@
|
||||
<button type="button" class="btn btn-warning m-t m-b" ng-click="addTheme()" translate>{{ 'project_elements.add_a_new_theme' }}</button>
|
||||
<button type="button" class="btn btn-warning m-t m-b" ng-click="addTheme()" translate>{{ 'app.admin.project_elements.add_a_new_theme' }}</button>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:80%" translate>{{ 'name' }}</th>
|
||||
<th style="width:80%" translate>{{ 'app.admin.project_elements.name' }}</th>
|
||||
<th style="width:20%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -26,7 +26,7 @@
|
||||
</form>
|
||||
<div class="buttons" ng-show="!rowform.$visible">
|
||||
<button class="btn btn-default" ng-click="rowform.$show()">
|
||||
<i class="fa fa-edit"></i> <span class="hidden-xs hidden-sm" translate>{{ 'edit' }}</span>
|
||||
<i class="fa fa-edit"></i> <span class="hidden-xs hidden-sm" translate>{{ 'app.shared.buttons.edit' }}</span>
|
||||
</button>
|
||||
<button class="btn btn-danger" ng-click="removeTheme($index)">
|
||||
<i class="fa fa-trash-o"></i>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user