Merge branch 'PHRAS-3078-Prod_redirect_end_session' of https://github.com/alchemy-fr/Phraseanet into PHRAS-3078-Prod_redirect_end_session
20
.env
@@ -2,7 +2,7 @@ PHRASEANET_PROJECT_NAME=Phraseanet
|
|||||||
# Registry from where you pull Docker images
|
# Registry from where you pull Docker images
|
||||||
PHRASEANET_DOCKER_REGISTRY=local
|
PHRASEANET_DOCKER_REGISTRY=local
|
||||||
# Tag of the Docker images
|
# Tag of the Docker images
|
||||||
PHRASEANET_DOCKER_TAG=latest
|
PHRASEANET_DOCKER_TAG=4.1.1
|
||||||
# APPLICATION PORT
|
# APPLICATION PORT
|
||||||
PHRASEANET_APP_PORT=8082
|
PHRASEANET_APP_PORT=8082
|
||||||
# RabbitMQ configuration
|
# RabbitMQ configuration
|
||||||
@@ -13,6 +13,8 @@ RABBITMQ_MANAGEMENT_PORT=10811
|
|||||||
MYSQL_ROOT_PASSWORD=root
|
MYSQL_ROOT_PASSWORD=root
|
||||||
SERVER_NAME=phraseanet-docker
|
SERVER_NAME=phraseanet-docker
|
||||||
|
|
||||||
|
# --------------- GATEWAY TIMEOUT -----------------------
|
||||||
|
GATEWAY_SEND_TIMEOUT=120
|
||||||
|
|
||||||
# --------------- PHP CONFIGURATION --------------------
|
# --------------- PHP CONFIGURATION --------------------
|
||||||
|
|
||||||
@@ -21,6 +23,9 @@ MAX_BODY_SIZE=2G
|
|||||||
# Max input var
|
# Max input var
|
||||||
MAX_INPUT_VARS=12000
|
MAX_INPUT_VARS=12000
|
||||||
|
|
||||||
|
MAX_EXECUTION_TIME=120
|
||||||
|
MAX_INPUT_TIME=60
|
||||||
|
|
||||||
# Enable opcache ? (0/1)
|
# Enable opcache ? (0/1)
|
||||||
OPCACHE_ENABLED=1
|
OPCACHE_ENABLED=1
|
||||||
# session cache limiter (off/on)
|
# session cache limiter (off/on)
|
||||||
@@ -34,6 +39,8 @@ PHP_LOG_LEVEL=warning
|
|||||||
# These variables are used in the configuration.yml .
|
# These variables are used in the configuration.yml .
|
||||||
|
|
||||||
# set here the first user / email couple
|
# set here the first user / email couple
|
||||||
|
#set to id of Phraseanet root account, if you want activate a sync for Phraseanet root account password provide by PHRASEANET_ADMIN_ACCOUNT_PASSWORD env value.
|
||||||
|
PHRASEANET_ADMIN_ACCOUNT_ID=
|
||||||
PHRASEANET_ADMIN_ACCOUNT_EMAIL=admin@alchemy.fr
|
PHRASEANET_ADMIN_ACCOUNT_EMAIL=admin@alchemy.fr
|
||||||
PHRASEANET_ADMIN_ACCOUNT_PASSWORD=iJRqXU0MwbyJewQLBbra6IWHsWly
|
PHRASEANET_ADMIN_ACCOUNT_PASSWORD=iJRqXU0MwbyJewQLBbra6IWHsWly
|
||||||
# Database parameters
|
# Database parameters
|
||||||
@@ -64,6 +71,16 @@ PHRASEANET_SMTP_SECURE_MODE=tls
|
|||||||
PHRASEANET_SMTP_USER=
|
PHRASEANET_SMTP_USER=
|
||||||
PHRASEANET_SMTP_PASSWORD=
|
PHRASEANET_SMTP_PASSWORD=
|
||||||
|
|
||||||
|
# Locale setting
|
||||||
|
|
||||||
|
LC_MESSAGES=C.UTF-8
|
||||||
|
LC_COLLATE=C.UTF-8
|
||||||
|
LC_IDENTIFICATION=C.UTF-8
|
||||||
|
LANG=C.UTF-8
|
||||||
|
LC_MEASUREMENT=C.UTF-8
|
||||||
|
LC_CTYPE=C.UTF-8
|
||||||
|
LC_TIME=C.UTF-8
|
||||||
|
LC_NAME=C.UTF-8
|
||||||
|
|
||||||
# --- DEV purpose ---
|
# --- DEV purpose ---
|
||||||
|
|
||||||
@@ -86,6 +103,7 @@ PHRASEANET_DB_DIR=./volumes/db
|
|||||||
PHRASEANET_ELASTICSEARCH_DIR=./volumes/elasticsearch
|
PHRASEANET_ELASTICSEARCH_DIR=./volumes/elasticsearch
|
||||||
PHRASEANET_THUMBNAILS_DIR=./www/thumbnails
|
PHRASEANET_THUMBNAILS_DIR=./www/thumbnails
|
||||||
PHRASEANET_CUSTOM_DIR=./www/custom
|
PHRASEANET_CUSTOM_DIR=./www/custom
|
||||||
|
PHRASEANET_PLUGINS_DIR=./www/plugins
|
||||||
PHRASEANET_TMP_DIR=./tmp
|
PHRASEANET_TMP_DIR=./tmp
|
||||||
PHRASEANET_CACHE_DIR=./cache
|
PHRASEANET_CACHE_DIR=./cache
|
||||||
PHRASEANET_DOWNLOAD_DIR=./datas/download
|
PHRASEANET_DOWNLOAD_DIR=./datas/download
|
||||||
|
160
CHANGELOG.md
@@ -1,5 +1,155 @@
|
|||||||
# CHANGELOG
|
# CHANGELOG
|
||||||
|
|
||||||
|
## 4.1.1
|
||||||
|
|
||||||
|
### Change summary
|
||||||
|
|
||||||
|
- Phraseanet now using Docker. Retrieve all official images on DockerHub
|
||||||
|
- Worker manager, a new way for all operations on assets. In the near future, this will replace the current task manager.
|
||||||
|
- Geolocation based on Mapbox (requires an account on Mapbox https://www.mapbox.com).
|
||||||
|
- Video chaptering and subtitling support.
|
||||||
|
- GUI redesign for Push, Feedback, List manager, Lightbox on mobile.
|
||||||
|
|
||||||
|
|
||||||
|
this version is finale version of 4.1.0 published in preview at start of year, a lot of improvement, bugfixes on several elements see summary here
|
||||||
|
|
||||||
|
### New Feature summary
|
||||||
|
|
||||||
|
* [PHRAS-2023] - Refacto Lightbox mobile in 4.1
|
||||||
|
* [PHRAS-2219] - Refacto design Push screen
|
||||||
|
* [PHRAS-2220] - Refacto design Feedback screen
|
||||||
|
* [PHRAS-2221] - Refacto design List manager general screen
|
||||||
|
* [PHRAS-2222] - Refacto design ListManager Advance Mode screen
|
||||||
|
* [PHRAS-2223] - Refacto dev list manager Advance Mode screen
|
||||||
|
* [PHRAS-2541] - Dev-Design-Prod/Publish Screen
|
||||||
|
* [PHRAS-2548] - Phraseanet Docker and Docker Compose
|
||||||
|
* [PHRAS-1226] - Geolocalisation In Phraseanet
|
||||||
|
* [PHRAS-1626] - bin/console databox:mount mount an existing databox
|
||||||
|
* [PHRAS-1628] - bin/console collection:publish
|
||||||
|
* [PHRAS-1630] - bin/console database:unmout
|
||||||
|
* [PHRAS-1631] - bin/console collection:unpublish
|
||||||
|
* [PHRAS-1648] - bin/console user:password
|
||||||
|
* [PHRAS-1659] - bin/console user:create
|
||||||
|
* [PHRAS-1771] - bin/console collection:unpublish
|
||||||
|
* [PHRAS-1773] - bin/console collection:publish
|
||||||
|
* [PHRAS-2518] - Phraseanet worker Read/Write metadata
|
||||||
|
* [PHRAS-2520] - Phraseanet worker send webhook
|
||||||
|
* [PHRAS-2738] - Phraseanet worker populate database
|
||||||
|
* [PHRAS-2435] - Phraseanet Worker Build subdefinition
|
||||||
|
* [PHRAS-2436] - Phraseanet Worker build zip export and send mail
|
||||||
|
* [PHRAS-2636] - Phraseanet Worker fetch assets from external uploader (pull mode)
|
||||||
|
* [PHRAS-2904] - Fullfill field define in geoloc - position field with information return by Geonames
|
||||||
|
* [PHRAS-161] - PROD Add a maps for geolocalisation of media in detailed view
|
||||||
|
* [PHRAS-1935] - View prod/ Video chapter editor
|
||||||
|
* [PHRAS-2997] - Matomo analytic service in Phraseanet
|
||||||
|
* [PHRAS-1890] - Add GS1 databases model to Phraseanet
|
||||||
|
|
||||||
|
|
||||||
|
### Improvement and fix summary
|
||||||
|
|
||||||
|
* [PHRAS-1561] - Prod | Print - Use the label of field when print, use the GUI user language
|
||||||
|
* [PHRAS-2067] - Prod : Introduce thumbnail & preview generic images for Fonts records
|
||||||
|
* [PHRAS-2473] - Populate Optimisation, sometime populate databox (database) is very long
|
||||||
|
* [PHRAS-2524] - Put worker log in ELK
|
||||||
|
* [PHRAS-2739] - incorporate Phraseanet-plugin-SubdefWebhook into Phraseanet
|
||||||
|
* [PHRAS-2157] - Prod / Share : Iframe sizes are set to 0 for audio documents
|
||||||
|
* [PHRAS-2538] - Some MP4 file is not correctly detected by Phraseanet.
|
||||||
|
* [PHRAS-2825] - Prod : Add a reset button to initialize searches filters
|
||||||
|
* [PHRAS-1872] - prod/export by email / subject are NOK
|
||||||
|
* [PHRAS-2342] - Report : collections not selected
|
||||||
|
* [PHRAS-2343] - report : all fields of all databases
|
||||||
|
* [PHRAS-2350] - Report : url is too long
|
||||||
|
* [PHRAS-2476] - Bad header in generated video preview file
|
||||||
|
* [PHRAS-2196] - API - Stories records pagination on search answer and Stories fetch info
|
||||||
|
* [PHRAS-2880] - extend admin GUI for define facets ordering.
|
||||||
|
* [PHRAS-2967] - Lightbox - dev of send email report - warn windows
|
||||||
|
* [PHRAS-1752] - update facebook sdk dependency
|
||||||
|
* [PHRAS-2678] - add `webhook monitor`
|
||||||
|
* [PHRAS-2915] - Lightbox (desktop version) Change sort order for basket and Feedback in landing page ( most recent in first)
|
||||||
|
* [PHRAS-2082] - Bump design of windows create user , create template user, create new subdef
|
||||||
|
* [PHRAS-2676] - Weaked download behaviour for large amount of data
|
||||||
|
* [PHRAS-2671] - Change behavior of preview display in audio file case
|
||||||
|
* [PHRAS-2879] - Define facets order in GUI and query result
|
||||||
|
|
||||||
|
## 4.0.12
|
||||||
|
|
||||||
|
Release notes - Phraseanet - Version 4.0.12
|
||||||
|
|
||||||
|
### Improvement
|
||||||
|
* [PHRAS-2955] - Cache doctrine entity metadata for performance
|
||||||
|
* [PHRAS-2964] - Application-box - set host colon of table sbas set to char 255
|
||||||
|
* [PHRAS-3012] - [PHRAS-2977] - Docker compose optimisation, refacto volumes, build image
|
||||||
|
optimisation, add Phraseanet plugin in build image, bump ffmpeg version in worker,
|
||||||
|
fix error un redis configuration.
|
||||||
|
more option for define volumes during installation process.
|
||||||
|
* [PHRAS-3027] - Backport To 4.0 - Populate - Slow query - due to LIMIT in sql query.
|
||||||
|
* [PHRAS-3027] - Translation improvement in EN and DE.
|
||||||
|
|
||||||
|
### Bugfix
|
||||||
|
* [PHRAS-2979] - The content of a story is not displayed even for users with appropriate on the collection
|
||||||
|
|
||||||
|
|
||||||
|
## 4.1.0
|
||||||
|
|
||||||
|
Pre release of 4.1
|
||||||
|
|
||||||
|
|
||||||
|
## 4.0.11
|
||||||
|
|
||||||
|
Release notes - Phraseanet - Version 4.0.11
|
||||||
|
|
||||||
|
### New Feature and Improvement
|
||||||
|
* [PHRAS-2878] - Print feedback report in PDF
|
||||||
|
* [PHRAS-2757] - Exclude some collections from quarantine checkers sha256, UUID, filename (AKA exclude Trash from quarantine)
|
||||||
|
* [PHRAS-2766] - Add status change capabilities to quarantine lazaret in substitute and add action
|
||||||
|
* [PHRAS-2674] - Prod grey skin Improvement
|
||||||
|
* [PHRAS-2775] - Prod - plugin - Publish item in diapo local menu - plugin skeleton improvement.
|
||||||
|
* [PHRAS-925] - Search Engine improvement for word with dot and hyphen characters
|
||||||
|
* [PHRAS-2496] - Pre-build vagrant image for Phraseanet and implement it in Phraseanet vagrant file.
|
||||||
|
* [PHRAS-2637] - Sub definition Task init : select all databases when databases property is not set
|
||||||
|
* [PHRAS-2670] - Fix notifications slow sql and basket select
|
||||||
|
* [PHRAS-2672] - Bump videojs version to 7.5
|
||||||
|
* [PHRAS-2691] - Prod - delete from trash , send deletion by bulk of 3 records
|
||||||
|
* [PHRAS-2700] - Prod - number of results - Formating the results number
|
||||||
|
* [PHRAS-2742] - Enhance plugin-skeleton in 4.0
|
||||||
|
* [PHRAS-2750] - PHPExiftool to handle DJI XMP Tags, Bump exiftool version and switch to original exiftool/exiftool github repository
|
||||||
|
* [PHRAS-835] - ES - date format timestamp unix, store and search datetime
|
||||||
|
* [PHRAS-2791] - Embed-bundle - Videojs player serve poster-image property with sub definition permalink
|
||||||
|
* [PHRAS-2842] - Databases Models - now default audio encodeur is mp3lame
|
||||||
|
* [PHRAS-2857] - Exclude some collections from quarantine checkers sha256, UUID, filename (AKA exclude Trash)
|
||||||
|
* [PHRAS-2899] - Quarantine: allow to substitute without selecting target record, (when match only one record).
|
||||||
|
* [PHRAS-2765] - Translation in Plugin menu locale is now available
|
||||||
|
* [PHRAS-2929] - bump sinonjs dependency to 1.7.1
|
||||||
|
* [PHRAS-2728] - Landing page take browser language in account
|
||||||
|
* [PHRAS-2693] - Collection Sort Sorter is now presented by column
|
||||||
|
* [PHRAS-2817] - Deploy and Dev with docker is OK
|
||||||
|
|
||||||
|
|
||||||
|
### Bugfix
|
||||||
|
* [PHRAS-1069] - Dates seems not extracted from iptc
|
||||||
|
* [PHRAS-1428] - Phraseanet Binaries in configuration not used in some alchemy-fr libraries (AKA text extraction of pdf is NOK)
|
||||||
|
* [PHRAS-2567] - Registration Form - Term of use link is broken
|
||||||
|
* [PHRAS-2644] - Searching for stories after applying a document filtering choice gives no results
|
||||||
|
* [PHRAS-2652] - Fields "Phraseanet::no-source" are pushed to exiftool
|
||||||
|
* [PHRAS-2682] - Prod - facets display is NOK when switch from basket or thesaurus Tab.
|
||||||
|
* [PHRAS-2695] - Prod - Grey and White Skins - Browse Baskets: Unable to read the titles
|
||||||
|
* [PHRAS-2702] - Lightbox - scroller thumbnail Nok
|
||||||
|
* [PHRAS-2714] - Adding record from the API leaves a copy of the file into the system temporary directory
|
||||||
|
* [PHRAS-2715] - Embed bundle, border issue on firefox.
|
||||||
|
* [PHRAS-2716] - Records SetStatus HTTP API malfunction
|
||||||
|
* [PHRAS-2723] - None information (name, last name etc...) is keep from the Push or a FeedBack user creation form
|
||||||
|
* [PHRAS-2748] - Some characters into cterms (candidats) leeds to 500 error
|
||||||
|
* [PHRAS-2754] - Permalink is not (re) activated when record is move from _TRASH_ collection
|
||||||
|
* [PHRAS-2860] - Generated Subdefs for video Portait are not correctly Oriented
|
||||||
|
* [PHRAS-2877] - User manipulator does not allow to set a null email
|
||||||
|
* [PHRAS-2912] - When updating a user informations the wrong field are populated (job and activity inverted)
|
||||||
|
* [PHRAS-2811] - Cleanning of bad chars in candidats terms
|
||||||
|
|
||||||
|
|
||||||
|
## 4.0.10
|
||||||
|
|
||||||
|
Not publish
|
||||||
|
|
||||||
## 4.0.9
|
## 4.0.9
|
||||||
|
|
||||||
### Adds
|
### Adds
|
||||||
@@ -13,11 +163,11 @@
|
|||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
|
|
||||||
* PHRAS-2491 - Front - Click on facets title (expand/collapse) launched a bad query, due to jquery error.
|
- PHRAS-2491 - Front - Click on facets title (expand/collapse) launched a bad query, due to jquery error.
|
||||||
* PHRAS-2510 - Front - Facets values appear Truncated after 15th character.
|
- PHRAS-2510 - Front - Facets values appear Truncated after 15th character.
|
||||||
* PHRAS-2153 - Front - No user search possible with the field "Company" and field "Country".
|
- PHRAS-2153 - Front - No user search possible with the field "Company" and field "Country".
|
||||||
* PHRAS-2154 - Front - Bug on Chrome only - selected 1 document instead of all for the feedback.
|
- PHRAS-2154 - Front - Bug on Chrome only - selected 1 document instead of all for the feedback.
|
||||||
* PHRAS-2538 - Back - Some MP4 files were not correctly detected by Phraseanet.
|
- PHRAS-2538 - Back - Some MP4 files were not correctly detected by Phraseanet.
|
||||||
|
|
||||||
## 4.0.8
|
## 4.0.8
|
||||||
|
|
||||||
|
@@ -37,7 +37,7 @@ RUN echo "deb http://deb.debian.org/debian stretch main non-free" > /etc/apt/sou
|
|||||||
swftools \
|
swftools \
|
||||||
unoconv \
|
unoconv \
|
||||||
unzip \
|
unzip \
|
||||||
xpdf \
|
poppler-utils \
|
||||||
libreoffice-base-core \
|
libreoffice-base-core \
|
||||||
libreoffice-impress \
|
libreoffice-impress \
|
||||||
libreoffice-calc \
|
libreoffice-calc \
|
||||||
@@ -67,6 +67,7 @@ RUN echo "deb http://deb.debian.org/debian stretch main non-free" > /etc/apt/sou
|
|||||||
libgsm1-dev \
|
libgsm1-dev \
|
||||||
libfreetype6-dev \
|
libfreetype6-dev \
|
||||||
# End FFmpeg
|
# End FFmpeg
|
||||||
|
nano \
|
||||||
&& update-locale "LANG=fr_FR.UTF-8 UTF-8" \
|
&& update-locale "LANG=fr_FR.UTF-8 UTF-8" \
|
||||||
&& dpkg-reconfigure --frontend noninteractive locales \
|
&& dpkg-reconfigure --frontend noninteractive locales \
|
||||||
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
|
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
|
||||||
|
41
README.md
@@ -32,9 +32,13 @@ And follow the install steps described at https://docs.phraseanet.com/4.0/en/Adm
|
|||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
- docker-compose
|
- docker-compose >=v1.25.4
|
||||||
- docker >=v18.01-ce
|
- docker >=v18.01-ce
|
||||||
|
|
||||||
|
Note about elasticsearch container
|
||||||
|
Check this link
|
||||||
|
https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html#docker-prod-prerequisites
|
||||||
|
|
||||||
## Get started
|
## Get started
|
||||||
|
|
||||||
You should review the default env variables defined in `.env` file.
|
You should review the default env variables defined in `.env` file.
|
||||||
@@ -84,8 +88,9 @@ docker-compose -f docker-compose.yml run --rm worker <command>
|
|||||||
```
|
```
|
||||||
|
|
||||||
Where `<command>` can be:
|
Where `<command>` can be:
|
||||||
- `bin/console task-manager:scheduler:run` (default)
|
|
||||||
- `bin/console worker:execute -m 2`
|
- `bin/console worker:execute -m 2` (default)
|
||||||
|
- `bin/console task-manager:scheduler:run`
|
||||||
- ...
|
- ...
|
||||||
|
|
||||||
The default parameters allow you to reach the app with : `http://localhost:8082`
|
The default parameters allow you to reach the app with : `http://localhost:8082`
|
||||||
@@ -100,6 +105,12 @@ https://hub.docker.com/r/alchemyfr/phraseanet-worker
|
|||||||
|
|
||||||
https://hub.docker.com/r/alchemyfr/phraseanet-nginx
|
https://hub.docker.com/r/alchemyfr/phraseanet-nginx
|
||||||
|
|
||||||
|
https://hub.docker.com/repository/docker/alchemyfr/phraseanet-db
|
||||||
|
|
||||||
|
https://hub.docker.com/repository/docker/alchemyfr/phraseanet-elasticsearch
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
To use them and not build the images locally, we advise to override the properties in file: env.local
|
To use them and not build the images locally, we advise to override the properties in file: env.local
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -108,6 +119,21 @@ PHRASEANET_DOCKER_REGISTRY=alchemyfr
|
|||||||
# Tag of the Docker images
|
# Tag of the Docker images
|
||||||
PHRASEANET_DOCKER_TAG=
|
PHRASEANET_DOCKER_TAG=
|
||||||
```
|
```
|
||||||
|
or
|
||||||
|
|
||||||
|
Pull images before launch docker-compose
|
||||||
|
|
||||||
|
#### Tag organisation on docker hub
|
||||||
|
|
||||||
|
|
||||||
|
```latest``` : latest stable version
|
||||||
|
|
||||||
|
```4.0``` : latest stable version in 4.0
|
||||||
|
|
||||||
|
```4.1``` : latest stable version in 4.1
|
||||||
|
|
||||||
|
```4.1.1``` : Phraseanet version 4.1.1
|
||||||
|
|
||||||
|
|
||||||
## Development mode
|
## Development mode
|
||||||
|
|
||||||
@@ -172,17 +198,20 @@ XDEBUG_REMOTE_HOST=host.docker.internal
|
|||||||
Plugins can be installed during build if you set the `PHRASEANET_PLUGINS` env var as follows:
|
Plugins can be installed during build if you set the `PHRASEANET_PLUGINS` env var as follows:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
PHRASEANET_PLUGINS="git@github.com:alchemy-fr/Phraseanet-plugin-webgallery.git"
|
PHRASEANET_PLUGINS="https://github.com/alchemy-fr/Phraseanet-plugin-expose.git"
|
||||||
|
|
||||||
# You can optionally precise the branch to install
|
# You can optionally precise the branch to install
|
||||||
# If not precised, the main branch will be pulled
|
# If not precised, the main branch will be pulled
|
||||||
PHRASEANET_PLUGINS="git@github.com:alchemy-fr/Phraseanet-plugin-webgallery.git(custom-branch)"
|
PHRASEANET_PLUGINS="git@github.com:alchemy-fr/Phraseanet-plugin-webgallery.git(custom-branch)"
|
||||||
|
|
||||||
# Plugins are separated by spaces
|
# Plugins are separated by semicolons
|
||||||
PHRASEANET_PLUGINS="git@github.com:foo/bar.git(branch-1) git@github.com:baz/42.git"
|
PHRASEANET_PLUGINS="git@github.com:foo/bar.git(branch-1);git@github.com:baz/42.git"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> Prefer the HTTPS URL for public repositories, you will not be required to provide your SSH key.
|
||||||
|
|
||||||
If you install private plugins, make sure you export your SSH private key content in order to allow docker build to access the GIT repository:
|
If you install private plugins, make sure you export your SSH private key content in order to allow docker build to access the GIT repository:
|
||||||
|
Also ensure you're using the SSH URL form (i.e: `git@github.com:alchemy-fr/repo.git`).
|
||||||
```bash
|
```bash
|
||||||
export PHRASEANET_SSH_PRIVATE_KEY=$(cat ~/.ssh/id_rsa)
|
export PHRASEANET_SSH_PRIVATE_KEY=$(cat ~/.ssh/id_rsa)
|
||||||
# or if your private key is protected by a passphrase:
|
# or if your private key is protected by a passphrase:
|
||||||
|
@@ -328,6 +328,14 @@ workers:
|
|||||||
password: guest
|
password: guest
|
||||||
vhost: /
|
vhost: /
|
||||||
|
|
||||||
|
externalservice:
|
||||||
|
ginger:
|
||||||
|
AutoSubtitling:
|
||||||
|
service_base_url: https://base.uri
|
||||||
|
token: 39c6011d
|
||||||
|
transcript_format: text/vtt
|
||||||
|
subdef_source: preview
|
||||||
|
|
||||||
user_account:
|
user_account:
|
||||||
deleting_policies:
|
deleting_policies:
|
||||||
email_confirmation: true
|
email_confirmation: true
|
||||||
|
@@ -13,10 +13,6 @@ services:
|
|||||||
- ../:/var/alchemy
|
- ../:/var/alchemy
|
||||||
- .:/var/alchemy/Phraseanet
|
- .:/var/alchemy/Phraseanet
|
||||||
- ./docker/nginx/root/entrypoint.sh:/entrypoint.sh
|
- ./docker/nginx/root/entrypoint.sh:/entrypoint.sh
|
||||||
- ${PHRASEANET_DATA_DIR}:/var/alchemy/Phraseanet/datas:rw
|
|
||||||
- ${PHRASEANET_THUMBNAILS_DIR}:/var/alchemy/Phraseanet/www/thumbnails:rw
|
|
||||||
- ${PHRASEANET_TMP_DIR}:/var/alchemy/Phraseanet/tmp:rw
|
|
||||||
- ${PHRASEANET_CUSTOM_DIR}:/var/alchemy/Phraseanet/www/custom:rw
|
|
||||||
|
|
||||||
builder:
|
builder:
|
||||||
build:
|
build:
|
||||||
@@ -50,25 +46,12 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ../:/var/alchemy
|
- ../:/var/alchemy
|
||||||
- .:/var/alchemy/Phraseanet
|
- .:/var/alchemy/Phraseanet
|
||||||
- ${PHRASEANET_CONFIG_DIR}:/var/alchemy/Phraseanet/config:rw
|
|
||||||
- ${PHRASEANET_LOGS_DIR}:/var/alchemy/Phraseanet/logs:rw
|
|
||||||
- ${PHRASEANET_DATA_DIR}:/var/alchemy/Phraseanet/datas:rw
|
|
||||||
- ${PHRASEANET_THUMBNAILS_DIR}:/var/alchemy/Phraseanet/www/thumbnails:rw
|
|
||||||
- ${PHRASEANET_CUSTOM_DIR}:/var/alchemy/Phraseanet/www/custom:rw
|
|
||||||
- ${PHRASEANET_CACHE_DIR}:/var/alchemy/Phraseanet/cache:rw
|
|
||||||
- ${PHRASEANET_TMP_DIR}:/var/alchemy/Phraseanet/tmp:rw
|
|
||||||
|
|
||||||
worker:
|
worker:
|
||||||
volumes:
|
volumes:
|
||||||
- ../:/var/alchemy
|
- ../:/var/alchemy
|
||||||
- .:/var/alchemy/Phraseanet
|
- .:/var/alchemy/Phraseanet
|
||||||
- ${PHRASEANET_CONFIG_DIR}:/var/alchemy/Phraseanet/config:rw
|
|
||||||
- ${PHRASEANET_LOGS_DIR}:/var/alchemy/Phraseanet/logs:rw
|
|
||||||
- ${PHRASEANET_DATA_DIR}:/var/alchemy/Phraseanet/datas:rw
|
|
||||||
- ${PHRASEANET_THUMBNAILS_DIR}:/var/alchemy/Phraseanet/www/thumbnails:rw
|
|
||||||
- ${PHRASEANET_CUSTOM_DIR}:/var/alchemy/Phraseanet/www/custom:rw
|
|
||||||
- ${PHRASEANET_CACHE_DIR}:/var/alchemy/Phraseanet/cache:rw
|
|
||||||
- ${PHRASEANET_TMP_DIR}:/var/alchemy/Phraseanet/tmp:rw
|
|
||||||
|
|
||||||
rabbitmq:
|
rabbitmq:
|
||||||
ports:
|
ports:
|
||||||
|
@@ -14,10 +14,12 @@ services:
|
|||||||
- ${PHRASEANET_DATA_DIR}:/var/alchemy/Phraseanet/datas:rw
|
- ${PHRASEANET_DATA_DIR}:/var/alchemy/Phraseanet/datas:rw
|
||||||
- ${PHRASEANET_THUMBNAILS_DIR}:/var/alchemy/Phraseanet/www/thumbnails:rw
|
- ${PHRASEANET_THUMBNAILS_DIR}:/var/alchemy/Phraseanet/www/thumbnails:rw
|
||||||
- ${PHRASEANET_CUSTOM_DIR}:/var/alchemy/Phraseanet/www/custom:rw
|
- ${PHRASEANET_CUSTOM_DIR}:/var/alchemy/Phraseanet/www/custom:rw
|
||||||
|
- ${PHRASEANET_PLUGINS_DIR}:/var/alchemy/Phraseanet/www/plugins:rw
|
||||||
depends_on:
|
depends_on:
|
||||||
- phraseanet
|
- phraseanet
|
||||||
environment:
|
environment:
|
||||||
- MAX_BODY_SIZE
|
- MAX_BODY_SIZE
|
||||||
|
- GATEWAY_SEND_TIMEOUT
|
||||||
ports:
|
ports:
|
||||||
- ${PHRASEANET_APP_PORT}:80
|
- ${PHRASEANET_APP_PORT}:80
|
||||||
|
|
||||||
@@ -39,9 +41,12 @@ services:
|
|||||||
- PHRASEANET_PROJECT_NAME
|
- PHRASEANET_PROJECT_NAME
|
||||||
- MAX_BODY_SIZE
|
- MAX_BODY_SIZE
|
||||||
- MAX_INPUT_VARS
|
- MAX_INPUT_VARS
|
||||||
|
- MAX_EXECUTION_TIME
|
||||||
|
- MAX_INPUT_TIME
|
||||||
- OPCACHE_ENABLED
|
- OPCACHE_ENABLED
|
||||||
- SESSION_CACHE_LIMITER
|
- SESSION_CACHE_LIMITER
|
||||||
- PHP_LOG_LEVEL
|
- PHP_LOG_LEVEL
|
||||||
|
- PHRASEANET_ADMIN_ACCOUNT_ID
|
||||||
- PHRASEANET_ADMIN_ACCOUNT_EMAIL
|
- PHRASEANET_ADMIN_ACCOUNT_EMAIL
|
||||||
- PHRASEANET_ADMIN_ACCOUNT_PASSWORD
|
- PHRASEANET_ADMIN_ACCOUNT_PASSWORD
|
||||||
- PHRASEANET_DB_HOST
|
- PHRASEANET_DB_HOST
|
||||||
@@ -63,14 +68,28 @@ services:
|
|||||||
- PHRASEANET_SMTP_SECURE_MODE
|
- PHRASEANET_SMTP_SECURE_MODE
|
||||||
- PHRASEANET_SMTP_USER
|
- PHRASEANET_SMTP_USER
|
||||||
- PHRASEANET_SMTP_PASSWORD
|
- PHRASEANET_SMTP_PASSWORD
|
||||||
|
- PHRASEANET_DOWNLOAD_DIR
|
||||||
|
- PHRASEANET_LAZARET_DIR
|
||||||
|
- PHRASEANET_CAPTION_DIR
|
||||||
|
- PHRASEANET_WORKER_TMP
|
||||||
|
- LC_MESSAGES=C.UTF-8
|
||||||
|
- LC_COLLATE=C.UTF-8
|
||||||
|
- LC_IDENTIFICATION=C.UTF-8
|
||||||
|
- LANG=C.UTF-8
|
||||||
|
- LC_MEASUREMENT=C.UTF-8
|
||||||
|
- LC_CTYPE=C.UTF-8
|
||||||
|
- LC_TIME=C.UTF-8
|
||||||
|
- LC_NAME=C.UTF-8
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
- config_vol:/var/alchemy/Phraseanet/config:rw
|
- ${PHRASEANET_CONFIG_DIR}:/var/alchemy/Phraseanet/config:rw
|
||||||
- data_vol:/var/alchemy/Phraseanet/datas:rw
|
- ${PHRASEANET_LOGS_DIR}:/var/alchemy/Phraseanet/logs:rw
|
||||||
- tmp_vol:/var/alchemy/Phraseanet/tmp:rw
|
- ${PHRASEANET_DATA_DIR}:/var/alchemy/Phraseanet/datas:rw
|
||||||
- logs_vol:/var/alchemy/Phraseanet/logs:rw
|
- ${PHRASEANET_THUMBNAILS_DIR}:/var/alchemy/Phraseanet/www/thumbnails:rw
|
||||||
- thumbnails_vol:/var/alchemy/Phraseanet/www/thumbnails:rw
|
- ${PHRASEANET_CUSTOM_DIR}:/var/alchemy/Phraseanet/www/custom:rw
|
||||||
- custom_vol:/var/alchemy/Phraseanet/www/custom:rw
|
- ${PHRASEANET_PLUGINS_DIR}:/var/alchemy/Phraseanet/www/plugins:rw
|
||||||
- cache_vol:/var/alchemy/Phraseanet/cache:rw
|
- ${PHRASEANET_CACHE_DIR}:/var/alchemy/Phraseanet/cache:rw
|
||||||
|
- ${PHRASEANET_TMP_DIR}:/var/alchemy/Phraseanet/tmp:rw
|
||||||
|
|
||||||
worker:
|
worker:
|
||||||
build:
|
build:
|
||||||
@@ -93,14 +112,23 @@ services:
|
|||||||
- OPCACHE_ENABLED
|
- OPCACHE_ENABLED
|
||||||
- SESSION_CACHE_LIMITER
|
- SESSION_CACHE_LIMITER
|
||||||
- PHP_LOG_LEVEL
|
- PHP_LOG_LEVEL
|
||||||
|
- LC_MESSAGES=C.UTF-8
|
||||||
|
- LC_COLLATE=C.UTF-8
|
||||||
|
- LC_IDENTIFICATION=C.UTF-8
|
||||||
|
- LANG=C.UTF-8
|
||||||
|
- LC_MEASUREMENT=C.UTF-8
|
||||||
|
- LC_CTYPE=C.UTF-8
|
||||||
|
- LC_TIME=C.UTF-8
|
||||||
|
- LC_NAME=C.UTF-8
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
- config_vol:/var/alchemy/Phraseanet/config:rw
|
- ${PHRASEANET_CONFIG_DIR}:/var/alchemy/Phraseanet/config:rw
|
||||||
- data_vol:/var/alchemy/Phraseanet/datas:rw
|
- ${PHRASEANET_LOGS_DIR}:/var/alchemy/Phraseanet/logs:rw
|
||||||
- tmp_vol:/var/alchemy/Phraseanet/tmp:rw
|
- ${PHRASEANET_DATA_DIR}:/var/alchemy/Phraseanet/datas:rw
|
||||||
- logs_vol:/var/alchemy/Phraseanet/logs:rw
|
- ${PHRASEANET_THUMBNAILS_DIR}:/var/alchemy/Phraseanet/www/thumbnails:rw
|
||||||
- thumbnails_vol:/var/alchemy/Phraseanet/www/thumbnails:rw
|
- ${PHRASEANET_CUSTOM_DIR}:/var/alchemy/Phraseanet/www/custom:rw
|
||||||
- custom_vol:/var/alchemy/Phraseanet/www/custom:rw
|
- ${PHRASEANET_CACHE_DIR}:/var/alchemy/Phraseanet/cache:rw
|
||||||
- cache_vol:/var/alchemy/Phraseanet/cache:rw
|
- ${PHRASEANET_TMP_DIR}:/var/alchemy/Phraseanet/tmp:rw
|
||||||
|
|
||||||
db:
|
db:
|
||||||
image: $PHRASEANET_DOCKER_REGISTRY/phraseanet-db:$PHRASEANET_DOCKER_TAG
|
image: $PHRASEANET_DOCKER_REGISTRY/phraseanet-db:$PHRASEANET_DOCKER_TAG
|
||||||
@@ -151,10 +179,12 @@ volumes:
|
|||||||
driver: local
|
driver: local
|
||||||
custom_vol:
|
custom_vol:
|
||||||
driver: local
|
driver: local
|
||||||
|
plugins_dir:
|
||||||
|
driver: local
|
||||||
cache_vol:
|
cache_vol:
|
||||||
driver: local
|
driver: local
|
||||||
# to be replacer by stdout/stderr
|
# to be replacer by stdout/stderr
|
||||||
logs_vol:
|
logs_vol:
|
||||||
driver: local
|
driver: local
|
||||||
dev_vol:
|
dev_vol:
|
||||||
driver: local
|
driver: local
|
||||||
|
@@ -2,6 +2,6 @@
|
|||||||
|
|
||||||
set -xe
|
set -xe
|
||||||
|
|
||||||
cat /nginx.conf.sample | sed "s/\$MAX_BODY_SIZE/$MAX_BODY_SIZE/g" > /etc/nginx/conf.d/default.conf
|
cat /nginx.conf.sample | sed "s/\$MAX_BODY_SIZE/$MAX_BODY_SIZE/g" | sed "s/\$GATEWAY_SEND_TIMEOUT/$GATEWAY_SEND_TIMEOUT/g" > /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
exec "$@"
|
exec "$@"
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
send_timeout $GATEWAY_SEND_TIMEOUT;
|
||||||
upstream backend {
|
upstream backend {
|
||||||
server phraseanet:9000;
|
server phraseanet:9000;
|
||||||
}
|
}
|
||||||
|
@@ -12,26 +12,33 @@ chown -R app:app \
|
|||||||
datas \
|
datas \
|
||||||
tmp \
|
tmp \
|
||||||
logs \
|
logs \
|
||||||
www/thumbnails \
|
www
|
||||||
www/custom
|
|
||||||
|
|
||||||
FILE=config/configuration.yml
|
FILE=config/configuration.yml
|
||||||
|
|
||||||
if [ -f "$FILE" ]; then
|
if [ -f "$FILE" ]; then
|
||||||
echo "$FILE exists, skip setup."
|
echo "$FILE exists, skip setup."
|
||||||
bin/setup system:config set registry.general.title $PHRASEANET_PROJECT_NAME
|
if [[ $PHRASEANET_PROJECT_NAME ]]; then
|
||||||
if [[ $PHRASEANET_SMTP_ENABLED=true ]]; then
|
bin/setup system:config set registry.general.title $PHRASEANET_PROJECT_NAME
|
||||||
|
fi
|
||||||
|
if [[ $PHRASEANET_SMTP_ENABLED && $PHRASEANET_SMTP_ENABLED=true ]]; then
|
||||||
bin/setup system:config set registry.email.smtp-enabled $PHRASEANET_SMTP_ENABLED
|
bin/setup system:config set registry.email.smtp-enabled $PHRASEANET_SMTP_ENABLED
|
||||||
bin/setup system:config set registry.email.smtp-auth-enabled $PHRASEANET_SMTP_AUTH_ENABLED
|
bin/setup system:config set registry.email.smtp-auth-enabled $PHRASEANET_SMTP_AUTH_ENABLED
|
||||||
bin/setup system:config set registry.email.smtp-auth-secure-mode $PHRASEANET_SMTP_SECURE_MODE
|
bin/setup system:config set registry.email.smtp-auth-secure-mode $PHRASEANET_SMTP_SECURE_MODE
|
||||||
bin/setup system:config set registry.email.smtp-auth-host $PHRASEANET_SMTP_HOST
|
bin/setup system:config set registry.email.smtp-host $PHRASEANET_SMTP_HOST
|
||||||
bin/setup system:config set registry.email.smtp-auth-port $PHRASEANET_SMTP_PORT
|
bin/setup system:config set registry.email.smtp-port $PHRASEANET_SMTP_PORT
|
||||||
bin/setup system:config set registry.email.smtp-user $PHRASEANET_SMTP_USER
|
bin/setup system:config set registry.email.smtp-user $PHRASEANET_SMTP_USER
|
||||||
bin/setup system:config set registry.email.smtp-password $PHRASEANET_SMTP_PASSWORD
|
bin/setup system:config set registry.email.smtp-password $PHRASEANET_SMTP_PASSWORD
|
||||||
bin/setup system:config set registry.email.emitter-email $PHRASEANET_EMITTER_EMAIL
|
bin/setup system:config set registry.email.emitter-email $PHRASEANET_EMITTER_EMAIL
|
||||||
bin/setup system:config set registry.email.prefix $PHRASEANET_MAIL_OBJECT_PREFIX
|
bin/setup system:config set registry.email.prefix $PHRASEANET_MAIL_OBJECT_PREFIX
|
||||||
|
if [[ -n $PHRASEANET_TRUSTED_PROXY ]]; then
|
||||||
|
bin/setup system:config add trusted-proxies $PHRASEANET_TRUSTED_PROXY
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
bin/console user:password --user_id=1 --password $PHRASEANET_ADMIN_ACCOUNT_PASSWORD -y
|
if [[ -n ${PHRASEANET_ADMIN_ACCOUNT_ID} && $PHRASEANET_ADMIN_ACCOUNT_ID =~ ^[0-9]+$ ]]; then
|
||||||
|
bin/console user:password --user_id=$PHRASEANET_ADMIN_ACCOUNT_ID --password $PHRASEANET_ADMIN_ACCOUNT_PASSWORD -y
|
||||||
|
fi
|
||||||
|
|
||||||
else
|
else
|
||||||
echo "$FILE doesn't exist, entering setup..."
|
echo "$FILE doesn't exist, entering setup..."
|
||||||
runuser app -c docker/phraseanet/auto-install.sh
|
runuser app -c docker/phraseanet/auto-install.sh
|
||||||
@@ -43,5 +50,18 @@ if [ ${XDEBUG_ENABLED} == "1" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
./docker/phraseanet/plugins/console init
|
./docker/phraseanet/plugins/console init
|
||||||
|
#rm -Rf cache/
|
||||||
|
|
||||||
|
chown -R app:app \
|
||||||
|
cache \
|
||||||
|
config \
|
||||||
|
datas \
|
||||||
|
tmp \
|
||||||
|
logs \
|
||||||
|
www
|
||||||
|
|
||||||
|
if [ -d "plugins/" ];then
|
||||||
|
chown -R app:app plugins;
|
||||||
|
fi
|
||||||
|
|
||||||
bash -e docker-php-entrypoint $@
|
bash -e docker-php-entrypoint $@
|
||||||
|
@@ -380,7 +380,7 @@ expose_php = On
|
|||||||
; Maximum execution time of each script, in seconds
|
; Maximum execution time of each script, in seconds
|
||||||
; http://php.net/max-execution-time
|
; http://php.net/max-execution-time
|
||||||
; Note: This directive is hardcoded to 0 for the CLI SAPI
|
; Note: This directive is hardcoded to 0 for the CLI SAPI
|
||||||
max_execution_time = 9999
|
max_execution_time = $MAX_EXECUTION_TIME
|
||||||
|
|
||||||
; Maximum amount of time each script may spend parsing request data. It's a good
|
; Maximum amount of time each script may spend parsing request data. It's a good
|
||||||
; idea to limit this time on productions servers in order to eliminate unexpectedly
|
; idea to limit this time on productions servers in order to eliminate unexpectedly
|
||||||
@@ -390,7 +390,7 @@ max_execution_time = 9999
|
|||||||
; Development Value: 60 (60 seconds)
|
; Development Value: 60 (60 seconds)
|
||||||
; Production Value: 60 (60 seconds)
|
; Production Value: 60 (60 seconds)
|
||||||
; http://php.net/max-input-time
|
; http://php.net/max-input-time
|
||||||
max_input_time = 60
|
max_input_time = $MAX_INPUT_TIME
|
||||||
|
|
||||||
; Maximum input variable nesting level
|
; Maximum input variable nesting level
|
||||||
; http://php.net/max-input-nesting-level
|
; http://php.net/max-input-nesting-level
|
||||||
|
@@ -29,7 +29,7 @@ class InstallCommand extends Command
|
|||||||
mkdir($pluginsDir);
|
mkdir($pluginsDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (explode(' ', $plugins) as $key => $plugin) {
|
foreach (explode(';', $plugins) as $key => $plugin) {
|
||||||
$plugin = trim($plugin);
|
$plugin = trim($plugin);
|
||||||
$repo = $plugin;
|
$repo = $plugin;
|
||||||
$branch = 'master';
|
$branch = 'master';
|
||||||
|
@@ -91,7 +91,6 @@ use Alchemy\Phrasea\WorkerManager\Provider\AlchemyWorkerServiceProvider;
|
|||||||
use Alchemy\Phrasea\WorkerManager\Provider\QueueWorkerServiceProvider;
|
use Alchemy\Phrasea\WorkerManager\Provider\QueueWorkerServiceProvider;
|
||||||
use Alchemy\QueueProvider\QueueServiceProvider;
|
use Alchemy\QueueProvider\QueueServiceProvider;
|
||||||
use Alchemy\WorkerProvider\WorkerServiceProvider;
|
use Alchemy\WorkerProvider\WorkerServiceProvider;
|
||||||
use Doctrine\DBAL\Event\ConnectionEventArgs;
|
|
||||||
use MediaVorus\Media\MediaInterface;
|
use MediaVorus\Media\MediaInterface;
|
||||||
use MediaVorus\MediaVorus;
|
use MediaVorus\MediaVorus;
|
||||||
use Monolog\Handler\ErrorLogHandler;
|
use Monolog\Handler\ErrorLogHandler;
|
||||||
@@ -618,7 +617,7 @@ class Application extends SilexApplication
|
|||||||
);
|
);
|
||||||
|
|
||||||
$this['tmp.lazaret.path'] = $factory->createDefinition(
|
$this['tmp.lazaret.path'] = $factory->createDefinition(
|
||||||
['main', 'storage', 'quarantine'],
|
['main', 'storage', 'lazaret'],
|
||||||
function (Application $app) {
|
function (Application $app) {
|
||||||
return $app['tmp.path'].'/lazaret';
|
return $app['tmp.path'].'/lazaret';
|
||||||
}
|
}
|
||||||
|
@@ -2093,7 +2093,7 @@ class V1Controller extends Controller
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$collection = \collection::getByBaseId($this->app, $request->get('base_id'));
|
$collection = \collection::getByBaseId($this->app, $request->get('base_id'));
|
||||||
$record->move_to_collection($collection, $this->getApplicationBox());
|
$record->move_to_collection($collection);
|
||||||
|
|
||||||
return Result::create($request, ["record" => $this->listRecord($request, $record)])->createResponse();
|
return Result::create($request, ["record" => $this->listRecord($request, $record)])->createResponse();
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
|
393
lib/Alchemy/Phrasea/Controller/Api/V3/V3RecordController.php
Normal file
@@ -0,0 +1,393 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Alchemy\Phrasea\Controller\Api\V3;
|
||||||
|
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\Application\Helper\DispatcherAware;
|
||||||
|
use Alchemy\Phrasea\Application\Helper\JsonBodyAware;
|
||||||
|
use Alchemy\Phrasea\Controller\Api\Result;
|
||||||
|
use Alchemy\Phrasea\Controller\Controller;
|
||||||
|
use Alchemy\Phrasea\Core\Event\RecordEdit;
|
||||||
|
use Alchemy\Phrasea\Core\PhraseaEvents;
|
||||||
|
use caption_field;
|
||||||
|
use databox_field;
|
||||||
|
use Exception;
|
||||||
|
use record_adapter;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
|
||||||
|
class V3RecordController extends Controller
|
||||||
|
{
|
||||||
|
use JsonBodyAware;
|
||||||
|
use DispatcherAware;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return detailed information about one story
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param int $databox_id
|
||||||
|
* @param int $record_id
|
||||||
|
*
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
public function indexAction_patch(Request $request, $databox_id, $record_id)
|
||||||
|
{
|
||||||
|
$struct = $this->findDataboxById($databox_id)->get_meta_structure();
|
||||||
|
$record = $this->findDataboxById($databox_id)->get_record($record_id);
|
||||||
|
|
||||||
|
//$record->set_metadatas()
|
||||||
|
|
||||||
|
//setRecordStatusAction
|
||||||
|
|
||||||
|
try {
|
||||||
|
$b = $this->decodeJsonBody($request);
|
||||||
|
}
|
||||||
|
catch (Exception $e) {
|
||||||
|
return $this->app['controller.api.v1']->getBadRequestAction($request, 'Bad JSON');
|
||||||
|
}
|
||||||
|
|
||||||
|
$debug = [
|
||||||
|
'metadatas_ops' => null,
|
||||||
|
'sb_ops' => null,
|
||||||
|
];
|
||||||
|
try {
|
||||||
|
// do metadatas ops
|
||||||
|
if (is_array($b->metadatas)) {
|
||||||
|
$debug['metadatas_ops'] = $this->do_metadatas($struct, $record, $b->metadatas);
|
||||||
|
}
|
||||||
|
// do sb ops
|
||||||
|
if (is_array($b->status)) {
|
||||||
|
$debug['sb_ops'] = $this->do_status($record, $b->status);
|
||||||
|
}
|
||||||
|
if(!is_null($b->base_id)) {
|
||||||
|
$debug['coll_ops'] = $this->do_collection($record, $b->base_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception $e) {
|
||||||
|
return $this->app['controller.api.v1']->getBadRequestAction(
|
||||||
|
$request,
|
||||||
|
$e->getMessage()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @todo Move event dispatch inside record_adapter class (keeps things encapsulated)
|
||||||
|
$this->dispatch(PhraseaEvents::RECORD_EDIT, new RecordEdit($record));
|
||||||
|
|
||||||
|
$ret = $this->getResultHelpers()->listRecord($request, $record, $this->getAclForUser());
|
||||||
|
|
||||||
|
return Result::create($request, $ret)->createResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param record_adapter $record
|
||||||
|
* @param $base_id
|
||||||
|
*/
|
||||||
|
private function do_collection(record_adapter $record, $base_id)
|
||||||
|
{
|
||||||
|
$record->move_to_collection($this->getApplicationBox()->get_collection($base_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////
|
||||||
|
/// TODO : keep multi-values uniques !
|
||||||
|
/// it should be done in record_adapter
|
||||||
|
//////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param databox_field[] $struct
|
||||||
|
* @param record_adapter $record
|
||||||
|
* @param $metadatas
|
||||||
|
* @return array
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private function do_metadatas($struct, record_adapter $record, $metadatas)
|
||||||
|
{
|
||||||
|
$structByKey = [];
|
||||||
|
$allStructFields = [];
|
||||||
|
foreach ($struct as $f) {
|
||||||
|
$allStructFields[$f->get_id()] = $f;
|
||||||
|
$structByKey[$f->get_id()] = &$allStructFields[$f->get_id()];
|
||||||
|
$structByKey[$f->get_name()] = &$allStructFields[$f->get_id()];
|
||||||
|
}
|
||||||
|
|
||||||
|
$metadatas_ops = [];
|
||||||
|
foreach ($metadatas as $_m) {
|
||||||
|
// sanity
|
||||||
|
if($_m->meta_struct_id && $_m->field_name) {
|
||||||
|
throw new Exception("define meta_struct_id OR field_name, not both.");
|
||||||
|
}
|
||||||
|
// select fields that match meta_struct_id or field_name (can be arrays)
|
||||||
|
$fields_list = null; // to filter caption_fields from record, default all
|
||||||
|
$struct_fields = []; // struct fields that match meta_struct_id or field_name
|
||||||
|
$field_keys = $_m->meta_struct_id ? $_m->meta_struct_id : $_m->field_name; // can be null if none defined (=match all)
|
||||||
|
if($field_keys !== null) {
|
||||||
|
if (!is_array($field_keys)) {
|
||||||
|
$field_keys = [$field_keys];
|
||||||
|
}
|
||||||
|
$fields_list = [];
|
||||||
|
foreach ($field_keys as $k) {
|
||||||
|
if(array_key_exists($k, $structByKey)) {
|
||||||
|
$fields_list[] = $structByKey[$k]->get_name();
|
||||||
|
$struct_fields[$structByKey[$k]->get_id()] = $structByKey[$k];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new Exception(sprintf("unknown field (%s).", $k));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// no meta_struct_id, no field_name --> match all struct fields !
|
||||||
|
$struct_fields = $allStructFields;
|
||||||
|
}
|
||||||
|
$caption_fields = $record->get_caption()->get_fields($fields_list, true);
|
||||||
|
|
||||||
|
$meta_id = is_null($_m->meta_id) ? null : (int)($_m->meta_id);
|
||||||
|
|
||||||
|
if(!($match_method = (string)($_m->match_method))) {
|
||||||
|
$match_method = 'ignore_case';
|
||||||
|
}
|
||||||
|
if(!in_array($match_method, ['strict', 'ignore_case', 'regexp'])) {
|
||||||
|
throw new Exception(sprintf("bad match_method (%s).", $match_method));
|
||||||
|
}
|
||||||
|
|
||||||
|
$values = [];
|
||||||
|
if(is_array($_m->value)) {
|
||||||
|
foreach ($_m->value as $v) {
|
||||||
|
if(($v = trim((string)$v)) !== '') {
|
||||||
|
$values[] = $v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(($v = trim((string)($_m->value))) !== '') {
|
||||||
|
$values[] = $v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!($action = (string)($_m->action))) {
|
||||||
|
$action = 'set';
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($_m->action) {
|
||||||
|
case 'set':
|
||||||
|
$ops = $this->metadata_set($struct_fields, $caption_fields, $meta_id, $values);
|
||||||
|
break;
|
||||||
|
case 'add':
|
||||||
|
$ops = $this->metadata_add($struct_fields, $values);
|
||||||
|
break;
|
||||||
|
case 'delete':
|
||||||
|
$ops = $this->metadata_replace($caption_fields, $meta_id, $match_method, $values, null);
|
||||||
|
break;
|
||||||
|
case 'replace':
|
||||||
|
if (!is_string($_m->replace_with) && !is_null($_m->replace_with)) {
|
||||||
|
throw new Exception("bad \"replace_with\" for action \"replace\".");
|
||||||
|
}
|
||||||
|
$ops = $this->metadata_replace($caption_fields, $meta_id, $match_method, $values, $_m->replace_with);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception(sprintf("bad action (%s).", $action));
|
||||||
|
}
|
||||||
|
|
||||||
|
$metadatas_ops = array_merge($metadatas_ops, $ops);
|
||||||
|
}
|
||||||
|
|
||||||
|
$record->set_metadatas($metadatas_ops, true);
|
||||||
|
|
||||||
|
return $metadatas_ops;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $record
|
||||||
|
* @param $statuses
|
||||||
|
* @return array
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private function do_status(record_adapter $record, $statuses)
|
||||||
|
{
|
||||||
|
$datas = strrev($record->getStatus());
|
||||||
|
|
||||||
|
foreach ($statuses as $status) {
|
||||||
|
$n = (int)($status->bit);
|
||||||
|
$value = (int)($status->state);
|
||||||
|
if ($n > 31 || $n < 4) {
|
||||||
|
throw new Exception(sprintf("Invalid status bit number (%s).", $n));
|
||||||
|
}
|
||||||
|
if ($value < 0 || $value > 1) {
|
||||||
|
throw new Exception(sprintf("Invalid status bit state (%s) for bit (%s).", $value, $n));
|
||||||
|
}
|
||||||
|
|
||||||
|
$datas = substr($datas, 0, ($n)) . $value . substr($datas, ($n + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
$record->setStatus(strrev($datas));
|
||||||
|
|
||||||
|
return ["status" => $this->getResultHelpers()->listRecordStatus($record)];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function match($pattern, $method, $value)
|
||||||
|
{
|
||||||
|
switch ($method) {
|
||||||
|
case 'strict':
|
||||||
|
return $value === $pattern;
|
||||||
|
case 'ignore_case':
|
||||||
|
return strtolower($value) === strtolower($pattern);
|
||||||
|
case 'regexp':
|
||||||
|
return preg_match($pattern, $value) == 1;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param databox_field[] $struct_fields struct-fields (from struct) matching meta_struct_id or field_name
|
||||||
|
* @param caption_field[] $caption_fields caption-fields (from record) matching meta_struct_id or field_name (or all if not set)
|
||||||
|
* @param int|null $meta_id
|
||||||
|
* @param string[] $values
|
||||||
|
*
|
||||||
|
* @return array ops to execute
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private function metadata_set($struct_fields, $caption_fields, $meta_id, $values)
|
||||||
|
{
|
||||||
|
$ops = [];
|
||||||
|
|
||||||
|
// if one field was multi-valued and no meta_id was set, we must delete all values
|
||||||
|
foreach ($caption_fields as $cf) {
|
||||||
|
foreach ($cf->get_values() as $field_value) {
|
||||||
|
if (is_null($meta_id) || $field_value->getId() === (int)$meta_id) {
|
||||||
|
$ops[] = [
|
||||||
|
'meta_struct_id' => $cf->get_meta_struct_id(),
|
||||||
|
'meta_id' => $field_value->getId(),
|
||||||
|
'value' => ''
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// now set values to matching struct_fields
|
||||||
|
foreach ($struct_fields as $sf) {
|
||||||
|
if($sf->is_multi()) {
|
||||||
|
// add the non-null value(s)
|
||||||
|
foreach ($values as $value) {
|
||||||
|
if ($value) {
|
||||||
|
$ops[] = [
|
||||||
|
'meta_struct_id' => $sf->get_id(),
|
||||||
|
'meta_id' => $meta_id, // can be null
|
||||||
|
'value' => $value
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// mono-valued
|
||||||
|
if(count($values) > 1) {
|
||||||
|
throw new Exception(sprintf("setting mono-valued (%s) requires only one value.", $sf->get_name()));
|
||||||
|
}
|
||||||
|
if( ($value = $values[0]) ) {
|
||||||
|
$ops[] = [
|
||||||
|
'meta_struct_id' => $sf->get_id(),
|
||||||
|
'meta_id' => $meta_id, // probably null,
|
||||||
|
'value' => $value
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ops;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param databox_field[] $struct_fields struct-fields (from struct) matching meta_struct_id or field_name
|
||||||
|
* @param string[] $values
|
||||||
|
*
|
||||||
|
* @return array ops to execute
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private function metadata_add($struct_fields, $values)
|
||||||
|
{
|
||||||
|
$ops = [];
|
||||||
|
|
||||||
|
// now set values to matching struct_fields
|
||||||
|
foreach ($struct_fields as $sf) {
|
||||||
|
if(!$sf->is_multi()) {
|
||||||
|
throw new Exception(sprintf("can't \"add\" to mono-valued (%s).", $sf->get_name()));
|
||||||
|
}
|
||||||
|
foreach ($values as $value) {
|
||||||
|
$ops[] = [
|
||||||
|
'meta_struct_id' => $sf->get_id(),
|
||||||
|
'meta_id' => null,
|
||||||
|
'value' => $value
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ops;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param caption_field[] $caption_fields caption-fields (from record) matching meta_struct_id or field_name (or all if not set)
|
||||||
|
* @param int|null $meta_id
|
||||||
|
* @param string $match_method "strict" | "ignore_case" | "regexp"
|
||||||
|
* @param string[] $values
|
||||||
|
* @param string|null $replace_with
|
||||||
|
*
|
||||||
|
* @return array ops to execute
|
||||||
|
*/
|
||||||
|
private function metadata_replace($caption_fields, $meta_id, $match_method, $values, $replace_with)
|
||||||
|
{
|
||||||
|
$ops = [];
|
||||||
|
|
||||||
|
$replace_with = trim((string)$replace_with);
|
||||||
|
|
||||||
|
foreach ($caption_fields as $cf) {
|
||||||
|
// match all ?
|
||||||
|
if(is_null($meta_id) && count($values) == 0) {
|
||||||
|
foreach ($cf->get_values() as $field_value) {
|
||||||
|
$ops[] = [
|
||||||
|
'meta_struct_id' => $cf->get_meta_struct_id(),
|
||||||
|
'meta_id' => $field_value->getId(),
|
||||||
|
'value' => $replace_with
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// match by meta-id ?
|
||||||
|
if (!is_null($meta_id)) {
|
||||||
|
foreach ($cf->get_values() as $field_value) {
|
||||||
|
if ($field_value->getId() === $meta_id) {
|
||||||
|
$ops[] = [
|
||||||
|
'meta_struct_id' => $cf->get_meta_struct_id(),
|
||||||
|
'meta_id' => $field_value->getId(),
|
||||||
|
'value' => $replace_with
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// match by value(s) ?
|
||||||
|
foreach ($values as $value) {
|
||||||
|
foreach ($cf->get_values() as $field_value) {
|
||||||
|
$rw = $replace_with;
|
||||||
|
if($match_method=='regexp' && $rw != '') {
|
||||||
|
$rw = preg_replace($value, $rw, $field_value->getValue());
|
||||||
|
}
|
||||||
|
if ($this->match($value, $match_method, $field_value->getValue())) {
|
||||||
|
$ops[] = [
|
||||||
|
'meta_struct_id' => $cf->get_meta_struct_id(),
|
||||||
|
'meta_id' => $field_value->getId(),
|
||||||
|
'value' => $rw
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ops;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return V3ResultHelpers
|
||||||
|
*/
|
||||||
|
private function getResultHelpers()
|
||||||
|
{
|
||||||
|
return $this->app['controller.api.v3.resulthelpers'];
|
||||||
|
}
|
||||||
|
}
|
277
lib/Alchemy/Phrasea/Controller/Api/V3/V3ResultHelpers.php
Normal file
@@ -0,0 +1,277 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Alchemy\Phrasea\Controller\Api\V3;
|
||||||
|
|
||||||
|
|
||||||
|
use ACL;
|
||||||
|
use Alchemy\Phrasea\Authentication\Authenticator;
|
||||||
|
use Alchemy\Phrasea\Core\Configuration\PropertyAccess;
|
||||||
|
use Alchemy\Phrasea\Media\MediaSubDefinitionUrlGenerator;
|
||||||
|
use caption_field;
|
||||||
|
use databox_status;
|
||||||
|
use media_Permalink_Adapter;
|
||||||
|
use media_subdef;
|
||||||
|
use record_adapter;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
|
||||||
|
|
||||||
|
class V3ResultHelpers
|
||||||
|
{
|
||||||
|
/** @var PropertyAccess */
|
||||||
|
private $conf;
|
||||||
|
|
||||||
|
/** @var MediaSubDefinitionUrlGenerator */
|
||||||
|
private $urlgenerator;
|
||||||
|
|
||||||
|
/** @var Authenticator */
|
||||||
|
private $authenticator;
|
||||||
|
|
||||||
|
|
||||||
|
public function __construct($conf, $urlgenerator, Authenticator $authenticator)
|
||||||
|
{
|
||||||
|
$this->urlgenerator = $urlgenerator;
|
||||||
|
$this->conf = $conf;
|
||||||
|
$this->authenticator = $authenticator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve detailed information about one status
|
||||||
|
*
|
||||||
|
* @param record_adapter $record
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function listRecordStatus(record_adapter $record)
|
||||||
|
{
|
||||||
|
$ret = [];
|
||||||
|
foreach ($record->getStatusStructure() as $bit => $status) {
|
||||||
|
$ret[] = [
|
||||||
|
'bit' => $bit,
|
||||||
|
'state' => databox_status::bitIsSet($record->getStatusBitField(), $bit),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function listEmbeddableMedia(Request $request, record_adapter $record, media_subdef $media, ACL $acl)
|
||||||
|
{
|
||||||
|
if (!$media->is_physically_present()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->getAuthenticator()->isAuthenticated()) {
|
||||||
|
if ($media->get_name() !== 'document'
|
||||||
|
&& false === $acl->has_access_to_subdef($record, $media->get_name())
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if ($media->get_name() === 'document'
|
||||||
|
&& !$acl->has_right_on_base($record->getBaseId(), ACL::CANDWNLDHD)
|
||||||
|
&& !$acl->has_hd_grant($record)
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($media->get_permalink() instanceof media_Permalink_Adapter) {
|
||||||
|
$permalink = $this->listPermalink($media->get_permalink());
|
||||||
|
} else {
|
||||||
|
$permalink = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$urlTTL = (int) $request->get(
|
||||||
|
'subdef_url_ttl',
|
||||||
|
$this->getConf()->get(['registry', 'general', 'default-subdef-url-ttl'])
|
||||||
|
);
|
||||||
|
if ($urlTTL < 0) {
|
||||||
|
$urlTTL = -1;
|
||||||
|
}
|
||||||
|
$issuer = $this->getAuthenticator()->getUser();
|
||||||
|
|
||||||
|
return [
|
||||||
|
'name' => $media->get_name(),
|
||||||
|
'permalink' => $permalink,
|
||||||
|
'height' => $media->get_height(),
|
||||||
|
'width' => $media->get_width(),
|
||||||
|
'filesize' => $media->get_size(),
|
||||||
|
'devices' => $media->getDevices(),
|
||||||
|
'player_type' => $media->get_type(),
|
||||||
|
'mime_type' => $media->get_mime(),
|
||||||
|
'substituted' => $media->is_substituted(),
|
||||||
|
'created_on' => $media->get_creation_date()->format(DATE_ATOM),
|
||||||
|
'updated_on' => $media->get_modification_date()->format(DATE_ATOM),
|
||||||
|
'url' => $this->urlgenerator->generate($issuer, $media, $urlTTL),
|
||||||
|
'url_ttl' => $urlTTL,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param media_Permalink_Adapter $permalink
|
||||||
|
* @return array
|
||||||
|
*
|
||||||
|
* @todo fix duplicated code
|
||||||
|
* @noinspection DuplicatedCode
|
||||||
|
*/
|
||||||
|
public function listPermalink(media_Permalink_Adapter $permalink)
|
||||||
|
{
|
||||||
|
$downloadUrl = $permalink->get_url();
|
||||||
|
$downloadUrl->getQuery()->set('download', '1');
|
||||||
|
|
||||||
|
return [
|
||||||
|
'created_on' => $permalink->get_created_on()->format(DATE_ATOM),
|
||||||
|
'id' => $permalink->get_id(),
|
||||||
|
'is_activated' => $permalink->get_is_activated(),
|
||||||
|
'label' => $permalink->get_label(),
|
||||||
|
'updated_on' => $permalink->get_last_modified()->format(DATE_ATOM),
|
||||||
|
'page_url' => $permalink->get_page(),
|
||||||
|
'download_url' => (string)$downloadUrl,
|
||||||
|
'url' => (string)$permalink->get_url(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve detailed information about one record
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param record_adapter $record
|
||||||
|
* @param ACL $aclforuser
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function listRecord(Request $request, record_adapter $record, ACL $aclforuser)
|
||||||
|
{
|
||||||
|
$technicalInformation = [];
|
||||||
|
foreach ($record->get_technical_infos()->getValues() as $name => $value) {
|
||||||
|
$technicalInformation[] = ['name' => $name, 'value' => $value];
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'databox_id' => $record->getDataboxId(),
|
||||||
|
'record_id' => $record->getRecordId(),
|
||||||
|
'mime_type' => $record->getMimeType(),
|
||||||
|
'title' => $record->get_title(),
|
||||||
|
'original_name' => $record->get_original_name(),
|
||||||
|
'updated_on' => $record->getUpdated()->format(DATE_ATOM),
|
||||||
|
'created_on' => $record->getCreated()->format(DATE_ATOM),
|
||||||
|
'collection_id' => $record->getCollectionId(),
|
||||||
|
'base_id' => $record->getBaseId(),
|
||||||
|
'sha256' => $record->getSha256(),
|
||||||
|
'thumbnail' => $this->listEmbeddableMedia($request, $record, $record->get_thumbnail(), $aclforuser),
|
||||||
|
'technical_informations' => $technicalInformation,
|
||||||
|
'phrasea_type' => $record->getType(),
|
||||||
|
'uuid' => $record->getUuid(),
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($request->attributes->get('_extended', false)) {
|
||||||
|
$data = array_merge($data, [
|
||||||
|
'subdefs' => $this->listRecordEmbeddableMedias($request, $record, $aclforuser),
|
||||||
|
'metadata' => $this->listRecordMetadata($record, $aclforuser),
|
||||||
|
'status' => $this->listRecordStatus($record),
|
||||||
|
'caption' => $this->listRecordCaption($record, $aclforuser),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param record_adapter $record
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function listRecordEmbeddableMedias(Request $request, record_adapter $record, ACL $acl)
|
||||||
|
{
|
||||||
|
$subdefs = [];
|
||||||
|
|
||||||
|
foreach ($record->get_embedable_medias([], []) as $name => $media) {
|
||||||
|
if (null !== $subdef = $this->listEmbeddableMedia($request, $record, $media, $acl)) {
|
||||||
|
$subdefs[] = $subdef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $subdefs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List all fields of given record
|
||||||
|
*
|
||||||
|
* @param record_adapter $record
|
||||||
|
* @param ACL $acl
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function listRecordMetadata(record_adapter $record, ACL $acl)
|
||||||
|
{
|
||||||
|
$includeBusiness = $acl->can_see_business_fields($record->getDatabox());
|
||||||
|
|
||||||
|
return $this->listRecordCaptionFields($record->get_caption()->get_fields(null, $includeBusiness));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param caption_field[] $fields
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function listRecordCaptionFields($fields)
|
||||||
|
{
|
||||||
|
$ret = [];
|
||||||
|
|
||||||
|
foreach ($fields as $field) {
|
||||||
|
$databox_field = $field->get_databox_field();
|
||||||
|
|
||||||
|
$fieldData = [
|
||||||
|
'meta_structure_id' => $field->get_meta_struct_id(),
|
||||||
|
'name' => $field->get_name(),
|
||||||
|
'labels' => [
|
||||||
|
'fr' => $databox_field->get_label('fr'),
|
||||||
|
'en' => $databox_field->get_label('en'),
|
||||||
|
'de' => $databox_field->get_label('de'),
|
||||||
|
'nl' => $databox_field->get_label('nl'),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($field->get_values() as $value) {
|
||||||
|
$data = [
|
||||||
|
'meta_id' => $value->getId(),
|
||||||
|
'value' => $value->getValue(),
|
||||||
|
];
|
||||||
|
|
||||||
|
$ret[] = $fieldData + $data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param record_adapter $record
|
||||||
|
* @param ACL $acl
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function listRecordCaption(record_adapter $record, ACL $acl)
|
||||||
|
{
|
||||||
|
$includeBusiness = $acl->can_see_business_fields($record->getDatabox());
|
||||||
|
|
||||||
|
$caption = [];
|
||||||
|
|
||||||
|
foreach ($record->get_caption()->get_fields(null, $includeBusiness) as $field) {
|
||||||
|
$caption[] = [
|
||||||
|
'meta_structure_id' => $field->get_meta_struct_id(),
|
||||||
|
'name' => $field->get_name(),
|
||||||
|
'value' => $field->get_serialized_values(';'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $caption;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////
|
||||||
|
private function getAuthenticator()
|
||||||
|
{
|
||||||
|
return $this->authenticator;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getConf()
|
||||||
|
{
|
||||||
|
return $this->conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,8 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Alchemy\Phrasea\Controller\Api;
|
namespace Alchemy\Phrasea\Controller\Api\V3;
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\Application\Helper\DispatcherAware;
|
||||||
|
use Alchemy\Phrasea\Application\Helper\JsonBodyAware;
|
||||||
use Alchemy\Phrasea\Collection\Reference\CollectionReference;
|
use Alchemy\Phrasea\Collection\Reference\CollectionReference;
|
||||||
|
use Alchemy\Phrasea\Controller\Api\Result;
|
||||||
use Alchemy\Phrasea\Controller\Controller;
|
use Alchemy\Phrasea\Controller\Controller;
|
||||||
use Alchemy\Phrasea\Databox\DataboxGroupable;
|
use Alchemy\Phrasea\Databox\DataboxGroupable;
|
||||||
use Alchemy\Phrasea\Fractal\CallbackTransformer;
|
use Alchemy\Phrasea\Fractal\CallbackTransformer;
|
||||||
@@ -31,34 +34,19 @@ use Alchemy\Phrasea\SearchEngine\SearchEngineInterface;
|
|||||||
use Alchemy\Phrasea\SearchEngine\SearchEngineLogger;
|
use Alchemy\Phrasea\SearchEngine\SearchEngineLogger;
|
||||||
use Alchemy\Phrasea\SearchEngine\SearchEngineOptions;
|
use Alchemy\Phrasea\SearchEngine\SearchEngineOptions;
|
||||||
use Alchemy\Phrasea\SearchEngine\SearchEngineResult;
|
use Alchemy\Phrasea\SearchEngine\SearchEngineResult;
|
||||||
|
use caption_record;
|
||||||
|
use League\Fractal\Manager as FractalManager;
|
||||||
use League\Fractal\Resource\Item;
|
use League\Fractal\Resource\Item;
|
||||||
|
use media_Permalink_Adapter;
|
||||||
|
use media_subdef;
|
||||||
|
use record_adapter;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|
||||||
|
|
||||||
class V3Controller extends Controller
|
class V3SearchController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
use JsonBodyAware;
|
||||||
* Return detailed information about one story
|
use DispatcherAware;
|
||||||
*
|
|
||||||
* @param Request $request
|
|
||||||
* @param int $databox_id
|
|
||||||
* @param int $record_id
|
|
||||||
*
|
|
||||||
* @return Response
|
|
||||||
*/
|
|
||||||
public function getStoryAction(Request $request, $databox_id, $record_id)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$story = $this->findDataboxById($databox_id)->get_record($record_id);
|
|
||||||
|
|
||||||
return Result::create($request, ['story' => $this->listStory($request, $story)])->createResponse();
|
|
||||||
} catch (NotFoundHttpException $e) {
|
|
||||||
return Result::createError($request, 404, $this->app->trans('Story Not Found'))->createResponse();
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
return $this->app['controller.api.v1']->getBadRequestAction($request, $this->app->trans('An error occurred'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search for results
|
* Search for results
|
||||||
@@ -101,7 +89,7 @@ class V3Controller extends Controller
|
|||||||
|
|
||||||
$includeResolver = new IncludeResolver($transformerResolver);
|
$includeResolver = new IncludeResolver($transformerResolver);
|
||||||
|
|
||||||
$fractal = new \League\Fractal\Manager();
|
$fractal = new FractalManager();
|
||||||
$fractal->setSerializer(new TraceableArraySerializer($this->app['dispatcher']));
|
$fractal->setSerializer(new TraceableArraySerializer($this->app['dispatcher']));
|
||||||
$fractal->parseIncludes($this->resolveSearchIncludes($request));
|
$fractal->parseIncludes($this->resolveSearchIncludes($request));
|
||||||
|
|
||||||
@@ -125,314 +113,7 @@ class V3Controller extends Controller
|
|||||||
return Result::create($request, $ret)->createResponse();
|
return Result::create($request, $ret)->createResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve detailed information about one story
|
|
||||||
*
|
|
||||||
* @param Request $request
|
|
||||||
* @param \record_adapter $story
|
|
||||||
* @return array
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
private function listStory(Request $request, \record_adapter $story)
|
|
||||||
{
|
|
||||||
if (!$story->isStory()) {
|
|
||||||
return Result::createError($request, 404, 'Story not found')->createResponse();
|
|
||||||
}
|
|
||||||
|
|
||||||
$per_page = (int)$request->get('per_page')?:10;
|
|
||||||
$page = (int)$request->get('page')?:1;
|
|
||||||
$offset = ($per_page * ($page - 1)) + 1;
|
|
||||||
|
|
||||||
$caption = $story->get_caption();
|
|
||||||
|
|
||||||
$format = function (\caption_record $caption, $dcField) {
|
|
||||||
|
|
||||||
$field = $caption->get_dc_field($dcField);
|
|
||||||
|
|
||||||
if (!$field) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $field->get_serialized_values();
|
|
||||||
};
|
|
||||||
|
|
||||||
return [
|
|
||||||
'@entity@' => V1Controller::OBJECT_TYPE_STORY,
|
|
||||||
'databox_id' => $story->getDataboxId(),
|
|
||||||
'story_id' => $story->getRecordId(),
|
|
||||||
'updated_on' => $story->getUpdated()->format(DATE_ATOM),
|
|
||||||
'created_on' => $story->getCreated()->format(DATE_ATOM),
|
|
||||||
'collection_id' => $story->getCollectionId(),
|
|
||||||
'base_id' => $story->getBaseId(),
|
|
||||||
'thumbnail' => $this->listEmbeddableMedia($request, $story, $story->get_thumbnail()),
|
|
||||||
'uuid' => $story->getUuid(),
|
|
||||||
'metadatas' => [
|
|
||||||
'@entity@' => V1Controller::OBJECT_TYPE_STORY_METADATA_BAG,
|
|
||||||
'dc:contributor' => $format($caption, \databox_Field_DCESAbstract::Contributor),
|
|
||||||
'dc:coverage' => $format($caption, \databox_Field_DCESAbstract::Coverage),
|
|
||||||
'dc:creator' => $format($caption, \databox_Field_DCESAbstract::Creator),
|
|
||||||
'dc:date' => $format($caption, \databox_Field_DCESAbstract::Date),
|
|
||||||
'dc:description' => $format($caption, \databox_Field_DCESAbstract::Description),
|
|
||||||
'dc:format' => $format($caption, \databox_Field_DCESAbstract::Format),
|
|
||||||
'dc:identifier' => $format($caption, \databox_Field_DCESAbstract::Identifier),
|
|
||||||
'dc:language' => $format($caption, \databox_Field_DCESAbstract::Language),
|
|
||||||
'dc:publisher' => $format($caption, \databox_Field_DCESAbstract::Publisher),
|
|
||||||
'dc:relation' => $format($caption, \databox_Field_DCESAbstract::Relation),
|
|
||||||
'dc:rights' => $format($caption, \databox_Field_DCESAbstract::Rights),
|
|
||||||
'dc:source' => $format($caption, \databox_Field_DCESAbstract::Source),
|
|
||||||
'dc:subject' => $format($caption, \databox_Field_DCESAbstract::Subject),
|
|
||||||
'dc:title' => $format($caption, \databox_Field_DCESAbstract::Title),
|
|
||||||
'dc:type' => $format($caption, \databox_Field_DCESAbstract::Type),
|
|
||||||
],
|
|
||||||
'records' => $this->listRecords($request, array_values($story->getChildren($offset, $per_page)->get_elements())),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
private function listEmbeddableMedia(Request $request, \record_adapter $record, \media_subdef $media)
|
|
||||||
{
|
|
||||||
if (!$media->is_physically_present()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->getAuthenticator()->isAuthenticated()) {
|
|
||||||
$acl = $this->getAclForUser();
|
|
||||||
if ($media->get_name() !== 'document'
|
|
||||||
&& false === $acl->has_access_to_subdef($record, $media->get_name())
|
|
||||||
) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if ($media->get_name() === 'document'
|
|
||||||
&& !$acl->has_right_on_base($record->getBaseId(), \ACL::CANDWNLDHD)
|
|
||||||
&& !$acl->has_hd_grant($record)
|
|
||||||
) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($media->get_permalink() instanceof \media_Permalink_Adapter) {
|
|
||||||
$permalink = $this->listPermalink($media->get_permalink());
|
|
||||||
} else {
|
|
||||||
$permalink = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$urlTTL = (int) $request->get(
|
|
||||||
'subdef_url_ttl',
|
|
||||||
$this->getConf()->get(['registry', 'general', 'default-subdef-url-ttl'])
|
|
||||||
);
|
|
||||||
if ($urlTTL < 0) {
|
|
||||||
$urlTTL = -1;
|
|
||||||
}
|
|
||||||
$issuer = $this->getAuthenticatedUser();
|
|
||||||
|
|
||||||
return [
|
|
||||||
'name' => $media->get_name(),
|
|
||||||
'permalink' => $permalink,
|
|
||||||
'height' => $media->get_height(),
|
|
||||||
'width' => $media->get_width(),
|
|
||||||
'filesize' => $media->get_size(),
|
|
||||||
'devices' => $media->getDevices(),
|
|
||||||
'player_type' => $media->get_type(),
|
|
||||||
'mime_type' => $media->get_mime(),
|
|
||||||
'substituted' => $media->is_substituted(),
|
|
||||||
'created_on' => $media->get_creation_date()->format(DATE_ATOM),
|
|
||||||
'updated_on' => $media->get_modification_date()->format(DATE_ATOM),
|
|
||||||
'url' => $this->app['media_accessor.subdef_url_generator']->generate($issuer, $media, $urlTTL),
|
|
||||||
'url_ttl' => $urlTTL,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
private function listPermalink(\media_Permalink_Adapter $permalink)
|
|
||||||
{
|
|
||||||
$downloadUrl = $permalink->get_url();
|
|
||||||
$downloadUrl->getQuery()->set('download', '1');
|
|
||||||
|
|
||||||
return [
|
|
||||||
'created_on' => $permalink->get_created_on()->format(DATE_ATOM),
|
|
||||||
'id' => $permalink->get_id(),
|
|
||||||
'is_activated' => $permalink->get_is_activated(),
|
|
||||||
/** @Ignore */
|
|
||||||
'label' => $permalink->get_label(),
|
|
||||||
'updated_on' => $permalink->get_last_modified()->format(DATE_ATOM),
|
|
||||||
'page_url' => $permalink->get_page(),
|
|
||||||
'download_url' => (string)$downloadUrl,
|
|
||||||
'url' => (string)$permalink->get_url(),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Request $request
|
|
||||||
* @param RecordReferenceInterface[]|RecordReferenceCollection $records
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function listRecords(Request $request, $records)
|
|
||||||
{
|
|
||||||
if (!$records instanceof RecordReferenceCollection) {
|
|
||||||
$records = new RecordReferenceCollection($records);
|
|
||||||
}
|
|
||||||
|
|
||||||
$technicalData = $this->app['service.technical_data']->fetchRecordsTechnicalData($records);
|
|
||||||
|
|
||||||
$data = [];
|
|
||||||
|
|
||||||
foreach ($records->toRecords($this->getApplicationBox()) as $index => $record) {
|
|
||||||
$record->setTechnicalDataSet($technicalData[$index]);
|
|
||||||
|
|
||||||
$data[$index] = $this->listRecord($request, $record);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve detailed information about one record
|
|
||||||
*
|
|
||||||
* @param Request $request
|
|
||||||
* @param \record_adapter $record
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function listRecord(Request $request, \record_adapter $record)
|
|
||||||
{
|
|
||||||
$technicalInformation = [];
|
|
||||||
foreach ($record->get_technical_infos()->getValues() as $name => $value) {
|
|
||||||
$technicalInformation[] = ['name' => $name, 'value' => $value];
|
|
||||||
}
|
|
||||||
|
|
||||||
$data = [
|
|
||||||
'databox_id' => $record->getDataboxId(),
|
|
||||||
'record_id' => $record->getRecordId(),
|
|
||||||
'mime_type' => $record->getMimeType(),
|
|
||||||
'title' => $record->get_title(),
|
|
||||||
'original_name' => $record->get_original_name(),
|
|
||||||
'updated_on' => $record->getUpdated()->format(DATE_ATOM),
|
|
||||||
'created_on' => $record->getCreated()->format(DATE_ATOM),
|
|
||||||
'collection_id' => $record->getCollectionId(),
|
|
||||||
'base_id' => $record->getBaseId(),
|
|
||||||
'sha256' => $record->getSha256(),
|
|
||||||
'thumbnail' => $this->listEmbeddableMedia($request, $record, $record->get_thumbnail()),
|
|
||||||
'technical_informations' => $technicalInformation,
|
|
||||||
'phrasea_type' => $record->getType(),
|
|
||||||
'uuid' => $record->getUuid(),
|
|
||||||
];
|
|
||||||
|
|
||||||
if ($request->attributes->get('_extended', false)) {
|
|
||||||
$data = array_merge($data, [
|
|
||||||
'subdefs' => $this->listRecordEmbeddableMedias($request, $record),
|
|
||||||
'metadata' => $this->listRecordMetadata($record),
|
|
||||||
'status' => $this->listRecordStatus($record),
|
|
||||||
'caption' => $this->listRecordCaption($record),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Request $request
|
|
||||||
* @param \record_adapter $record
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function listRecordEmbeddableMedias(Request $request, \record_adapter $record)
|
|
||||||
{
|
|
||||||
$subdefs = [];
|
|
||||||
|
|
||||||
foreach ($record->get_embedable_medias([], []) as $name => $media) {
|
|
||||||
if (null !== $subdef = $this->listEmbeddableMedia($request, $record, $media)) {
|
|
||||||
$subdefs[] = $subdef;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $subdefs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List all fields of given record
|
|
||||||
*
|
|
||||||
* @param \record_adapter $record
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function listRecordMetadata(\record_adapter $record)
|
|
||||||
{
|
|
||||||
$includeBusiness = $this->getAclForUser()->can_see_business_fields($record->getDatabox());
|
|
||||||
|
|
||||||
return $this->listRecordCaptionFields($record->get_caption()->get_fields(null, $includeBusiness));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \caption_field[] $fields
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function listRecordCaptionFields($fields)
|
|
||||||
{
|
|
||||||
$ret = [];
|
|
||||||
|
|
||||||
foreach ($fields as $field) {
|
|
||||||
$databox_field = $field->get_databox_field();
|
|
||||||
|
|
||||||
$fieldData = [
|
|
||||||
'meta_structure_id' => $field->get_meta_struct_id(),
|
|
||||||
'name' => $field->get_name(),
|
|
||||||
'labels' => [
|
|
||||||
'fr' => $databox_field->get_label('fr'),
|
|
||||||
'en' => $databox_field->get_label('en'),
|
|
||||||
'de' => $databox_field->get_label('de'),
|
|
||||||
'nl' => $databox_field->get_label('nl'),
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($field->get_values() as $value) {
|
|
||||||
$data = [
|
|
||||||
'meta_id' => $value->getId(),
|
|
||||||
'value' => $value->getValue(),
|
|
||||||
];
|
|
||||||
|
|
||||||
$ret[] = $fieldData + $data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve detailed information about one status
|
|
||||||
*
|
|
||||||
* @param \record_adapter $record
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function listRecordStatus(\record_adapter $record)
|
|
||||||
{
|
|
||||||
$ret = [];
|
|
||||||
foreach ($record->getStatusStructure() as $bit => $status) {
|
|
||||||
$ret[] = [
|
|
||||||
'bit' => $bit,
|
|
||||||
'state' => \databox_status::bitIsSet($record->getStatusBitField(), $bit),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \record_adapter $record
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function listRecordCaption(\record_adapter $record)
|
|
||||||
{
|
|
||||||
$includeBusiness = $this->getAclForUser()->can_see_business_fields($record->getDatabox());
|
|
||||||
|
|
||||||
$caption = [];
|
|
||||||
|
|
||||||
foreach ($record->get_caption()->get_fields(null, $includeBusiness) as $field) {
|
|
||||||
$caption[] = [
|
|
||||||
'meta_structure_id' => $field->get_meta_struct_id(),
|
|
||||||
'name' => $field->get_name(),
|
|
||||||
'value' => $field->get_serialized_values(';'),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $caption;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns requested includes
|
* Returns requested includes
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
@@ -660,7 +341,7 @@ class V3Controller extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param RecordCollection|\record_adapter[] $references
|
* @param RecordCollection|record_adapter[] $references
|
||||||
* @return RecordView[]
|
* @return RecordView[]
|
||||||
*/
|
*/
|
||||||
private function buildRecordViews($references)
|
private function buildRecordViews($references)
|
||||||
@@ -693,7 +374,7 @@ class V3Controller extends Controller
|
|||||||
|
|
||||||
foreach ($subdefGroups as $index => $subdefGroup) {
|
foreach ($subdefGroups as $index => $subdefGroup) {
|
||||||
if (!isset($subdefGroup['thumbnail'])) {
|
if (!isset($subdefGroup['thumbnail'])) {
|
||||||
$fakeSubdef = new \media_subdef($this->app, $references[$index], 'thumbnail', true, []);
|
$fakeSubdef = new media_subdef($this->app, $references[$index], 'thumbnail', true, []);
|
||||||
$fakeSubdefs[spl_object_hash($fakeSubdef)] = $fakeSubdef;
|
$fakeSubdefs[spl_object_hash($fakeSubdef)] = $fakeSubdef;
|
||||||
|
|
||||||
$subdefGroups[$index]['thumbnail'] = $fakeSubdef;
|
$subdefGroups[$index]['thumbnail'] = $fakeSubdef;
|
||||||
@@ -701,9 +382,9 @@ class V3Controller extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
$allSubdefs = $this->mergeGroupsIntoOneList($subdefGroups);
|
$allSubdefs = $this->mergeGroupsIntoOneList($subdefGroups);
|
||||||
$allPermalinks = \media_Permalink_Adapter::getMany(
|
$allPermalinks = media_Permalink_Adapter::getMany(
|
||||||
$this->app,
|
$this->app,
|
||||||
array_filter($allSubdefs, function (\media_subdef $subdef) use ($fakeSubdefs) {
|
array_filter($allSubdefs, function (media_subdef $subdef) use ($fakeSubdefs) {
|
||||||
return !isset($fakeSubdefs[spl_object_hash($subdef)]);
|
return !isset($fakeSubdefs[spl_object_hash($subdef)]);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -712,7 +393,7 @@ class V3Controller extends Controller
|
|||||||
|
|
||||||
$subdefViews = [];
|
$subdefViews = [];
|
||||||
|
|
||||||
/** @var \media_subdef $subdef */
|
/** @var media_subdef $subdef */
|
||||||
foreach ($allSubdefs as $index => $subdef) {
|
foreach ($allSubdefs as $index => $subdef) {
|
||||||
$subdefView = new SubdefView($subdef);
|
$subdefView = new SubdefView($subdef);
|
||||||
|
|
||||||
@@ -728,7 +409,7 @@ class V3Controller extends Controller
|
|||||||
|
|
||||||
$reorderedGroups = [];
|
$reorderedGroups = [];
|
||||||
|
|
||||||
/** @var \media_subdef[] $subdefGroup */
|
/** @var media_subdef[] $subdefGroup */
|
||||||
foreach ($subdefGroups as $index => $subdefGroup) {
|
foreach ($subdefGroups as $index => $subdefGroup) {
|
||||||
$reordered = [];
|
$reordered = [];
|
||||||
|
|
||||||
@@ -789,7 +470,7 @@ class V3Controller extends Controller
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param RecordView[] $recordViews
|
* @param RecordView[] $recordViews
|
||||||
* @param \caption_record[] $captions
|
* @param caption_record[] $captions
|
||||||
* @param bool[] $canSeeBusiness
|
* @param bool[] $canSeeBusiness
|
||||||
*/
|
*/
|
||||||
private function buildCaptionViews($recordViews, $captions, $canSeeBusiness)
|
private function buildCaptionViews($recordViews, $captions, $canSeeBusiness)
|
146
lib/Alchemy/Phrasea/Controller/Api/V3/V3StoriesController.php
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Alchemy\Phrasea\Controller\Api\V3;
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\Application\Helper\DispatcherAware;
|
||||||
|
use Alchemy\Phrasea\Application\Helper\JsonBodyAware;
|
||||||
|
use Alchemy\Phrasea\Controller\Api\Result;
|
||||||
|
use Alchemy\Phrasea\Controller\Api\V1Controller;
|
||||||
|
use Alchemy\Phrasea\Controller\Controller;
|
||||||
|
use Alchemy\Phrasea\Model\RecordReferenceInterface;
|
||||||
|
use Alchemy\Phrasea\Record\RecordReferenceCollection;
|
||||||
|
use caption_record;
|
||||||
|
use databox_Field_DCESAbstract;
|
||||||
|
use Exception;
|
||||||
|
use record_adapter;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
|
|
||||||
|
|
||||||
|
class V3StoriesController extends Controller
|
||||||
|
{
|
||||||
|
use JsonBodyAware;
|
||||||
|
use DispatcherAware;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return detailed information about one story
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param int $databox_id
|
||||||
|
* @param int $record_id
|
||||||
|
*
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
public function getStoryAction(Request $request, $databox_id, $record_id)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$story = $this->findDataboxById($databox_id)->get_record($record_id);
|
||||||
|
|
||||||
|
return Result::create($request, ['story' => $this->listStory($request, $story)])->createResponse();
|
||||||
|
}
|
||||||
|
catch (NotFoundHttpException $e) {
|
||||||
|
return Result::createError($request, 404, 'Story Not Found')->createResponse();
|
||||||
|
}
|
||||||
|
catch (Exception $e) {
|
||||||
|
return $this->app['controller.api.v1']->getBadRequestAction($request, 'An error occurred');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve detailed information about one story
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param record_adapter $story
|
||||||
|
* @return array
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private function listStory(Request $request, record_adapter $story)
|
||||||
|
{
|
||||||
|
if (!$story->isStory()) {
|
||||||
|
return Result::createError($request, 404, 'Story not found')->createResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
$per_page = (int)$request->get('per_page')?:10;
|
||||||
|
$page = (int)$request->get('page')?:1;
|
||||||
|
$offset = ($per_page * ($page - 1)) + 1;
|
||||||
|
|
||||||
|
$caption = $story->get_caption();
|
||||||
|
|
||||||
|
$format = function (caption_record $caption, $dcField) {
|
||||||
|
|
||||||
|
$field = $caption->get_dc_field($dcField);
|
||||||
|
|
||||||
|
if (!$field) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $field->get_serialized_values();
|
||||||
|
};
|
||||||
|
|
||||||
|
return [
|
||||||
|
'@entity@' => V1Controller::OBJECT_TYPE_STORY,
|
||||||
|
'databox_id' => $story->getDataboxId(),
|
||||||
|
'story_id' => $story->getRecordId(),
|
||||||
|
'updated_on' => $story->getUpdated()->format(DATE_ATOM),
|
||||||
|
'created_on' => $story->getCreated()->format(DATE_ATOM),
|
||||||
|
'collection_id' => $story->getCollectionId(),
|
||||||
|
'base_id' => $story->getBaseId(),
|
||||||
|
'thumbnail' => $this->getResultHelpers()->listEmbeddableMedia($request, $story, $story->get_thumbnail(), $this->getAclForUser()),
|
||||||
|
'uuid' => $story->getUuid(),
|
||||||
|
'metadatas' => [
|
||||||
|
'@entity@' => V1Controller::OBJECT_TYPE_STORY_METADATA_BAG,
|
||||||
|
'dc:contributor' => $format($caption, databox_Field_DCESAbstract::Contributor),
|
||||||
|
'dc:coverage' => $format($caption, databox_Field_DCESAbstract::Coverage),
|
||||||
|
'dc:creator' => $format($caption, databox_Field_DCESAbstract::Creator),
|
||||||
|
'dc:date' => $format($caption, databox_Field_DCESAbstract::Date),
|
||||||
|
'dc:description' => $format($caption, databox_Field_DCESAbstract::Description),
|
||||||
|
'dc:format' => $format($caption, databox_Field_DCESAbstract::Format),
|
||||||
|
'dc:identifier' => $format($caption, databox_Field_DCESAbstract::Identifier),
|
||||||
|
'dc:language' => $format($caption, databox_Field_DCESAbstract::Language),
|
||||||
|
'dc:publisher' => $format($caption, databox_Field_DCESAbstract::Publisher),
|
||||||
|
'dc:relation' => $format($caption, databox_Field_DCESAbstract::Relation),
|
||||||
|
'dc:rights' => $format($caption, databox_Field_DCESAbstract::Rights),
|
||||||
|
'dc:source' => $format($caption, databox_Field_DCESAbstract::Source),
|
||||||
|
'dc:subject' => $format($caption, databox_Field_DCESAbstract::Subject),
|
||||||
|
'dc:title' => $format($caption, databox_Field_DCESAbstract::Title),
|
||||||
|
'dc:type' => $format($caption, databox_Field_DCESAbstract::Type),
|
||||||
|
],
|
||||||
|
'records' => $this->listRecords($request, array_values($story->getChildren($offset, $per_page)->get_elements())),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param RecordReferenceInterface[]|RecordReferenceCollection $records
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function listRecords(Request $request, $records)
|
||||||
|
{
|
||||||
|
if (!$records instanceof RecordReferenceCollection) {
|
||||||
|
$records = new RecordReferenceCollection($records);
|
||||||
|
}
|
||||||
|
|
||||||
|
$technicalData = $this->app['service.technical_data']->fetchRecordsTechnicalData($records);
|
||||||
|
|
||||||
|
$data = [];
|
||||||
|
|
||||||
|
foreach ($records->toRecords($this->getApplicationBox()) as $index => $record) {
|
||||||
|
$record->setTechnicalDataSet($technicalData[$index]);
|
||||||
|
|
||||||
|
$data[$index] = $this->getResultHelpers()->listRecord($request, $record, $this->getAclForUser());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return V3ResultHelpers
|
||||||
|
*/
|
||||||
|
private function getResultHelpers()
|
||||||
|
{
|
||||||
|
return $this->app['controller.api.v3.resulthelpers'];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -155,6 +155,8 @@ class LanguageController
|
|||||||
'description notice' => $translator->trans('prod:mapboxgl: description notice'),
|
'description notice' => $translator->trans('prod:mapboxgl: description notice'),
|
||||||
'title-map-dialog' => $translator->trans('prod:mapboxgl: title map dialog'),
|
'title-map-dialog' => $translator->trans('prod:mapboxgl: title map dialog'),
|
||||||
'create new user' => $translator->trans('prod:push: create new user'),
|
'create new user' => $translator->trans('prod:push: create new user'),
|
||||||
|
'prod:videoeditor:subtitletab:message:: error' => $translator->trans('prod:videoeditor:subtitletab:message:: error'),
|
||||||
|
'prod:videoeditor:subtitletab:message:: success' => $translator->trans('prod:videoeditor:subtitletab:message:: success'),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -115,13 +115,13 @@ class MoveCollectionController extends Controller
|
|||||||
|
|
||||||
foreach ($records as $record) {
|
foreach ($records as $record) {
|
||||||
$oldCollectionId = $record->getCollection()->get_coll_id();
|
$oldCollectionId = $record->getCollection()->get_coll_id();
|
||||||
$record->move_to_collection($collection, $this->getApplicationBox());
|
$record->move_to_collection($collection);
|
||||||
|
|
||||||
if ($request->request->get("chg_coll_son") == "1") {
|
if ($request->request->get("chg_coll_son") == "1") {
|
||||||
/** @var \record_adapter $child */
|
/** @var \record_adapter $child */
|
||||||
foreach ($record->getChildren() as $child) {
|
foreach ($record->getChildren() as $child) {
|
||||||
if ($this->getAclForUser()->has_right_on_base($child->getBaseId(), \ACL::CANDELETERECORD)) {
|
if ($this->getAclForUser()->has_right_on_base($child->getBaseId(), \ACL::CANDELETERECORD)) {
|
||||||
$child->move_to_collection($collection, $this->getApplicationBox());
|
$child->move_to_collection($collection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -242,7 +242,7 @@ class RecordController extends Controller
|
|||||||
$this->getEventDispatcher()->dispatch(RecordEvents::DELETE, new DeleteEvent($record));
|
$this->getEventDispatcher()->dispatch(RecordEvents::DELETE, new DeleteEvent($record));
|
||||||
} else {
|
} else {
|
||||||
// move to trash collection
|
// move to trash collection
|
||||||
$record->move_to_collection($trashCollectionsBySbasId[$sbasId], $this->getApplicationBox());
|
$record->move_to_collection($trashCollectionsBySbasId[$sbasId]);
|
||||||
// disable permalinks
|
// disable permalinks
|
||||||
foreach($record->get_subdefs() as $subdef) {
|
foreach($record->get_subdefs() as $subdef) {
|
||||||
if( ($pl = $subdef->get_permalink()) ) {
|
if( ($pl = $subdef->get_permalink()) ) {
|
||||||
|
@@ -15,8 +15,10 @@ use Alchemy\Phrasea\Application\Helper\FilesystemAware;
|
|||||||
use Alchemy\Phrasea\Application\Helper\SubDefinitionSubstituerAware;
|
use Alchemy\Phrasea\Application\Helper\SubDefinitionSubstituerAware;
|
||||||
use Alchemy\Phrasea\Controller\Controller;
|
use Alchemy\Phrasea\Controller\Controller;
|
||||||
use Alchemy\Phrasea\Controller\RecordsRequest;
|
use Alchemy\Phrasea\Controller\RecordsRequest;
|
||||||
|
use Alchemy\Phrasea\Core\Event\Record\RecordAutoSubtitleEvent;
|
||||||
use Alchemy\Phrasea\Core\Event\Record\RecordEvents;
|
use Alchemy\Phrasea\Core\Event\Record\RecordEvents;
|
||||||
use Alchemy\Phrasea\Core\Event\Record\SubdefinitionCreateEvent;
|
use Alchemy\Phrasea\Core\Event\Record\SubdefinitionCreateEvent;
|
||||||
|
use Alchemy\Phrasea\Core\PhraseaEvents;
|
||||||
use Alchemy\Phrasea\Exception\RuntimeException;
|
use Alchemy\Phrasea\Exception\RuntimeException;
|
||||||
use Alchemy\Phrasea\Metadata\PhraseanetMetadataReader;
|
use Alchemy\Phrasea\Metadata\PhraseanetMetadataReader;
|
||||||
use Alchemy\Phrasea\Metadata\PhraseanetMetadataSetter;
|
use Alchemy\Phrasea\Metadata\PhraseanetMetadataSetter;
|
||||||
@@ -24,7 +26,6 @@ use Alchemy\Phrasea\Record\RecordWasRotated;
|
|||||||
use DataURI\Parser;
|
use DataURI\Parser;
|
||||||
use MediaAlchemyst\Alchemyst;
|
use MediaAlchemyst\Alchemyst;
|
||||||
use MediaVorus\MediaVorus;
|
use MediaVorus\MediaVorus;
|
||||||
use PHPExiftool\Reader;
|
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
|
||||||
class ToolsController extends Controller
|
class ToolsController extends Controller
|
||||||
@@ -45,7 +46,6 @@ class ToolsController extends Controller
|
|||||||
if (count($records) == 1) {
|
if (count($records) == 1) {
|
||||||
/** @var \record_adapter $record */
|
/** @var \record_adapter $record */
|
||||||
$record = $records->first();
|
$record = $records->first();
|
||||||
$databox = $record->getDatabox();
|
|
||||||
|
|
||||||
/**Array list of subdefs**/
|
/**Array list of subdefs**/
|
||||||
$listsubdef = array_keys($record-> get_subdefs());
|
$listsubdef = array_keys($record-> get_subdefs());
|
||||||
@@ -88,14 +88,13 @@ class ToolsController extends Controller
|
|||||||
$metadatas = true;
|
$metadatas = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$conf = $this->getConf();
|
|
||||||
|
|
||||||
return $this->render('prod/actions/Tools/index.html.twig', [
|
return $this->render('prod/actions/Tools/index.html.twig', [
|
||||||
'records' => $records,
|
'records' => $records,
|
||||||
'record' => $record,
|
'record' => $record,
|
||||||
'recordSubdefs' => $recordAccessibleSubdefs,
|
'recordSubdefs' => $recordAccessibleSubdefs,
|
||||||
'metadatas' => $metadatas,
|
'metadatas' => $metadatas,
|
||||||
'listsubdef' => $listsubdef
|
'listsubdef' => $listsubdef
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,6 +117,7 @@ class ToolsController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
foreach ($records as $record) {
|
foreach ($records as $record) {
|
||||||
|
/** @var \media_subdef $subdef */
|
||||||
foreach ($record->get_subdefs() as $subdef) {
|
foreach ($record->get_subdefs() as $subdef) {
|
||||||
if ($subdef->get_type() !== \media_subdef::TYPE_IMAGE) {
|
if ($subdef->get_type() !== \media_subdef::TYPE_IMAGE) {
|
||||||
continue;
|
continue;
|
||||||
@@ -146,6 +146,7 @@ class ToolsController extends Controller
|
|||||||
|
|
||||||
foreach ($selection as $record) {
|
foreach ($selection as $record) {
|
||||||
$substituted = false;
|
$substituted = false;
|
||||||
|
/** @var \media_subdef $subdef */
|
||||||
foreach ($record->get_subdefs() as $subdef) {
|
foreach ($record->get_subdefs() as $subdef) {
|
||||||
if ($subdef->is_substituted()) {
|
if ($subdef->is_substituted()) {
|
||||||
$substituted = true;
|
$substituted = true;
|
||||||
@@ -362,14 +363,6 @@ class ToolsController extends Controller
|
|||||||
return $this->app->json($return);
|
return $this->app->json($return);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Reader
|
|
||||||
*/
|
|
||||||
private function getExifToolReader()
|
|
||||||
{
|
|
||||||
return $this->app['exiftool.reader'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Alchemyst
|
* @return Alchemyst
|
||||||
*/
|
*/
|
||||||
@@ -449,13 +442,45 @@ class ToolsController extends Controller
|
|||||||
try {
|
try {
|
||||||
$record->set_metadatas($metadatas);
|
$record->set_metadatas($metadatas);
|
||||||
}
|
}
|
||||||
catch (Exception $e) {
|
catch (\Exception $e) {
|
||||||
return $this->app->json(['success' => false, 'errorMessage' => $e->getMessage()]);
|
return $this->app->json(['success' => false, 'errorMessage' => $e->getMessage()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->app->json(['success' => true, 'errorMessage' => '']);
|
return $this->app->json(['success' => true, 'errorMessage' => '']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function autoSubtitleAction(Request $request)
|
||||||
|
{
|
||||||
|
$record = new \record_adapter($this->app,
|
||||||
|
(int)$request->request->get("databox_id"),
|
||||||
|
(int)$request->request->get("record_id")
|
||||||
|
);
|
||||||
|
|
||||||
|
$permalinkUrl = '';
|
||||||
|
$conf = $this->getConf();
|
||||||
|
|
||||||
|
// if subdef_source not set, by default use the preview permalink
|
||||||
|
$subdefSource = $conf->get(['externalservice', 'ginger', 'AutoSubtitling', 'subdef_source']) ?: 'preview';
|
||||||
|
|
||||||
|
if ($this->isPhysicallyPresent($record, $subdefSource) && ($previewLink = $record->get_subdef($subdefSource)->get_permalink()) != null) {
|
||||||
|
$permalinkUrl = $previewLink->get_url()->__toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->dispatch(
|
||||||
|
PhraseaEvents::RECORD_AUTO_SUBTITLE,
|
||||||
|
new RecordAutoSubtitleEvent(
|
||||||
|
$record,
|
||||||
|
$permalinkUrl,
|
||||||
|
$request->request->get("subtitle_language_source"),
|
||||||
|
$request->request->get("meta_struct_id_source"),
|
||||||
|
$request->request->get("subtitle_language_destination"),
|
||||||
|
$request->request->get("meta_struct_id_destination")
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this->app->json(["status" => "dispatch"]);
|
||||||
|
}
|
||||||
|
|
||||||
public function videoEditorAction(Request $request)
|
public function videoEditorAction(Request $request)
|
||||||
{
|
{
|
||||||
$records = RecordsRequest::fromRequest($this->app, $request, false);
|
$records = RecordsRequest::fromRequest($this->app, $request, false);
|
||||||
@@ -463,6 +488,7 @@ class ToolsController extends Controller
|
|||||||
$metadatas = false;
|
$metadatas = false;
|
||||||
$record = null;
|
$record = null;
|
||||||
$JSFields = [];
|
$JSFields = [];
|
||||||
|
$videoTextTrackFields = [];
|
||||||
|
|
||||||
if (count($records) == 1) {
|
if (count($records) == 1) {
|
||||||
/** @var \record_adapter $record */
|
/** @var \record_adapter $record */
|
||||||
@@ -480,6 +506,19 @@ class ToolsController extends Controller
|
|||||||
'name' => $meta->get_name(),
|
'name' => $meta->get_name(),
|
||||||
'_value' => $record->getCaption([$meta->get_name()]),
|
'_value' => $record->getCaption([$meta->get_name()]),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if (preg_match('/^VideoTextTrack(.*)$/iu', $meta->get_name(), $matches) && !empty($matches[1]) && strlen($matches[1]) == 2 ) {
|
||||||
|
$field['label'] = $matches[1];
|
||||||
|
$field['meta_struct_id'] = $meta->get_id();
|
||||||
|
$field['value'] = '';
|
||||||
|
if ($record->get_caption()->has_field($meta->get_name())) {
|
||||||
|
$fieldValues = $record->get_caption()->get_field($meta->get_name())->get_values();
|
||||||
|
$fieldValue = array_pop($fieldValues);
|
||||||
|
$field['value'] = $fieldValue->getValue();
|
||||||
|
}
|
||||||
|
$videoTextTrackFields[$meta->get_id()] = $field;
|
||||||
|
unset($field);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$record->isStory()) {
|
if (!$record->isStory()) {
|
||||||
@@ -489,11 +528,23 @@ class ToolsController extends Controller
|
|||||||
$conf = $this->getConf();
|
$conf = $this->getConf();
|
||||||
|
|
||||||
return $this->render('prod/actions/Tools/videoEditor.html.twig', [
|
return $this->render('prod/actions/Tools/videoEditor.html.twig', [
|
||||||
'records' => $records,
|
'records' => $records,
|
||||||
'record' => $record,
|
'record' => $record,
|
||||||
'videoEditorConfig' => $conf->get(['video-editor']),
|
'videoEditorConfig' => $conf->get(['video-editor']),
|
||||||
'metadatas' => $metadatas,
|
'metadatas' => $metadatas,
|
||||||
'JSonFields' => json_encode($JSFields),
|
'JSonFields' => json_encode($JSFields),
|
||||||
|
'videoTextTrackFields' => $videoTextTrackFields
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function isPhysicallyPresent(\record_adapter $record, $subdefName)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return $record->get_subdef($subdefName)->is_physically_present();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
unset($e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -13,6 +13,9 @@ use Alchemy\Phrasea\Application\Helper\DispatcherAware;
|
|||||||
use Alchemy\Phrasea\Controller\Controller;
|
use Alchemy\Phrasea\Controller\Controller;
|
||||||
use Alchemy\Phrasea\Core\Event\Thesaurus as ThesaurusEvent;
|
use Alchemy\Phrasea\Core\Event\Thesaurus as ThesaurusEvent;
|
||||||
use Alchemy\Phrasea\Core\Event\Thesaurus\ThesaurusEvents;
|
use Alchemy\Phrasea\Core\Event\Thesaurus\ThesaurusEvents;
|
||||||
|
use Alchemy\Phrasea\SearchEngine\Elastic\ElasticsearchOptions;
|
||||||
|
use Alchemy\Phrasea\WorkerManager\Event\PopulateIndexEvent;
|
||||||
|
use Alchemy\Phrasea\WorkerManager\Event\WorkerEvents;
|
||||||
use Doctrine\DBAL\Driver\Connection;
|
use Doctrine\DBAL\Driver\Connection;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
@@ -1222,6 +1225,26 @@ class ThesaurusController extends Controller
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Order to populate databox
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return \Symfony\Component\HttpFoundation\JsonResponse
|
||||||
|
*/
|
||||||
|
public function populate(Request $request)
|
||||||
|
{
|
||||||
|
$options = $this->getElasticsearchOptions();
|
||||||
|
|
||||||
|
$data['host'] = $options->getHost();
|
||||||
|
$data['port'] = $options->getPort();
|
||||||
|
$data['indexName'] = $options->getIndexName();
|
||||||
|
$data['databoxIds'] = [$request->get('databox_id')];
|
||||||
|
|
||||||
|
$this->getDispatcher()->dispatch(WorkerEvents::POPULATE_INDEX, new PopulateIndexEvent($data));
|
||||||
|
|
||||||
|
return $this->app->json(["status" => "success"]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @return Response
|
* @return Response
|
||||||
@@ -3031,4 +3054,12 @@ class ThesaurusController extends Controller
|
|||||||
{
|
{
|
||||||
return $this->app['locales.available'];
|
return $this->app['locales.available'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return ElasticsearchOptions
|
||||||
|
*/
|
||||||
|
private function getElasticsearchOptions()
|
||||||
|
{
|
||||||
|
return $this->app['elasticsearch.options'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,21 +3,41 @@
|
|||||||
namespace Alchemy\Phrasea\ControllerProvider\Api;
|
namespace Alchemy\Phrasea\ControllerProvider\Api;
|
||||||
|
|
||||||
use Alchemy\Phrasea\Application as PhraseaApplication;
|
use Alchemy\Phrasea\Application as PhraseaApplication;
|
||||||
use Alchemy\Phrasea\Controller\Api\V3Controller;
|
use Alchemy\Phrasea\Controller\Api\V3\V3RecordController;
|
||||||
|
use Alchemy\Phrasea\Controller\Api\V3\V3ResultHelpers;
|
||||||
|
use Alchemy\Phrasea\Controller\Api\V3\V3SearchController;
|
||||||
|
use Alchemy\Phrasea\Controller\Api\V3\V3StoriesController;
|
||||||
use Alchemy\Phrasea\Core\Event\Listener\OAuthListener;
|
use Alchemy\Phrasea\Core\Event\Listener\OAuthListener;
|
||||||
use Silex\Application;
|
use Silex\Application;
|
||||||
use Silex\ControllerCollection;
|
use Silex\ControllerCollection;
|
||||||
use Silex\ControllerProviderInterface;
|
use Silex\ControllerProviderInterface;
|
||||||
use Silex\ServiceProviderInterface;
|
use Silex\ServiceProviderInterface;
|
||||||
|
|
||||||
|
|
||||||
class V3 extends Api implements ControllerProviderInterface, ServiceProviderInterface
|
class V3 extends Api implements ControllerProviderInterface, ServiceProviderInterface
|
||||||
{
|
{
|
||||||
const VERSION = '3.0.0';
|
const VERSION = '3.0.0';
|
||||||
|
|
||||||
public function register(Application $app)
|
public function register(Application $app)
|
||||||
{
|
{
|
||||||
$app['controller.api.v3'] = $app->share(function (PhraseaApplication $app) {
|
$app['controller.api.v3.resulthelpers'] = $app->share(function (PhraseaApplication $app) {
|
||||||
return (new V3Controller($app));
|
return (new V3ResultHelpers(
|
||||||
|
$app['conf'],
|
||||||
|
$app['media_accessor.subdef_url_generator'],
|
||||||
|
$app['authentication']
|
||||||
|
));
|
||||||
|
});
|
||||||
|
$app['controller.api.v3.metadatas'] = $app->share(function (PhraseaApplication $app) {
|
||||||
|
return (new V3RecordController($app))
|
||||||
|
->setJsonBodyHelper($app['json.body_helper'])
|
||||||
|
->setDispatcher($app['dispatcher'])
|
||||||
|
;
|
||||||
|
});
|
||||||
|
$app['controller.api.v3.search'] = $app->share(function (PhraseaApplication $app) {
|
||||||
|
return (new V3SearchController($app));
|
||||||
|
});
|
||||||
|
$app['controller.api.v3.stories'] = $app->share(function (PhraseaApplication $app) {
|
||||||
|
return (new V3StoriesController($app));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,12 +56,32 @@ class V3 extends Api implements ControllerProviderInterface, ServiceProviderInte
|
|||||||
|
|
||||||
$controllers->before(new OAuthListener());
|
$controllers->before(new OAuthListener());
|
||||||
|
|
||||||
$controllers->get('/stories/{databox_id}/{record_id}/', 'controller.api.v3:getStoryAction')
|
/**
|
||||||
|
* @uses V3StoriesController::getStoryAction()
|
||||||
|
*/
|
||||||
|
$controllers->get('/stories/{databox_id}/{record_id}/', 'controller.api.v3.stories:getStoryAction')
|
||||||
->before('controller.api.v1:ensureCanAccessToRecord')
|
->before('controller.api.v1:ensureCanAccessToRecord')
|
||||||
->assert('databox_id', '\d+')
|
->assert('databox_id', '\d+')
|
||||||
->assert('record_id', '\d+');
|
->assert('record_id', '\d+');
|
||||||
|
|
||||||
$controllers->match('/search/', 'controller.api.v3:searchAction');
|
/**
|
||||||
|
* @uses V3SearchController::searchAction()
|
||||||
|
*/
|
||||||
|
$controllers->match('/search/', 'controller.api.v3.search:searchAction');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @uses V3RecordController::indexAction_patch()
|
||||||
|
*/
|
||||||
|
$controllers->patch('/records/{databox_id}/{record_id}/', 'controller.api.v3.metadatas:indexAction_patch')
|
||||||
|
->before('controller.api.v1:ensureCanAccessToRecord')
|
||||||
|
->before('controller.api.v1:ensureCanModifyRecord')
|
||||||
|
->assert('databox_id', '\d+')
|
||||||
|
->assert('record_id', '\d+');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @uses \Alchemy\Phrasea\Controller\Api\V1Controller::getBadRequestAction()
|
||||||
|
*/
|
||||||
|
$controllers->match('/records/{any_id}/{anyother_id}/setmetadatas/', 'controller.api.v1:getBadRequestAction');
|
||||||
|
|
||||||
return $controllers;
|
return $controllers;
|
||||||
}
|
}
|
||||||
|
@@ -72,6 +72,9 @@ class Tools implements ControllerProviderInterface, ServiceProviderInterface
|
|||||||
$controllers->post('/metadata/save/', 'controller.prod.tools:saveMetasAction')
|
$controllers->post('/metadata/save/', 'controller.prod.tools:saveMetasAction')
|
||||||
->bind('prod_tools_metadata_save');
|
->bind('prod_tools_metadata_save');
|
||||||
|
|
||||||
|
$controllers->post('/auto-subtitle/', 'controller.prod.tools:autoSubtitleAction')
|
||||||
|
->bind('prod_tools_auto_subtitle');
|
||||||
|
|
||||||
$controllers->get('/videoEditor', 'controller.prod.tools:videoEditorAction');
|
$controllers->get('/videoEditor', 'controller.prod.tools:videoEditorAction');
|
||||||
|
|
||||||
return $controllers;
|
return $controllers;
|
||||||
|
@@ -60,6 +60,7 @@ class Thesaurus implements ControllerProviderInterface, ServiceProviderInterface
|
|||||||
$controllers->match('newterm.php', 'controller.thesaurus:newTerm');
|
$controllers->match('newterm.php', 'controller.thesaurus:newTerm');
|
||||||
$controllers->match('properties.php', 'controller.thesaurus:properties');
|
$controllers->match('properties.php', 'controller.thesaurus:properties');
|
||||||
$controllers->match('thesaurus.php', 'controller.thesaurus:thesaurus')->bind('thesaurus_thesaurus');
|
$controllers->match('thesaurus.php', 'controller.thesaurus:thesaurus')->bind('thesaurus_thesaurus');
|
||||||
|
$controllers->match('populate', 'controller.thesaurus:populate')->bind('thesaurus_populate');
|
||||||
|
|
||||||
$controllers->match('xmlhttp/accept.x.php', 'controller.thesaurus:acceptXml');
|
$controllers->match('xmlhttp/accept.x.php', 'controller.thesaurus:acceptXml');
|
||||||
$controllers->match('xmlhttp/acceptcandidates.x.php', 'controller.thesaurus:acceptCandidatesXml');
|
$controllers->match('xmlhttp/acceptcandidates.x.php', 'controller.thesaurus:acceptCandidatesXml');
|
||||||
|
@@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Alchemy\Phrasea\Core\Event\Record;
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\Model\RecordInterface;
|
||||||
|
|
||||||
|
class RecordAutoSubtitleEvent extends RecordEvent
|
||||||
|
{
|
||||||
|
private $languageSource;
|
||||||
|
private $metaStructureIdSource;
|
||||||
|
private $languageDestination;
|
||||||
|
private $metaStructureIdDestination;
|
||||||
|
private $permalinkUrl;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
RecordInterface $record,
|
||||||
|
$permalinkUrl,
|
||||||
|
$languageSource,
|
||||||
|
$metaStructureIdSource,
|
||||||
|
$languageDestination,
|
||||||
|
$metaStructureIdDestination
|
||||||
|
)
|
||||||
|
{
|
||||||
|
parent::__construct($record);
|
||||||
|
|
||||||
|
$this->languageSource = $languageSource;
|
||||||
|
$this->metaStructureIdSource = $metaStructureIdSource;
|
||||||
|
$this->languageDestination = $languageDestination;
|
||||||
|
$this->metaStructureIdDestination = $metaStructureIdDestination;
|
||||||
|
$this->permalinkUrl = $permalinkUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLanguageSource()
|
||||||
|
{
|
||||||
|
return $this->languageSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMetaStructureIdSource()
|
||||||
|
{
|
||||||
|
return $this->metaStructureIdSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLanguageDestination()
|
||||||
|
{
|
||||||
|
return $this->languageDestination;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMetaStructureIdDestination()
|
||||||
|
{
|
||||||
|
return $this->metaStructureIdDestination;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPermalinkUrl()
|
||||||
|
{
|
||||||
|
return $this->permalinkUrl;
|
||||||
|
}
|
||||||
|
}
|
@@ -5,7 +5,6 @@ namespace Alchemy\Phrasea\Core\Event\Subscriber;
|
|||||||
use Alchemy\Phrasea\Core\Event\Record\RecordEvents;
|
use Alchemy\Phrasea\Core\Event\Record\RecordEvents;
|
||||||
use Alchemy\Phrasea\Core\Event\Record\SubDefinitionCreatedEvent;
|
use Alchemy\Phrasea\Core\Event\Record\SubDefinitionCreatedEvent;
|
||||||
use Alchemy\Phrasea\Core\Event\Record\SubDefinitionCreationFailedEvent;
|
use Alchemy\Phrasea\Core\Event\Record\SubDefinitionCreationFailedEvent;
|
||||||
use Alchemy\Phrasea\Core\Event\Record\SubDefinitionsCreatedEvent;
|
|
||||||
use Alchemy\Phrasea\Model\Entities\WebhookEvent;
|
use Alchemy\Phrasea\Model\Entities\WebhookEvent;
|
||||||
use Silex\Application;
|
use Silex\Application;
|
||||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||||
@@ -30,7 +29,8 @@ class WebhookSubdefEventSubscriber implements EventSubscriberInterface
|
|||||||
$this->app['manipulator.webhook-event']->create(
|
$this->app['manipulator.webhook-event']->create(
|
||||||
WebhookEvent::RECORD_SUBDEF_CREATED,
|
WebhookEvent::RECORD_SUBDEF_CREATED,
|
||||||
WebhookEvent::RECORD_SUBDEF_TYPE,
|
WebhookEvent::RECORD_SUBDEF_TYPE,
|
||||||
$eventData
|
$eventData,
|
||||||
|
[$event->getRecord()->getBaseId()]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,22 +45,8 @@ class WebhookSubdefEventSubscriber implements EventSubscriberInterface
|
|||||||
$this->app['manipulator.webhook-event']->create(
|
$this->app['manipulator.webhook-event']->create(
|
||||||
WebhookEvent::RECORD_SUBDEF_FAILED,
|
WebhookEvent::RECORD_SUBDEF_FAILED,
|
||||||
WebhookEvent::RECORD_SUBDEF_TYPE,
|
WebhookEvent::RECORD_SUBDEF_TYPE,
|
||||||
$eventData
|
$eventData,
|
||||||
);
|
[$event->getRecord()->getBaseId()]
|
||||||
}
|
|
||||||
|
|
||||||
public function onSubdefsCreated(SubDefinitionsCreatedEvent $event)
|
|
||||||
{
|
|
||||||
$eventData = [
|
|
||||||
'databox_id' => $event->getRecord()->getDataboxId(),
|
|
||||||
'record_id' => $event->getRecord()->getRecordId(),
|
|
||||||
'subdef_count' => count($event->getMedia())
|
|
||||||
];
|
|
||||||
|
|
||||||
$this->app['manipulator.webhook-event']->create(
|
|
||||||
WebhookEvent::RECORD_SUBDEFS_CREATED,
|
|
||||||
WebhookEvent::RECORD_SUBDEF_TYPE,
|
|
||||||
$eventData
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,7 +54,6 @@ class WebhookSubdefEventSubscriber implements EventSubscriberInterface
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
RecordEvents::SUB_DEFINITION_CREATED => 'onSubdefCreated',
|
RecordEvents::SUB_DEFINITION_CREATED => 'onSubdefCreated',
|
||||||
RecordEvents::SUB_DEFINITIONS_CREATED => 'onSubdefsCreated',
|
|
||||||
RecordEvents::SUB_DEFINITION_CREATION_FAILED => 'onSubdefCreationFailed'
|
RecordEvents::SUB_DEFINITION_CREATION_FAILED => 'onSubdefCreationFailed'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@@ -54,6 +54,8 @@ final class PhraseaEvents
|
|||||||
const RECORD_EDIT = 'record.edit';
|
const RECORD_EDIT = 'record.edit';
|
||||||
const RECORD_UPLOAD = 'record.upload';
|
const RECORD_UPLOAD = 'record.upload';
|
||||||
|
|
||||||
|
const RECORD_AUTO_SUBTITLE = 'record.auto-subtitle';
|
||||||
|
|
||||||
const THESAURUS_IMPORTED = 'thesaurus.imported';
|
const THESAURUS_IMPORTED = 'thesaurus.imported';
|
||||||
const THESAURUS_FIELD_LINKED = 'thesaurus.field-linked';
|
const THESAURUS_FIELD_LINKED = 'thesaurus.field-linked';
|
||||||
const THESAURUS_CANDIDATE_ACCEPTED_AS_CONCEPT = 'thesaurus.candidate-accepted-as-concept';
|
const THESAURUS_CANDIDATE_ACCEPTED_AS_CONCEPT = 'thesaurus.candidate-accepted-as-concept';
|
||||||
|
@@ -150,6 +150,9 @@ class RepositoriesServiceProvider implements ServiceProviderInterface
|
|||||||
$app['repo.worker-running-job'] = $app->share(function (PhraseaApplication $app) {
|
$app['repo.worker-running-job'] = $app->share(function (PhraseaApplication $app) {
|
||||||
return $app['orm.em']->getRepository('Phraseanet:WorkerRunningJob');
|
return $app['orm.em']->getRepository('Phraseanet:WorkerRunningJob');
|
||||||
});
|
});
|
||||||
|
$app['repo.worker-job'] = $app->share(function (PhraseaApplication $app) {
|
||||||
|
return $app['orm.em']->getRepository('Phraseanet:WorkerJob');
|
||||||
|
});
|
||||||
$app['repo.worker-running-populate'] = $app->share(function (PhraseaApplication $app) {
|
$app['repo.worker-running-populate'] = $app->share(function (PhraseaApplication $app) {
|
||||||
return $app['orm.em']->getRepository('Phraseanet:WorkerRunningPopulate');
|
return $app['orm.em']->getRepository('Phraseanet:WorkerRunningPopulate');
|
||||||
});
|
});
|
||||||
|
@@ -16,8 +16,7 @@ class Version
|
|||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
|
private $number = '4.1.1';
|
||||||
private $number = '4.1.0-alpha.29a';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
|
150
lib/Alchemy/Phrasea/Model/Entities/WorkerJob.php
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Alchemy\Phrasea\Model\Entities;
|
||||||
|
|
||||||
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
use Gedmo\Mapping\Annotation as Gedmo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Table(name="WorkerJob", indexes={@ORM\Index(name="worker_job_type", columns={"type"})})
|
||||||
|
* @ORM\Entity(repositoryClass="Alchemy\Phrasea\Model\Repositories\WorkerJobRepository")
|
||||||
|
*/
|
||||||
|
class WorkerJob
|
||||||
|
{
|
||||||
|
const WAITING = "waiting";
|
||||||
|
const RUNNING = "running";
|
||||||
|
const FINISHED = "finished";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="integer")
|
||||||
|
* @ORM\Id
|
||||||
|
* @ORM\GeneratedValue
|
||||||
|
*/
|
||||||
|
private $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="string", name="type")
|
||||||
|
*/
|
||||||
|
private $type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="json_array", name="data", nullable=false)
|
||||||
|
*/
|
||||||
|
private $data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="string", name="status")
|
||||||
|
*/
|
||||||
|
private $status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Gedmo\Timestampable(on="create")
|
||||||
|
* @ORM\Column(type="datetime")
|
||||||
|
*/
|
||||||
|
private $created;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="datetime", nullable=true)
|
||||||
|
*/
|
||||||
|
private $started;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="datetime", nullable=true)
|
||||||
|
*/
|
||||||
|
private $finished;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function getId()
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setType($type)
|
||||||
|
{
|
||||||
|
$this->type = $type;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getType()
|
||||||
|
{
|
||||||
|
return $this->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $data
|
||||||
|
*
|
||||||
|
* @return WorkerJob
|
||||||
|
*/
|
||||||
|
public function setData(array $data)
|
||||||
|
{
|
||||||
|
$this->data = $data;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getData()
|
||||||
|
{
|
||||||
|
return $this->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setStatus($status)
|
||||||
|
{
|
||||||
|
$this->status = $status;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStatus()
|
||||||
|
{
|
||||||
|
return $this->status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \DateTime
|
||||||
|
*/
|
||||||
|
public function getCreated()
|
||||||
|
{
|
||||||
|
return $this->created;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \DateTime $finished
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setFinished(\DateTime $finished)
|
||||||
|
{
|
||||||
|
$this->finished = $finished;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getFinished()
|
||||||
|
{
|
||||||
|
return $this->finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \DateTime $started
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setStarted(\DateTime $started)
|
||||||
|
{
|
||||||
|
$this->started = $started;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getStarted()
|
||||||
|
{
|
||||||
|
return $this->started;
|
||||||
|
}
|
||||||
|
}
|
@@ -20,6 +20,8 @@ class WorkerRunningJob
|
|||||||
const FINISHED = 'finished';
|
const FINISHED = 'finished';
|
||||||
const RUNNING = 'running';
|
const RUNNING = 'running';
|
||||||
|
|
||||||
|
const MAX_RESULT = 500;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="integer")
|
* @ORM\Column(type="integer")
|
||||||
* @ORM\Id
|
* @ORM\Id
|
||||||
|
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Alchemy\Phrasea\Model\Repositories;
|
||||||
|
|
||||||
|
use Doctrine\ORM\EntityRepository;
|
||||||
|
|
||||||
|
|
||||||
|
class WorkerJobRepository extends EntityRepository
|
||||||
|
{
|
||||||
|
public function getEntityManager()
|
||||||
|
{
|
||||||
|
return parent::getEntityManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function reconnect()
|
||||||
|
{
|
||||||
|
if($this->_em->getConnection()->ping() === false) {
|
||||||
|
$this->_em->getConnection()->close();
|
||||||
|
$this->_em->getConnection()->connect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -25,7 +25,6 @@ class PermalinkTransformer extends TransformerAbstract
|
|||||||
'created_on' => $permalink->get_created_on()->format(DATE_ATOM),
|
'created_on' => $permalink->get_created_on()->format(DATE_ATOM),
|
||||||
'id' => $permalink->get_id(),
|
'id' => $permalink->get_id(),
|
||||||
'is_activated' => $permalink->get_is_activated(),
|
'is_activated' => $permalink->get_is_activated(),
|
||||||
/** @Ignore */
|
|
||||||
'label' => $permalink->get_label(),
|
'label' => $permalink->get_label(),
|
||||||
'updated_on' => $permalink->get_last_modified()->format(DATE_ATOM),
|
'updated_on' => $permalink->get_last_modified()->format(DATE_ATOM),
|
||||||
'page_url' => $permalink->get_page(),
|
'page_url' => $permalink->get_page(),
|
||||||
|
@@ -11,13 +11,10 @@
|
|||||||
|
|
||||||
namespace Alchemy\Phrasea\SearchEngine\Elastic;
|
namespace Alchemy\Phrasea\SearchEngine\Elastic;
|
||||||
|
|
||||||
use Alchemy\Phrasea\SearchEngine\Elastic\Exception\MergeException;
|
|
||||||
use Alchemy\Phrasea\SearchEngine\Elastic\Mapping;
|
|
||||||
use Alchemy\Phrasea\SearchEngine\Elastic\Structure\Field;
|
|
||||||
use Alchemy\Phrasea\SearchEngine\Elastic\Structure\Flag;
|
|
||||||
use appbox;
|
use appbox;
|
||||||
use DateTime;
|
use DateTime;
|
||||||
use igorw;
|
use Exception;
|
||||||
|
|
||||||
|
|
||||||
class RecordHelper
|
class RecordHelper
|
||||||
{
|
{
|
||||||
@@ -100,31 +97,31 @@ class RecordHelper
|
|||||||
$a = explode(';', preg_replace('/\D+/', ';', trim($value)));
|
$a = explode(';', preg_replace('/\D+/', ';', trim($value)));
|
||||||
switch (count($a)) {
|
switch (count($a)) {
|
||||||
case 1: // yyyy
|
case 1: // yyyy
|
||||||
$date = new \DateTime($a[0] . '-01-01'); // will throw if date is not valid
|
$date = new DateTime($a[0] . '-01-01'); // will throw if date is not valid
|
||||||
$v_fix = $date->format('Y');
|
$v_fix = $date->format('Y');
|
||||||
break;
|
break;
|
||||||
case 2: // yyyy;mm
|
case 2: // yyyy;mm
|
||||||
$date = new \DateTime( $a[0] . '-' . $a[1] . '-01');
|
$date = new DateTime( $a[0] . '-' . $a[1] . '-01');
|
||||||
$v_fix = $date->format('Y-m');
|
$v_fix = $date->format('Y-m');
|
||||||
break;
|
break;
|
||||||
case 3: // yyyy;mm;dd
|
case 3: // yyyy;mm;dd
|
||||||
$date = new \DateTime($a[0] . '-' . $a[1] . '-' . $a[2]);
|
$date = new DateTime($a[0] . '-' . $a[1] . '-' . $a[2]);
|
||||||
$v_fix = $date->format('Y-m-d');
|
$v_fix = $date->format('Y-m-d');
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
$date = new \DateTime($a[0] . '-' . $a[1] . '-' . $a[2] . ' ' . $a[3] . ':00:00');
|
$date = new DateTime($a[0] . '-' . $a[1] . '-' . $a[2] . ' ' . $a[3] . ':00:00');
|
||||||
$v_fix = $date->format('Y-m-d H:i:s');
|
$v_fix = $date->format('Y-m-d H:i:s');
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
$date = new \DateTime($a[0] . '-' . $a[1] . '-' . $a[2] . ' ' . $a[3] . ':' . $a[4] . ':00');
|
$date = new DateTime($a[0] . '-' . $a[1] . '-' . $a[2] . ' ' . $a[3] . ':' . $a[4] . ':00');
|
||||||
$v_fix = $date->format('Y-m-d H:i:s');
|
$v_fix = $date->format('Y-m-d H:i:s');
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
$date = new \DateTime($a[0] . '-' . $a[1] . '-' . $a[2] . ' ' . $a[3] . ':' . $a[4] . ':' . $a[5]);
|
$date = new DateTime($a[0] . '-' . $a[1] . '-' . $a[2] . ' ' . $a[3] . ':' . $a[4] . ':' . $a[5]);
|
||||||
$v_fix = $date->format('Y-m-d H:i:s');
|
$v_fix = $date->format('Y-m-d H:i:s');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (Exception $e) {
|
||||||
// no-op, v_fix = null
|
// no-op, v_fix = null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,8 +148,16 @@ class RecordHelper
|
|||||||
return (bool) $value;
|
return (bool) $value;
|
||||||
|
|
||||||
case FieldMapping::TYPE_STRING:
|
case FieldMapping::TYPE_STRING:
|
||||||
$value = substr($value, 0, 32766); // for lucene limit, before a better solution
|
$value = str_replace("\0", '', $value); // no null char for lucene !
|
||||||
return str_replace("\0", '', $value);
|
if( strlen($value) > 32766) { // for lucene limit, before a better solution
|
||||||
|
for($l=32766; $l > 0; $l--) {
|
||||||
|
if(ord(substr($value, $l-1, 1)) < 128) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$value = substr($value, 0, $l);
|
||||||
|
}
|
||||||
|
return $value;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return $value;
|
return $value;
|
||||||
|
@@ -74,7 +74,6 @@ class RecordMoverJob extends AbstractJob
|
|||||||
|
|
||||||
private function processData(Application $app, $row, $logsql)
|
private function processData(Application $app, $row, $logsql)
|
||||||
{
|
{
|
||||||
/** @var databox $databox */
|
|
||||||
$databox = $app->findDataboxById($row['sbas_id']);
|
$databox = $app->findDataboxById($row['sbas_id']);
|
||||||
$rec = $databox->get_record($row['record_id']);
|
$rec = $databox->get_record($row['record_id']);
|
||||||
|
|
||||||
@@ -83,7 +82,7 @@ class RecordMoverJob extends AbstractJob
|
|||||||
// change collection ?
|
// change collection ?
|
||||||
if (array_key_exists('coll', $row)) {
|
if (array_key_exists('coll', $row)) {
|
||||||
$coll = \collection::getByCollectionId($app, $databox, $row['coll']);
|
$coll = \collection::getByCollectionId($app, $databox, $row['coll']);
|
||||||
$rec->move_to_collection($coll, $app['phraseanet.appbox']);
|
$rec->move_to_collection($coll);
|
||||||
if ($logsql) {
|
if ($logsql) {
|
||||||
$this->log('debug', sprintf("on sbas %s move rid %s to coll %s \n", $row['sbas_id'], $row['record_id'], $coll->get_coll_id()));
|
$this->log('debug', sprintf("on sbas %s move rid %s to coll %s \n", $row['sbas_id'], $row['record_id'], $coll->get_coll_id()));
|
||||||
}
|
}
|
||||||
|
@@ -23,9 +23,9 @@ class WorkerExecuteCommand extends Command
|
|||||||
$this->setDescription('Listen queues define on configuration, launch corresponding service for execution')
|
$this->setDescription('Listen queues define on configuration, launch corresponding service for execution')
|
||||||
->addOption('preserve-payload', 'p', InputOption::VALUE_NONE, 'Preserve temporary payload file')
|
->addOption('preserve-payload', 'p', InputOption::VALUE_NONE, 'Preserve temporary payload file')
|
||||||
->addOption('queue-name', '', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'The name of queues to be consuming')
|
->addOption('queue-name', '', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'The name of queues to be consuming')
|
||||||
->addOption('max-processes', 'm', InputOption::VALUE_REQUIRED, 'The max number of process allow to run (default 4) ')
|
->addOption('max-processes', 'm', InputOption::VALUE_REQUIRED, 'The max number of process allow to run (default 1) ')
|
||||||
->addOption('MWG', '', InputOption::VALUE_NONE, 'Enable MWG metadata compatibility (use only for write metadata service)')
|
// ->addOption('MWG', '', InputOption::VALUE_NONE, 'Enable MWG metadata compatibility (use only for write metadata service)')
|
||||||
->addOption('clear-metadatas', '', InputOption::VALUE_NONE, 'Delete metadatas from documents if not compliant with Database structure (use only for write metadata service)')
|
// ->addOption('clear-metadatas', '', InputOption::VALUE_NONE, 'Remove metadatas from documents if not compliant with Database structure (use only for write metadata service)')
|
||||||
->setHelp('');
|
->setHelp('');
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
@@ -33,9 +33,6 @@ class WorkerExecuteCommand extends Command
|
|||||||
|
|
||||||
protected function doExecute(InputInterface $input, OutputInterface $output)
|
protected function doExecute(InputInterface $input, OutputInterface $output)
|
||||||
{
|
{
|
||||||
$MWG = false;
|
|
||||||
$clearMetadatas = false;
|
|
||||||
|
|
||||||
$argQueueName = $input->getOption('queue-name');
|
$argQueueName = $input->getOption('queue-name');
|
||||||
$maxProcesses = intval($input->getOption('max-processes'));
|
$maxProcesses = intval($input->getOption('max-processes'));
|
||||||
|
|
||||||
@@ -64,14 +61,6 @@ class WorkerExecuteCommand extends Command
|
|||||||
$workerInvoker->setMaxProcessPoolValue($maxProcesses);
|
$workerInvoker->setMaxProcessPoolValue($maxProcesses);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($input->getOption('MWG')) {
|
|
||||||
$MWG = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($input->getOption('clear-metadatas')) {
|
|
||||||
$clearMetadatas = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($input->getOption('preserve-payload')) {
|
if ($input->getOption('preserve-payload')) {
|
||||||
$workerInvoker->preservePayloads();
|
$workerInvoker->preservePayloads();
|
||||||
}
|
}
|
||||||
|
@@ -79,11 +79,11 @@ class AdminConfigurationController extends Controller
|
|||||||
$reload = ($request->query->get('reload')) == 1 ? true : false ;
|
$reload = ($request->query->get('reload')) == 1 ? true : false ;
|
||||||
|
|
||||||
if ($request->query->get('running') == 1 && $request->query->get('finished') == 1) {
|
if ($request->query->get('running') == 1 && $request->query->get('finished') == 1) {
|
||||||
$workerRunningJob = $repoWorker->findAll();
|
$workerRunningJob = $repoWorker->findBy([], ['id' => 'DESC'], WorkerRunningJob::MAX_RESULT);
|
||||||
} elseif ($request->query->get('running') == 1) {
|
} elseif ($request->query->get('running') == 1) {
|
||||||
$workerRunningJob = $repoWorker->findBy(['status' => WorkerRunningJob::RUNNING]);
|
$workerRunningJob = $repoWorker->findBy(['status' => WorkerRunningJob::RUNNING], ['id' => 'DESC'], WorkerRunningJob::MAX_RESULT);
|
||||||
} elseif ($request->query->get('finished') == 1) {
|
} elseif ($request->query->get('finished') == 1) {
|
||||||
$workerRunningJob = $repoWorker->findBy(['status' => WorkerRunningJob::FINISHED]);
|
$workerRunningJob = $repoWorker->findBy(['status' => WorkerRunningJob::FINISHED], ['id' => 'DESC'], WorkerRunningJob::MAX_RESULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->render('admin/worker-manager/worker_info.html.twig', [
|
return $this->render('admin/worker-manager/worker_info.html.twig', [
|
||||||
@@ -92,6 +92,22 @@ class AdminConfigurationController extends Controller
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function queueMonitorAction(PhraseaApplication $app, Request $request)
|
||||||
|
{
|
||||||
|
$reload = ($request->query->get('reload')) == 1 ? true : false ;
|
||||||
|
|
||||||
|
/** @var AMQPConnection $serverConnection */
|
||||||
|
$serverConnection = $app['alchemy_worker.amqp.connection'];
|
||||||
|
$serverConnection->getChannel();
|
||||||
|
$serverConnection->declareExchange();
|
||||||
|
$queuesStatus = $serverConnection->getQueuesStatus();
|
||||||
|
|
||||||
|
return $this->render('admin/worker-manager/worker_queue_monitor.html.twig', [
|
||||||
|
'queuesStatus' => $queuesStatus,
|
||||||
|
'reload' => $reload
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
public function truncateTableAction(PhraseaApplication $app, Request $request)
|
public function truncateTableAction(PhraseaApplication $app, Request $request)
|
||||||
{
|
{
|
||||||
/** @var WorkerRunningJobRepository $repoWorker */
|
/** @var WorkerRunningJobRepository $repoWorker */
|
||||||
|
@@ -11,11 +11,13 @@ use Alchemy\Phrasea\WorkerManager\Worker\CreateRecordWorker;
|
|||||||
use Alchemy\Phrasea\WorkerManager\Worker\DeleteRecordWorker;
|
use Alchemy\Phrasea\WorkerManager\Worker\DeleteRecordWorker;
|
||||||
use Alchemy\Phrasea\WorkerManager\Worker\ExportMailWorker;
|
use Alchemy\Phrasea\WorkerManager\Worker\ExportMailWorker;
|
||||||
use Alchemy\Phrasea\WorkerManager\Worker\Factory\CallableWorkerFactory;
|
use Alchemy\Phrasea\WorkerManager\Worker\Factory\CallableWorkerFactory;
|
||||||
|
use Alchemy\Phrasea\WorkerManager\Worker\MainQueueWorker;
|
||||||
use Alchemy\Phrasea\WorkerManager\Worker\PopulateIndexWorker;
|
use Alchemy\Phrasea\WorkerManager\Worker\PopulateIndexWorker;
|
||||||
use Alchemy\Phrasea\WorkerManager\Worker\ProcessPool;
|
use Alchemy\Phrasea\WorkerManager\Worker\ProcessPool;
|
||||||
use Alchemy\Phrasea\WorkerManager\Worker\PullAssetsWorker;
|
use Alchemy\Phrasea\WorkerManager\Worker\PullAssetsWorker;
|
||||||
use Alchemy\Phrasea\WorkerManager\Worker\Resolver\TypeBasedWorkerResolver;
|
use Alchemy\Phrasea\WorkerManager\Worker\Resolver\TypeBasedWorkerResolver;
|
||||||
use Alchemy\Phrasea\WorkerManager\Worker\SubdefCreationWorker;
|
use Alchemy\Phrasea\WorkerManager\Worker\SubdefCreationWorker;
|
||||||
|
use Alchemy\Phrasea\WorkerManager\Worker\SubtitleWorker;
|
||||||
use Alchemy\Phrasea\WorkerManager\Worker\WebhookWorker;
|
use Alchemy\Phrasea\WorkerManager\Worker\WebhookWorker;
|
||||||
use Alchemy\Phrasea\WorkerManager\Worker\WorkerInvoker;
|
use Alchemy\Phrasea\WorkerManager\Worker\WorkerInvoker;
|
||||||
use Alchemy\Phrasea\WorkerManager\Worker\WriteMetadatasWorker;
|
use Alchemy\Phrasea\WorkerManager\Worker\WriteMetadatasWorker;
|
||||||
@@ -128,6 +130,16 @@ class AlchemyWorkerServiceProvider implements PluginProviderInterface
|
|||||||
return (new DeleteRecordWorker())
|
return (new DeleteRecordWorker())
|
||||||
->setApplicationBox($app['phraseanet.appbox']);
|
->setApplicationBox($app['phraseanet.appbox']);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
$app['alchemy_worker.type_based_worker_resolver']->addFactory(MessagePublisher::SUBTITLE_TYPE, new CallableWorkerFactory(function () use ($app) {
|
||||||
|
return (new SubtitleWorker($app['repo.worker-job'], $app['conf'], new LazyLocator($app, 'phraseanet.appbox'), $app['alchemy_worker.logger']))
|
||||||
|
->setFileSystemLocator(new LazyLocator($app, 'filesystem'))
|
||||||
|
->setTemporaryFileSystemLocator(new LazyLocator($app, 'temporary-filesystem'));
|
||||||
|
}));
|
||||||
|
|
||||||
|
$app['alchemy_worker.type_based_worker_resolver']->addFactory(MessagePublisher::MAIN_QUEUE_TYPE, new CallableWorkerFactory(function () use ($app) {
|
||||||
|
return new MainQueueWorker($app['alchemy_worker.message.publisher'], $app['repo.worker-job']);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -84,6 +84,10 @@ class ControllerServiceProvider implements ControllerProviderInterface, ServiceP
|
|||||||
->method('GET|POST')
|
->method('GET|POST')
|
||||||
->bind('worker_admin_pullAssets');
|
->bind('worker_admin_pullAssets');
|
||||||
|
|
||||||
|
$controllers->match('/queue-monitor', 'controller.worker.admin.configuration:queueMonitorAction')
|
||||||
|
->method('GET')
|
||||||
|
->bind('worker_admin_queue_monitor');
|
||||||
|
|
||||||
return $controllers;
|
return $controllers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -23,6 +23,7 @@ use Alchemy\Phrasea\WorkerManager\Subscriber\AssetsIngestSubscriber;
|
|||||||
use Alchemy\Phrasea\WorkerManager\Subscriber\ExportSubscriber;
|
use Alchemy\Phrasea\WorkerManager\Subscriber\ExportSubscriber;
|
||||||
use Alchemy\Phrasea\WorkerManager\Subscriber\RecordSubscriber;
|
use Alchemy\Phrasea\WorkerManager\Subscriber\RecordSubscriber;
|
||||||
use Alchemy\Phrasea\WorkerManager\Subscriber\SearchengineSubscriber;
|
use Alchemy\Phrasea\WorkerManager\Subscriber\SearchengineSubscriber;
|
||||||
|
use Alchemy\Phrasea\WorkerManager\Subscriber\SubtitleSubscriber;
|
||||||
use Alchemy\Phrasea\WorkerManager\Subscriber\WebhookSubscriber;
|
use Alchemy\Phrasea\WorkerManager\Subscriber\WebhookSubscriber;
|
||||||
use Silex\Application;
|
use Silex\Application;
|
||||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||||
@@ -68,6 +69,7 @@ class QueueWorkerServiceProvider implements PluginProviderInterface
|
|||||||
$dispatcher->addSubscriber(new AssetsIngestSubscriber($app['alchemy_worker.message.publisher']));
|
$dispatcher->addSubscriber(new AssetsIngestSubscriber($app['alchemy_worker.message.publisher']));
|
||||||
$dispatcher->addSubscriber(new SearchengineSubscriber($app['alchemy_worker.message.publisher']));
|
$dispatcher->addSubscriber(new SearchengineSubscriber($app['alchemy_worker.message.publisher']));
|
||||||
$dispatcher->addSubscriber(new WebhookSubscriber($app['alchemy_worker.message.publisher']));
|
$dispatcher->addSubscriber(new WebhookSubscriber($app['alchemy_worker.message.publisher']));
|
||||||
|
$dispatcher->addSubscriber(new SubtitleSubscriber(new LazyLocator($app, 'repo.worker-job'), $app['alchemy_worker.message.publisher']));
|
||||||
|
|
||||||
return $dispatcher;
|
return $dispatcher;
|
||||||
})
|
})
|
||||||
|
@@ -29,7 +29,9 @@ class AMQPConnection
|
|||||||
MessagePublisher::CREATE_RECORD_TYPE => MessagePublisher::CREATE_RECORD_QUEUE,
|
MessagePublisher::CREATE_RECORD_TYPE => MessagePublisher::CREATE_RECORD_QUEUE,
|
||||||
MessagePublisher::PULL_QUEUE => MessagePublisher::PULL_QUEUE,
|
MessagePublisher::PULL_QUEUE => MessagePublisher::PULL_QUEUE,
|
||||||
MessagePublisher::POPULATE_INDEX_TYPE => MessagePublisher::POPULATE_INDEX_QUEUE,
|
MessagePublisher::POPULATE_INDEX_TYPE => MessagePublisher::POPULATE_INDEX_QUEUE,
|
||||||
MessagePublisher::DELETE_RECORD_TYPE => MessagePublisher::DELETE_RECORD_QUEUE
|
MessagePublisher::DELETE_RECORD_TYPE => MessagePublisher::DELETE_RECORD_QUEUE,
|
||||||
|
MessagePublisher::MAIN_QUEUE_TYPE => MessagePublisher::MAIN_QUEUE,
|
||||||
|
MessagePublisher::SUBTITLE_TYPE => MessagePublisher::SUBTITLE_QUEUE
|
||||||
];
|
];
|
||||||
|
|
||||||
// the corresponding worker queues and retry queues, loop queue
|
// the corresponding worker queues and retry queues, loop queue
|
||||||
@@ -44,7 +46,6 @@ class AMQPConnection
|
|||||||
MessagePublisher::PULL_QUEUE => MessagePublisher::LOOP_PULL_QUEUE
|
MessagePublisher::PULL_QUEUE => MessagePublisher::LOOP_PULL_QUEUE
|
||||||
];
|
];
|
||||||
|
|
||||||
// default message TTL in retry queue in millisecond
|
|
||||||
public static $defaultFailedQueues = [
|
public static $defaultFailedQueues = [
|
||||||
MessagePublisher::WRITE_METADATAS_TYPE => MessagePublisher::FAILED_METADATAS_QUEUE,
|
MessagePublisher::WRITE_METADATAS_TYPE => MessagePublisher::FAILED_METADATAS_QUEUE,
|
||||||
MessagePublisher::SUBDEF_CREATION_TYPE => MessagePublisher::FAILED_SUBDEF_QUEUE,
|
MessagePublisher::SUBDEF_CREATION_TYPE => MessagePublisher::FAILED_SUBDEF_QUEUE,
|
||||||
@@ -213,6 +214,37 @@ class AMQPConnection
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get queueName, messageCount, consumerCount of queues
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getQueuesStatus()
|
||||||
|
{
|
||||||
|
$queuesList = array_merge(
|
||||||
|
array_values(self::$defaultQueues),
|
||||||
|
array_values(self::$defaultDelayedQueues),
|
||||||
|
array_values(self::$defaultRetryQueues),
|
||||||
|
array_values(self::$defaultFailedQueues)
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->getChannel();
|
||||||
|
$queuesStatus = [];
|
||||||
|
|
||||||
|
foreach ($queuesList as $queue) {
|
||||||
|
$this->setQueue($queue);
|
||||||
|
list($queueName, $messageCount, $consumerCount) = $this->channel->queue_declare($queue, true);
|
||||||
|
|
||||||
|
$status['queueName'] = $queueName;
|
||||||
|
$status['messageCount'] = $messageCount;
|
||||||
|
$status['consumerCount'] = $consumerCount;
|
||||||
|
|
||||||
|
$queuesStatus[] = $status;
|
||||||
|
unset($status);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $queuesStatus;
|
||||||
|
}
|
||||||
|
|
||||||
public function connectionClose()
|
public function connectionClose()
|
||||||
{
|
{
|
||||||
$this->channel->close();
|
$this->channel->close();
|
||||||
|
@@ -18,6 +18,12 @@ class MessagePublisher
|
|||||||
const WEBHOOK_TYPE = 'webhook';
|
const WEBHOOK_TYPE = 'webhook';
|
||||||
const POPULATE_INDEX_TYPE = 'populateIndex';
|
const POPULATE_INDEX_TYPE = 'populateIndex';
|
||||||
const PULL_ASSETS_TYPE = 'pullAssets';
|
const PULL_ASSETS_TYPE = 'pullAssets';
|
||||||
|
const SUBTITLE_TYPE = 'subtitle';
|
||||||
|
const MAIN_QUEUE_TYPE = 'mainQueue';
|
||||||
|
|
||||||
|
|
||||||
|
const MAIN_QUEUE = 'main-queue';
|
||||||
|
const SUBTITLE_QUEUE = 'subtitle-queue';
|
||||||
|
|
||||||
// worker queue to be consumed, when no ack , it is requeued to the retry queue
|
// worker queue to be consumed, when no ack , it is requeued to the retry queue
|
||||||
const EXPORT_QUEUE = 'export-queue';
|
const EXPORT_QUEUE = 'export-queue';
|
||||||
|
@@ -54,18 +54,20 @@ class RecordSubscriber implements EventSubscriberInterface
|
|||||||
if (!$record->isStory()) {
|
if (!$record->isStory()) {
|
||||||
$subdefs = $record->getDatabox()->get_subdef_structure()->getSubdefGroup($record->getType());
|
$subdefs = $record->getDatabox()->get_subdef_structure()->getSubdefGroup($record->getType());
|
||||||
|
|
||||||
foreach ($subdefs as $subdef) {
|
if ($subdefs !== null) {
|
||||||
$payload = [
|
foreach ($subdefs as $subdef) {
|
||||||
'message_type' => MessagePublisher::SUBDEF_CREATION_TYPE,
|
$payload = [
|
||||||
'payload' => [
|
'message_type' => MessagePublisher::SUBDEF_CREATION_TYPE,
|
||||||
'recordId' => $event->getRecord()->getRecordId(),
|
'payload' => [
|
||||||
'databoxId' => $event->getRecord()->getDataboxId(),
|
'recordId' => $event->getRecord()->getRecordId(),
|
||||||
'subdefName' => $subdef->get_name(),
|
'databoxId' => $event->getRecord()->getDataboxId(),
|
||||||
'status' => $event->isNewRecord() ? MessagePublisher::NEW_RECORD_MESSAGE : ''
|
'subdefName' => $subdef->get_name(),
|
||||||
]
|
'status' => $event->isNewRecord() ? MessagePublisher::NEW_RECORD_MESSAGE : ''
|
||||||
];
|
]
|
||||||
|
];
|
||||||
|
|
||||||
$this->messagePublisher->publishMessage($payload, MessagePublisher::SUBDEF_QUEUE);
|
$this->messagePublisher->publishMessage($payload, MessagePublisher::SUBDEF_QUEUE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,90 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Alchemy\Phrasea\WorkerManager\Subscriber;
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\Core\Event\Record\RecordAutoSubtitleEvent;
|
||||||
|
use Alchemy\Phrasea\Core\PhraseaEvents;
|
||||||
|
use Alchemy\Phrasea\Model\Entities\WorkerJob;
|
||||||
|
use Alchemy\Phrasea\Model\Repositories\WorkerJobRepository;
|
||||||
|
use Alchemy\Phrasea\WorkerManager\Queue\MessagePublisher;
|
||||||
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||||
|
|
||||||
|
class SubtitleSubscriber implements EventSubscriberInterface
|
||||||
|
{
|
||||||
|
private $messagePublisher;
|
||||||
|
|
||||||
|
/** @var WorkerJobRepository $repoWorkerJob*/
|
||||||
|
private $repoWorkerJob;
|
||||||
|
|
||||||
|
/** @var callable */
|
||||||
|
private $repoWorkerJobLocator;
|
||||||
|
|
||||||
|
public function __construct(callable $repoWorkerJobLocator, MessagePublisher $messagePublisher)
|
||||||
|
{
|
||||||
|
$this->repoWorkerJobLocator = $repoWorkerJobLocator;
|
||||||
|
$this->messagePublisher = $messagePublisher;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onRecordAutoSubtitle(RecordAutoSubtitleEvent $event)
|
||||||
|
{
|
||||||
|
$this->repoWorkerJob = $this->getRepoWorkerJob();
|
||||||
|
|
||||||
|
$em = $this->repoWorkerJob->getEntityManager();
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
"databoxId" => $event->getRecord()->getDataboxId(),
|
||||||
|
"recordId" => $event->getRecord()->getRecordId(),
|
||||||
|
"permalinkUrl" => $event->getPermalinkUrl(),
|
||||||
|
"languageSource" => $event->getLanguageSource(),
|
||||||
|
"metaStructureIdSource" => $event->getMetaStructureIdSource(),
|
||||||
|
"languageDestination" => $event->getLanguageDestination(),
|
||||||
|
"metaStructureIdDestination" => $event->getMetaStructureIdDestination()
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->repoWorkerJob->reconnect();
|
||||||
|
$em->beginTransaction();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$workerJob = new WorkerJob();
|
||||||
|
$workerJob
|
||||||
|
->setType(MessagePublisher::SUBTITLE_TYPE)
|
||||||
|
->setData($data)
|
||||||
|
->setStatus(WorkerJob::WAITING)
|
||||||
|
;
|
||||||
|
|
||||||
|
$em->persist($workerJob);
|
||||||
|
$em->flush();
|
||||||
|
|
||||||
|
$em->commit();
|
||||||
|
|
||||||
|
$data['workerId'] = $workerJob->getId();
|
||||||
|
$data['type'] = MessagePublisher::SUBTITLE_TYPE;
|
||||||
|
|
||||||
|
$payload = [
|
||||||
|
'message_type' => MessagePublisher::MAIN_QUEUE_TYPE,
|
||||||
|
'payload' => $data
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->messagePublisher->publishMessage($payload, MessagePublisher::MAIN_QUEUE);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$em->rollback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getSubscribedEvents()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
PhraseaEvents::RECORD_AUTO_SUBTITLE => 'onRecordAutoSubtitle',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return WorkerJobRepository
|
||||||
|
*/
|
||||||
|
private function getRepoWorkerJob()
|
||||||
|
{
|
||||||
|
$callable = $this->repoWorkerJobLocator;
|
||||||
|
|
||||||
|
return $callable();
|
||||||
|
}
|
||||||
|
}
|
49
lib/Alchemy/Phrasea/WorkerManager/Worker/MainQueueWorker.php
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Alchemy\Phrasea\WorkerManager\Worker;
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\Model\Repositories\WorkerJobRepository;
|
||||||
|
use Alchemy\Phrasea\WorkerManager\Queue\MessagePublisher;
|
||||||
|
|
||||||
|
class MainQueueWorker implements WorkerInterface
|
||||||
|
{
|
||||||
|
private $messagePublisher;
|
||||||
|
|
||||||
|
private $repoWorkerJob;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
MessagePublisher $messagePublisher,
|
||||||
|
WorkerJobRepository $repoWorkerJob
|
||||||
|
)
|
||||||
|
{
|
||||||
|
$this->messagePublisher = $messagePublisher;
|
||||||
|
$this->repoWorkerJob = $repoWorkerJob;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function process(array $payload)
|
||||||
|
{
|
||||||
|
|
||||||
|
// if needed do treatement here depending on the type
|
||||||
|
$queue = null;
|
||||||
|
$messageType = '';
|
||||||
|
|
||||||
|
switch ($payload['type']) {
|
||||||
|
case MessagePublisher::SUBTITLE_TYPE:
|
||||||
|
$queue = MessagePublisher::SUBTITLE_QUEUE;
|
||||||
|
$messageType = $payload['type'];
|
||||||
|
unset($payload['type']);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'message_type' => $messageType,
|
||||||
|
'payload' => $payload
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($queue != null) {
|
||||||
|
$this->messagePublisher->publishMessage($data, $queue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -10,7 +10,7 @@ use Symfony\Component\Process\ProcessBuilder;
|
|||||||
|
|
||||||
class ProcessPool implements LoggerAwareInterface
|
class ProcessPool implements LoggerAwareInterface
|
||||||
{
|
{
|
||||||
const MAX_PROCESSES = 4;
|
const MAX_PROCESSES = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var int
|
* @var int
|
||||||
@@ -41,7 +41,7 @@ class ProcessPool implements LoggerAwareInterface
|
|||||||
* Sets a logger instance on the object
|
* Sets a logger instance on the object
|
||||||
*
|
*
|
||||||
* @param LoggerInterface $logger
|
* @param LoggerInterface $logger
|
||||||
* @return null
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setLogger(LoggerInterface $logger)
|
public function setLogger(LoggerInterface $logger)
|
||||||
{
|
{
|
||||||
|
310
lib/Alchemy/Phrasea/WorkerManager/Worker/SubtitleWorker.php
Normal file
@@ -0,0 +1,310 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Alchemy\Phrasea\WorkerManager\Worker;
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\Application\Helper\FilesystemAware;
|
||||||
|
use Alchemy\Phrasea\Core\Configuration\PropertyAccess;
|
||||||
|
use Alchemy\Phrasea\Model\Entities\WorkerJob;
|
||||||
|
use Alchemy\Phrasea\Model\Repositories\WorkerJobRepository;
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
|
class SubtitleWorker implements WorkerInterface
|
||||||
|
{
|
||||||
|
use FilesystemAware;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var callable
|
||||||
|
*/
|
||||||
|
private $appboxLocator;
|
||||||
|
|
||||||
|
private $logger;
|
||||||
|
private $conf;
|
||||||
|
|
||||||
|
/** @var WorkerJobRepository $repoWorkerJob*/
|
||||||
|
private $repoWorkerJob;
|
||||||
|
|
||||||
|
public function __construct(WorkerJobRepository $repoWorkerJob, PropertyAccess $conf, callable $appboxLocator, LoggerInterface $logger)
|
||||||
|
{
|
||||||
|
$this->repoWorkerJob = $repoWorkerJob;
|
||||||
|
$this->conf = $conf;
|
||||||
|
$this->appboxLocator = $appboxLocator;
|
||||||
|
$this->logger = $logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function process(array $payload)
|
||||||
|
{
|
||||||
|
$gingaBaseurl = $this->conf->get(['externalservice', 'ginger', 'AutoSubtitling', 'service_base_url']);
|
||||||
|
$gingaToken = $this->conf->get(['externalservice', 'ginger', 'AutoSubtitling', 'token']);
|
||||||
|
$gingaTranscriptFormat = $this->conf->get(['externalservice', 'ginger', 'AutoSubtitling', 'transcript_format']);
|
||||||
|
|
||||||
|
if (!$gingaBaseurl || !$gingaToken || !$gingaTranscriptFormat) {
|
||||||
|
$this->logger->error("External service Ginga not set correctly in configuration.yml");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var WorkerJob $workerJob */
|
||||||
|
$workerJob = $this->repoWorkerJob->find($payload['workerId']);
|
||||||
|
if ($workerJob == null) {
|
||||||
|
$this->logger->error("WorkerId not found");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$workerJob->setStatus(WorkerJob::RUNNING)
|
||||||
|
->setStarted(new \DateTime('now'));
|
||||||
|
|
||||||
|
$em = $this->repoWorkerJob->getEntityManager();
|
||||||
|
$this->repoWorkerJob->reconnect();
|
||||||
|
$em->persist($workerJob);
|
||||||
|
$em->flush();
|
||||||
|
|
||||||
|
switch ($gingaTranscriptFormat) {
|
||||||
|
case 'text/srt,':
|
||||||
|
$extension = 'srt';
|
||||||
|
break;
|
||||||
|
case 'text/plain':
|
||||||
|
$extension = 'txt';
|
||||||
|
break;
|
||||||
|
case 'application/json':
|
||||||
|
$extension = 'json';
|
||||||
|
break;
|
||||||
|
case 'text/vtt':
|
||||||
|
default:
|
||||||
|
$extension = 'vtt';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$languageSource = $this->getLanguageFormat($payload['languageSource']);
|
||||||
|
$languageDestination = $this->getLanguageFormat($payload['languageDestination']);
|
||||||
|
|
||||||
|
$record = $this->getApplicationBox()->get_databox($payload['databoxId'])->get_record($payload['recordId']);
|
||||||
|
$languageSourceFieldName = $record->getDatabox()->get_meta_structure()->get_element($payload['metaStructureIdSource'])->get_name();
|
||||||
|
|
||||||
|
$subtitleSourceTemporaryFile = $this->getTemporaryFilesystem()->createTemporaryFile("subtitle", null, $extension);
|
||||||
|
$gingerClient = new Client();
|
||||||
|
|
||||||
|
// if the languageSourceFieldName do not yet exist, first generate subtitle for it
|
||||||
|
if ($payload['permalinkUrl'] != '' && !$record->get_caption()->has_field($languageSourceFieldName)) {
|
||||||
|
try {
|
||||||
|
$response = $gingerClient->post($gingaBaseurl.'/media/', [
|
||||||
|
'headers' => [
|
||||||
|
'Authorization' => 'token '.$gingaToken
|
||||||
|
],
|
||||||
|
'json' => [
|
||||||
|
'url' => $payload['permalinkUrl'],
|
||||||
|
'language' => $languageSource
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
} catch(\Exception $e) {
|
||||||
|
$this->logger->error($e->getMessage());
|
||||||
|
$this->jobFinished($workerJob);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($response->getStatusCode() !== 201) {
|
||||||
|
$this->logger->error("response status /media/ : ". $response->getStatusCode());
|
||||||
|
$this->jobFinished($workerJob);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$responseMediaBody = $response->getBody()->getContents();
|
||||||
|
$responseMediaBody = json_decode($responseMediaBody,true);
|
||||||
|
|
||||||
|
$checkStatus = true;
|
||||||
|
do {
|
||||||
|
// first wait 5 second before check subtitling status
|
||||||
|
sleep(5);
|
||||||
|
$this->logger->info("bigin to check status");
|
||||||
|
try {
|
||||||
|
$response = $gingerClient->get($gingaBaseurl.'/task/'.$responseMediaBody['task_id'].'/', [
|
||||||
|
'headers' => [
|
||||||
|
'Authorization' => 'token '.$gingaToken
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$checkStatus = false;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($response->getStatusCode() !== 200) {
|
||||||
|
$checkStatus = false;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$responseTaskBody = $response->getBody()->getContents();
|
||||||
|
$responseTaskBody = json_decode($responseTaskBody,true);
|
||||||
|
|
||||||
|
} while($responseTaskBody['status'] != 'SUCCESS');
|
||||||
|
|
||||||
|
if (!$checkStatus) {
|
||||||
|
$this->logger->error("can't check status");
|
||||||
|
$this->jobFinished($workerJob);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$response = $gingerClient->get($gingaBaseurl.'/media/'.$responseMediaBody['media']['uuid'].'/', [
|
||||||
|
'headers' => [
|
||||||
|
'Authorization' => 'token '.$gingaToken,
|
||||||
|
'ACCEPT' => $gingaTranscriptFormat
|
||||||
|
],
|
||||||
|
'query' => [
|
||||||
|
'language' => $languageSource
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->logger->error($e->getMessage());
|
||||||
|
$this->jobFinished($workerJob);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($response->getStatusCode() !== 200) {
|
||||||
|
$this->logger->error("response status /media/uuid : ". $response->getStatusCode());
|
||||||
|
$this->jobFinished($workerJob);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$transcriptContent = $response->getBody()->getContents();
|
||||||
|
|
||||||
|
$transcriptContent = preg_replace('/WEBVTT/', 'WEBVTT - with cue identifier', $transcriptContent, 1);
|
||||||
|
|
||||||
|
// save subtitle on temporary file to use to translate if needed
|
||||||
|
file_put_contents($subtitleSourceTemporaryFile, $transcriptContent);
|
||||||
|
|
||||||
|
$metadatas[0] = [
|
||||||
|
'meta_struct_id' => (int)$payload['metaStructureIdSource'],
|
||||||
|
'meta_id' => '',
|
||||||
|
'value' => $transcriptContent
|
||||||
|
];
|
||||||
|
|
||||||
|
try {
|
||||||
|
$record->set_metadatas($metadatas);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->logger->error($e->getMessage());
|
||||||
|
$this->jobFinished($workerJob);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->logger->info("Generate subtitle on language source SUCCESS");
|
||||||
|
} elseif ($record->get_caption()->has_field($languageSourceFieldName)) {
|
||||||
|
// get the source subtitle and save it to a temporary file
|
||||||
|
$fieldValues = $record->get_caption()->get_field($languageSourceFieldName)->get_values();
|
||||||
|
$fieldValue = array_pop($fieldValues);
|
||||||
|
|
||||||
|
file_put_contents($subtitleSourceTemporaryFile, $fieldValue->getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($payload['metaStructureIdSource'] !== $payload['metaStructureIdDestination']) {
|
||||||
|
try {
|
||||||
|
$response = $gingerClient->post($gingaBaseurl.'/translate/', [
|
||||||
|
'headers' => [
|
||||||
|
'Authorization' => 'token '.$gingaToken,
|
||||||
|
'ACCEPT' => $gingaTranscriptFormat
|
||||||
|
],
|
||||||
|
'multipart' => [
|
||||||
|
[
|
||||||
|
'name' => 'transcript',
|
||||||
|
'contents' => fopen($subtitleSourceTemporaryFile, 'r')
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'transcript_format',
|
||||||
|
'contents' => $gingaTranscriptFormat,
|
||||||
|
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'language_in',
|
||||||
|
'contents' => $languageSource,
|
||||||
|
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'language_out',
|
||||||
|
'contents' => $languageDestination,
|
||||||
|
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
} catch(\Exception $e) {
|
||||||
|
$this->logger->error($e->getMessage());
|
||||||
|
$this->jobFinished($workerJob);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($response->getStatusCode() !== 200) {
|
||||||
|
$this->logger->error("response status /translate/ : ". $response->getStatusCode());
|
||||||
|
$this->jobFinished($workerJob);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$transcriptContent = $response->getBody()->getContents();
|
||||||
|
$transcriptContent = preg_replace('/WEBVTT/', 'WEBVTT - with cue identifier', $transcriptContent, 1);
|
||||||
|
|
||||||
|
$metadatas[0] = [
|
||||||
|
'meta_struct_id' => (int)$payload['metaStructureIdDestination'],
|
||||||
|
'meta_id' => '',
|
||||||
|
'value' => $transcriptContent
|
||||||
|
];
|
||||||
|
|
||||||
|
try {
|
||||||
|
$record->set_metadatas($metadatas);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->logger->error($e->getMessage());
|
||||||
|
$this->jobFinished($workerJob);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->logger->info("Translate subtitle on language destination SUCCESS");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->jobFinished($workerJob);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \appbox
|
||||||
|
*/
|
||||||
|
private function getApplicationBox()
|
||||||
|
{
|
||||||
|
$callable = $this->appboxLocator;
|
||||||
|
|
||||||
|
return $callable();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function jobFinished(WorkerJob $workerJob)
|
||||||
|
{
|
||||||
|
$workerJob->setStatus(WorkerJob::FINISHED)
|
||||||
|
->setFinished(new \DateTime('now'));
|
||||||
|
|
||||||
|
$em = $this->repoWorkerJob->getEntityManager();
|
||||||
|
$this->repoWorkerJob->reconnect();
|
||||||
|
|
||||||
|
$em->persist($workerJob);
|
||||||
|
$em->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getLanguageFormat($language)
|
||||||
|
{
|
||||||
|
switch ($language) {
|
||||||
|
case 'En':
|
||||||
|
return 'en-GB';
|
||||||
|
case 'De':
|
||||||
|
return 'de-DE';
|
||||||
|
case 'Fr':
|
||||||
|
default:
|
||||||
|
return 'fr-FR';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -522,10 +522,11 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param collection $collection
|
* @param collection $collection
|
||||||
* @param appbox $appbox
|
* @param appbox $appbox WTF this parm is useless
|
||||||
* @return record_adapter
|
* @return record_adapter
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public function move_to_collection(collection $collection, appbox $appbox)
|
public function move_to_collection(collection $collection, appbox $appbox = null)
|
||||||
{
|
{
|
||||||
if ($this->getCollection()->get_base_id() === $collection->get_base_id()) {
|
if ($this->getCollection()->get_base_id() === $collection->get_base_id()) {
|
||||||
return $this;
|
return $this;
|
||||||
@@ -1054,10 +1055,13 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trim($params['meta_id']) !== '') {
|
$tmp_val = trim($params['value']);
|
||||||
$tmp_val = trim($params['value']);
|
|
||||||
|
|
||||||
$caption_field_value = $caption_field->get_value($params['meta_id']);
|
if (trim($params['meta_id']) !== '') {
|
||||||
|
|
||||||
|
if(is_null($caption_field_value = $caption_field->get_value($params['meta_id']))) {
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
if ($tmp_val === '') {
|
if ($tmp_val === '') {
|
||||||
$caption_field_value->delete();
|
$caption_field_value->delete();
|
||||||
@@ -1068,8 +1072,11 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
|
|||||||
$caption_field_value->setVocab($vocab, $vocab_id);
|
$caption_field_value->setVocab($vocab, $vocab_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
$caption_field_value = caption_Field_Value::create($this->app, $databox_field, $this, $params['value'], $vocab, $vocab_id);
|
else {
|
||||||
|
if($tmp_val !== '') {
|
||||||
|
caption_Field_Value::create($this->app, $databox_field, $this, $params['value'], $vocab, $vocab_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
@@ -319,5 +319,15 @@ workers:
|
|||||||
user: ''
|
user: ''
|
||||||
password: ''
|
password: ''
|
||||||
vhost: /
|
vhost: /
|
||||||
|
|
||||||
|
externalservice:
|
||||||
|
ginger:
|
||||||
|
AutoSubtitling:
|
||||||
|
service_base_url: https://base.uri
|
||||||
|
token: 39c6011d
|
||||||
|
transcript_format: text/vtt
|
||||||
|
subdef_source: preview
|
||||||
|
|
||||||
|
|
||||||
Console_logger_enabled_environments: [test]
|
Console_logger_enabled_environments: [test]
|
||||||
|
|
||||||
|
@@ -119,7 +119,7 @@
|
|||||||
<vcodec>libvpx</vcodec>
|
<vcodec>libvpx</vcodec>
|
||||||
</subdef>
|
</subdef>
|
||||||
<subdef class="preview" name="audiovideowav" downloadable="true" orderable="true" presets="Wave Mono 8 kHz">
|
<subdef class="preview" name="audiovideowav" downloadable="true" orderable="true" presets="Wave Mono 8 kHz">
|
||||||
<path>{{datapathnoweb}}{{basename}}/subview</path>
|
<path>{{datapathnoweb}}{{basename}}/subdefs</path>
|
||||||
<meta>no</meta>
|
<meta>no</meta>
|
||||||
<mediatype>audio</mediatype>
|
<mediatype>audio</mediatype>
|
||||||
<audiobitrate>128</audiobitrate>
|
<audiobitrate>128</audiobitrate>
|
||||||
@@ -131,7 +131,7 @@
|
|||||||
<label lang="en">Audio WAVE 8 kHz</label>
|
<label lang="en">Audio WAVE 8 kHz</label>
|
||||||
</subdef>
|
</subdef>
|
||||||
<subdef class="preview" name="audiovideomp3" downloadable="true" orderable="true" presets="Normal MP3 128 kbit/s">
|
<subdef class="preview" name="audiovideomp3" downloadable="true" orderable="true" presets="Normal MP3 128 kbit/s">
|
||||||
<path>{{datapathnoweb}}{{basename}}/subview</path>
|
<path>{{datapathnoweb}}{{basename}}/subdefs</path>
|
||||||
<meta>no</meta>
|
<meta>no</meta>
|
||||||
<mediatype>audio</mediatype>
|
<mediatype>audio</mediatype>
|
||||||
<audiobitrate>180</audiobitrate>
|
<audiobitrate>180</audiobitrate>
|
||||||
|
234
lib/conf.d/data_templates/gs1.xml
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||||
|
<record>
|
||||||
|
<path>{{datapathnoweb}}{{basename}}/documents</path>
|
||||||
|
<subdefs>
|
||||||
|
<subdefgroup name="image">
|
||||||
|
<subdef class="preview" name="preview" downloadable="true">
|
||||||
|
<path>{{datapathnoweb}}{{basename}}/subdefs</path>
|
||||||
|
<size>1024</size>
|
||||||
|
<method>resample</method>
|
||||||
|
<dpi>72</dpi>
|
||||||
|
<strip>no</strip>
|
||||||
|
<quality>75</quality>
|
||||||
|
<meta>yes</meta>
|
||||||
|
<devices>screen</devices>
|
||||||
|
<mediatype>image</mediatype>
|
||||||
|
<label lang="fr">Prévisualisation</label>
|
||||||
|
<label lang="en">Preview</label>
|
||||||
|
</subdef>
|
||||||
|
<subdef class="thumbnail" name="thumbnail" downloadable="true">
|
||||||
|
<path>{{datapathnoweb}}{{basename}}/subdefs</path>
|
||||||
|
<size>240</size>
|
||||||
|
<method>resample</method>
|
||||||
|
<dpi>72</dpi>
|
||||||
|
<strip>yes</strip>
|
||||||
|
<quality>75</quality>
|
||||||
|
<meta>no</meta>
|
||||||
|
<devices>screen</devices>
|
||||||
|
<mediatype>image</mediatype>
|
||||||
|
<label lang="fr">Vignette</label>
|
||||||
|
<label lang="en">Thumbnail</label>
|
||||||
|
</subdef>
|
||||||
|
<subdef class="preview" name="preview_mobile" downloadable="false">
|
||||||
|
<size>480</size>
|
||||||
|
<resolution>72</resolution>
|
||||||
|
<strip>yes</strip>
|
||||||
|
<quality>75</quality>
|
||||||
|
<path>{{datapathnoweb}}{{basename}}/subdefs</path>
|
||||||
|
<mediatype>image</mediatype>
|
||||||
|
<meta>no</meta>
|
||||||
|
<devices>handheld</devices>
|
||||||
|
<label lang="fr">Prévisualisation Mobile</label>
|
||||||
|
<label lang="en">Mobile Preview</label>
|
||||||
|
</subdef>
|
||||||
|
<subdef class="thumbnail" name="thumbnail_mobile" downloadable="false">
|
||||||
|
<size>150</size>
|
||||||
|
<resolution>72</resolution>
|
||||||
|
<strip>yes</strip>
|
||||||
|
<quality>75</quality>
|
||||||
|
<path>{{datapathnoweb}}{{basename}}/subdefs</path>
|
||||||
|
<mediatype>image</mediatype>
|
||||||
|
<meta>no</meta>
|
||||||
|
<devices>handheld</devices>
|
||||||
|
<label lang="fr">Vignette mobile</label>
|
||||||
|
<label lang="en">Mobile Thumbnail</label>
|
||||||
|
</subdef>
|
||||||
|
</subdefgroup>
|
||||||
|
<subdefgroup name="video">
|
||||||
|
<subdef class="thumbnail" name="thumbnail" downloadable="false">
|
||||||
|
<path>{{datapathnoweb}}{{basename}}/subdefs</path>
|
||||||
|
<size>240</size>
|
||||||
|
<devices>screen</devices>
|
||||||
|
<mediatype>image</mediatype>
|
||||||
|
<writeDatas>no</writeDatas>
|
||||||
|
<label lang="fr">Vignette</label>
|
||||||
|
<label lang="en">Thumbnail</label>
|
||||||
|
</subdef>
|
||||||
|
<subdef class="thumbnail" name="thumbnailgif" downloadable="false">
|
||||||
|
<path>{{datapathnoweb}}{{basename}}/subdefs</path>
|
||||||
|
<size>240</size>
|
||||||
|
<mediatype>gif</mediatype>
|
||||||
|
<delay>150</delay>
|
||||||
|
<devices>screen</devices>
|
||||||
|
<writeDatas>no</writeDatas>
|
||||||
|
<label lang="fr">Animation GIF</label>
|
||||||
|
<label lang="en">GIF Animation</label>
|
||||||
|
</subdef>
|
||||||
|
<subdef class="preview" name="preview" downloadable="true">
|
||||||
|
<path>{{datapathnoweb}}{{basename}}/subdefs</path>
|
||||||
|
<size>748</size>
|
||||||
|
<mediatype>video</mediatype>
|
||||||
|
<writeDatas>yes</writeDatas>
|
||||||
|
<acodec>libfdk_aac</acodec>
|
||||||
|
<vcodec>libx264</vcodec>
|
||||||
|
<devices>screen</devices>
|
||||||
|
<bitrate>1000</bitrate>
|
||||||
|
<audiobitrate>128</audiobitrate>
|
||||||
|
<audiosamplerate>48000</audiosamplerate>
|
||||||
|
<fps>25</fps>
|
||||||
|
<GOPsize>25</GOPsize>
|
||||||
|
<label lang="fr">Prévisualisation</label>
|
||||||
|
<label lang="en">Preview</label>
|
||||||
|
</subdef>
|
||||||
|
<subdef class="preview" name="preview_webm" downloadable="false">
|
||||||
|
<path>{{datapathnoweb}}{{basename}}/subdefs</path>
|
||||||
|
<size>748</size>
|
||||||
|
<mediatype>video</mediatype>
|
||||||
|
<devices>screen</devices>
|
||||||
|
<bitrate>1000</bitrate>
|
||||||
|
<audiobitrate>128</audiobitrate>
|
||||||
|
<audiosamplerate>48000</audiosamplerate>
|
||||||
|
<acodec>libvorbis</acodec>
|
||||||
|
<fps>25</fps>
|
||||||
|
<GOPsize>25</GOPsize>
|
||||||
|
<vcodec>libvpx</vcodec>
|
||||||
|
<label lang="fr">Prévisualisation WebM</label>
|
||||||
|
<label lang="en">WebM Preview</label>
|
||||||
|
</subdef>
|
||||||
|
</subdefgroup>
|
||||||
|
<subdefgroup name="audio">
|
||||||
|
<subdef class="thumbnail" name="thumbnail" downloadable="true">
|
||||||
|
<path>{{datapathnoweb}}{{basename}}/subdefs</path>
|
||||||
|
<mediatype>image</mediatype>
|
||||||
|
<size>240</size>
|
||||||
|
<devices>screen</devices>
|
||||||
|
<writeDatas>no</writeDatas>
|
||||||
|
<label lang="fr">Vignette</label>
|
||||||
|
<label lang="en">Thumbnail</label>
|
||||||
|
</subdef>
|
||||||
|
<subdef class="preview" name="preview" downloadable="true">
|
||||||
|
<path>{{datapathnoweb}}{{basename}}/subdefs</path>
|
||||||
|
<mediatype>audio</mediatype>
|
||||||
|
<writeDatas>yes</writeDatas>
|
||||||
|
<audiobitrate>128</audiobitrate>
|
||||||
|
<audiosamplerate>48000</audiosamplerate>
|
||||||
|
<devices>screen</devices>
|
||||||
|
<label lang="fr">Prévisualisation</label>
|
||||||
|
<label lang="en">Preview</label>
|
||||||
|
</subdef>
|
||||||
|
<subdef class="preview" name="preview_mobile" downloadable="false">
|
||||||
|
<path>{{datapathnoweb}}{{basename}}/subdefs</path>
|
||||||
|
<mediatype>audio</mediatype>
|
||||||
|
<devices>handheld</devices>
|
||||||
|
<label lang="fr">Prévisualisation Mobile</label>
|
||||||
|
<label lang="en">Mobile Preview</label>
|
||||||
|
</subdef>
|
||||||
|
</subdefgroup>
|
||||||
|
<subdefgroup name="document">
|
||||||
|
<subdef class="thumbnail" name="thumbnail" downloadable="false">
|
||||||
|
<path>{{datapathnoweb}}{{basename}}/subdefs</path>
|
||||||
|
<mediatype>image</mediatype>
|
||||||
|
<method>resample</method>
|
||||||
|
<dpi>72</dpi>
|
||||||
|
<size>240</size>
|
||||||
|
<writeDatas>no</writeDatas>
|
||||||
|
<devices>screen</devices>
|
||||||
|
<label lang="fr">Vignette</label>
|
||||||
|
<label lang="en">Thumbnail</label>
|
||||||
|
</subdef>
|
||||||
|
<subdef class="preview" name="preview" downloadable="false">
|
||||||
|
<path>{{datapathnoweb}}{{basename}}/subdefs</path>
|
||||||
|
<mediatype>flexpaper</mediatype>
|
||||||
|
<writeDatas>no</writeDatas>
|
||||||
|
<devices>screen</devices>
|
||||||
|
<label lang="fr">Prévisualisation</label>
|
||||||
|
<label lang="en">Preview</label>
|
||||||
|
</subdef>
|
||||||
|
</subdefgroup>
|
||||||
|
<subdefgroup name="flash">
|
||||||
|
<subdef class="thumbnail" name="thumbnail" downloadable="false">
|
||||||
|
<path>{{datapathnoweb}}{{basename}}/subdefs</path>
|
||||||
|
<mediatype>image</mediatype>
|
||||||
|
<size>240</size>
|
||||||
|
<writeDatas>no</writeDatas>
|
||||||
|
<method>resample</method>
|
||||||
|
<dpi>72</dpi>
|
||||||
|
<devices>screen</devices>
|
||||||
|
<label lang="fr">Vignette</label>
|
||||||
|
<label lang="en">Thumbnail</label>
|
||||||
|
</subdef>
|
||||||
|
<subdef class="preview" name="preview" downloadable="false">
|
||||||
|
<path>{{datapathnoweb}}{{basename}}/subdefs</path>
|
||||||
|
<mediatype>image</mediatype>
|
||||||
|
<size>800</size>
|
||||||
|
<writeDatas>no</writeDatas>
|
||||||
|
<method>resample</method>
|
||||||
|
<dpi>72</dpi>
|
||||||
|
<devices>screen</devices>
|
||||||
|
<label lang="fr">Prévisualisation</label>
|
||||||
|
<label lang="en">Preview</label>
|
||||||
|
</subdef>
|
||||||
|
</subdefgroup>
|
||||||
|
</subdefs>
|
||||||
|
|
||||||
|
<description>
|
||||||
|
<GDTI src="" index="1" />
|
||||||
|
<BrandName src="" index="1" />
|
||||||
|
<ProductName src="XMP-dc:Title" index="1" />
|
||||||
|
<ValidFromDate src="" index="1" type="date" />
|
||||||
|
<GTIN14 src="" index="1" />
|
||||||
|
<AngleIndicator src="" index="1" />
|
||||||
|
<ArticleVariant src="" index="1" />
|
||||||
|
<ClippingPathName src="" index="1" />
|
||||||
|
<ColorMode src="" index="1" readonly="1" />
|
||||||
|
<Copyright src="" index="1" />
|
||||||
|
<CreateDate src="" index="1" readonly="1" type="date" />
|
||||||
|
<Description src="XMP-dc:Description" index="1" />
|
||||||
|
<ExpirationDate src="XMP-plus:LicenseEndDate" index="1" type="date" />
|
||||||
|
<FacingIndicator src="" index="1" />
|
||||||
|
<FileType src="" index="1" />
|
||||||
|
<Filename src="Phraseanet:tf-basename" index="1" readonly="1" thumbtitle="1"/>
|
||||||
|
<ImageQADate src="" index="1" readonly="1" type="date" />
|
||||||
|
<ClippingPathPresent src="" index="1" />
|
||||||
|
<LegalOwner src="XMP-plus:CopyrightOwnerName" index="1" />
|
||||||
|
<LegalOwnerContactInfo src="" index="1" />
|
||||||
|
<MaxAvailHeight src="Phraseanet:tf-height" index="1" readonly="1" type="number" />
|
||||||
|
<MaxAvailWidth src="Phraseanet:tf-width" index="1" readonly="1" type="number" />
|
||||||
|
<NumberOfTheImage src="" index="1" />
|
||||||
|
<PackagingType src="" index="1" />
|
||||||
|
<ProductNetContent src="" index="1" />
|
||||||
|
<ProductSupplier src="" index="1" />
|
||||||
|
<ProductURL src="" index="1" readonly="1" />
|
||||||
|
<RightOfUse src="XMP-xmpRights:UsageTerms" index="1" multi="1" separator=";" />
|
||||||
|
<SpecialRights src="" index="1" multi="1" separator=";" />
|
||||||
|
<VersionNumber src="" index="1" />
|
||||||
|
<InOutPackaging src="" index="1" />
|
||||||
|
<ArchiveDate src="Phraseanet:tf-archivedate" readonly="1" type="date" />
|
||||||
|
<LastEditDate src="Phraseanet:tf-editdate" readonly="1" type="date" />
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<statbits>
|
||||||
|
<bit n="4" labelOn="Caption_filled" searchable="0" printable="0" labelOff="Unspecified_caption">
|
||||||
|
<label switch="off" code="en">Caption not filled</label>
|
||||||
|
<label switch="off" code="fr">Media non renseigne</label>
|
||||||
|
<label switch="on" code="en">Caption filled</label>
|
||||||
|
<label switch="on" code="fr">Média renseigné</label>
|
||||||
|
</bit>
|
||||||
|
<bit n="5" labelOn="Clipping_Path_Present" searchable="1" printable="0" labelOff="No_Clipping_Path">
|
||||||
|
<label switch="off" code="en">No Clipping Path</label>
|
||||||
|
<label switch="off" code="fr">Sans masque de détourage</label>
|
||||||
|
<label switch="on" code="en">Clipping Path Present</label>
|
||||||
|
<label switch="on" code="fr">Avec masque de détourage</label>
|
||||||
|
</bit>
|
||||||
|
</statbits>
|
||||||
|
</record>
|
@@ -65,7 +65,7 @@
|
|||||||
"normalize-css": "^2.1.0",
|
"normalize-css": "^2.1.0",
|
||||||
"npm": "^6.0.0",
|
"npm": "^6.0.0",
|
||||||
"npm-modernizr": "^2.8.3",
|
"npm-modernizr": "^2.8.3",
|
||||||
"phraseanet-production-client": "0.34.214-d",
|
"phraseanet-production-client": "0.34.256-d",
|
||||||
"requirejs": "^2.3.5",
|
"requirejs": "^2.3.5",
|
||||||
"tinymce": "^4.0.28",
|
"tinymce": "^4.0.28",
|
||||||
"underscore": "^1.8.3",
|
"underscore": "^1.8.3",
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2">
|
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2">
|
||||||
<file date="2020-05-29T13:54:14Z" source-language="en" target-language="de" datatype="plaintext" original="not.available">
|
<file date="2020-07-08T13:05:50Z" source-language="en" target-language="de" datatype="plaintext" original="not.available">
|
||||||
<header>
|
<header>
|
||||||
<tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/>
|
<tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/>
|
||||||
<note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note>
|
<note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note>
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2">
|
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2">
|
||||||
<file date="2020-05-29T13:54:38Z" source-language="en" target-language="en" datatype="plaintext" original="not.available">
|
<file date="2020-07-08T13:06:14Z" source-language="en" target-language="en" datatype="plaintext" original="not.available">
|
||||||
<header>
|
<header>
|
||||||
<tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/>
|
<tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/>
|
||||||
<note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note>
|
<note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note>
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2">
|
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2">
|
||||||
<file date="2020-05-29T13:55:04Z" source-language="en" target-language="fr" datatype="plaintext" original="not.available">
|
<file date="2020-07-08T13:06:42Z" source-language="en" target-language="fr" datatype="plaintext" original="not.available">
|
||||||
<header>
|
<header>
|
||||||
<tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/>
|
<tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/>
|
||||||
<note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note>
|
<note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note>
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2">
|
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2">
|
||||||
<file date="2020-05-29T13:55:35Z" source-language="en" target-language="nl" datatype="plaintext" original="not.available">
|
<file date="2020-07-08T13:07:11Z" source-language="en" target-language="nl" datatype="plaintext" original="not.available">
|
||||||
<header>
|
<header>
|
||||||
<tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/>
|
<tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/>
|
||||||
<note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note>
|
<note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note>
|
||||||
|
@@ -0,0 +1,345 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Alchemy\Phrasea\Model\Proxies\__CG__\Alchemy\Phrasea\Model\Entities;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DO NOT EDIT THIS FILE - IT WAS CREATED BY DOCTRINE'S PROXY GENERATOR
|
||||||
|
*/
|
||||||
|
class WorkerRunningJob extends \Alchemy\Phrasea\Model\Entities\WorkerRunningJob implements \Doctrine\ORM\Proxy\Proxy
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var \Closure the callback responsible for loading properties in the proxy object. This callback is called with
|
||||||
|
* three parameters, being respectively the proxy object to be initialized, the method that triggered the
|
||||||
|
* initialization process and an array of ordered parameters that were passed to that method.
|
||||||
|
*
|
||||||
|
* @see \Doctrine\Common\Persistence\Proxy::__setInitializer
|
||||||
|
*/
|
||||||
|
public $__initializer__;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Closure the callback responsible of loading properties that need to be copied in the cloned object
|
||||||
|
*
|
||||||
|
* @see \Doctrine\Common\Persistence\Proxy::__setCloner
|
||||||
|
*/
|
||||||
|
public $__cloner__;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var boolean flag indicating if this object was already initialized
|
||||||
|
*
|
||||||
|
* @see \Doctrine\Common\Persistence\Proxy::__isInitialized
|
||||||
|
*/
|
||||||
|
public $__isInitialized__ = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array properties to be lazy loaded, with keys being the property
|
||||||
|
* names and values being their default values
|
||||||
|
*
|
||||||
|
* @see \Doctrine\Common\Persistence\Proxy::__getLazyProperties
|
||||||
|
*/
|
||||||
|
public static $lazyPropertiesDefaults = [];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \Closure $initializer
|
||||||
|
* @param \Closure $cloner
|
||||||
|
*/
|
||||||
|
public function __construct($initializer = null, $cloner = null)
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->__initializer__ = $initializer;
|
||||||
|
$this->__cloner__ = $cloner;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function __sleep()
|
||||||
|
{
|
||||||
|
if ($this->__isInitialized__) {
|
||||||
|
return ['__isInitialized__', '' . "\0" . 'Alchemy\\Phrasea\\Model\\Entities\\WorkerRunningJob' . "\0" . 'id', '' . "\0" . 'Alchemy\\Phrasea\\Model\\Entities\\WorkerRunningJob' . "\0" . 'databoxId', '' . "\0" . 'Alchemy\\Phrasea\\Model\\Entities\\WorkerRunningJob' . "\0" . 'recordId', '' . "\0" . 'Alchemy\\Phrasea\\Model\\Entities\\WorkerRunningJob' . "\0" . 'work', '' . "\0" . 'Alchemy\\Phrasea\\Model\\Entities\\WorkerRunningJob' . "\0" . 'workOn', '' . "\0" . 'Alchemy\\Phrasea\\Model\\Entities\\WorkerRunningJob' . "\0" . 'created', '' . "\0" . 'Alchemy\\Phrasea\\Model\\Entities\\WorkerRunningJob' . "\0" . 'published', '' . "\0" . 'Alchemy\\Phrasea\\Model\\Entities\\WorkerRunningJob' . "\0" . 'status'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return ['__isInitialized__', '' . "\0" . 'Alchemy\\Phrasea\\Model\\Entities\\WorkerRunningJob' . "\0" . 'id', '' . "\0" . 'Alchemy\\Phrasea\\Model\\Entities\\WorkerRunningJob' . "\0" . 'databoxId', '' . "\0" . 'Alchemy\\Phrasea\\Model\\Entities\\WorkerRunningJob' . "\0" . 'recordId', '' . "\0" . 'Alchemy\\Phrasea\\Model\\Entities\\WorkerRunningJob' . "\0" . 'work', '' . "\0" . 'Alchemy\\Phrasea\\Model\\Entities\\WorkerRunningJob' . "\0" . 'workOn', '' . "\0" . 'Alchemy\\Phrasea\\Model\\Entities\\WorkerRunningJob' . "\0" . 'created', '' . "\0" . 'Alchemy\\Phrasea\\Model\\Entities\\WorkerRunningJob' . "\0" . 'published', '' . "\0" . 'Alchemy\\Phrasea\\Model\\Entities\\WorkerRunningJob' . "\0" . 'status'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function __wakeup()
|
||||||
|
{
|
||||||
|
if ( ! $this->__isInitialized__) {
|
||||||
|
$this->__initializer__ = function (WorkerRunningJob $proxy) {
|
||||||
|
$proxy->__setInitializer(null);
|
||||||
|
$proxy->__setCloner(null);
|
||||||
|
|
||||||
|
$existingProperties = get_object_vars($proxy);
|
||||||
|
|
||||||
|
foreach ($proxy->__getLazyProperties() as $property => $defaultValue) {
|
||||||
|
if ( ! array_key_exists($property, $existingProperties)) {
|
||||||
|
$proxy->$property = $defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function __clone()
|
||||||
|
{
|
||||||
|
$this->__cloner__ && $this->__cloner__->__invoke($this, '__clone', []);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forces initialization of the proxy
|
||||||
|
*/
|
||||||
|
public function __load()
|
||||||
|
{
|
||||||
|
$this->__initializer__ && $this->__initializer__->__invoke($this, '__load', []);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* @internal generated method: use only when explicitly handling proxy specific loading logic
|
||||||
|
*/
|
||||||
|
public function __isInitialized()
|
||||||
|
{
|
||||||
|
return $this->__isInitialized__;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* @internal generated method: use only when explicitly handling proxy specific loading logic
|
||||||
|
*/
|
||||||
|
public function __setInitialized($initialized)
|
||||||
|
{
|
||||||
|
$this->__isInitialized__ = $initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* @internal generated method: use only when explicitly handling proxy specific loading logic
|
||||||
|
*/
|
||||||
|
public function __setInitializer(\Closure $initializer = null)
|
||||||
|
{
|
||||||
|
$this->__initializer__ = $initializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* @internal generated method: use only when explicitly handling proxy specific loading logic
|
||||||
|
*/
|
||||||
|
public function __getInitializer()
|
||||||
|
{
|
||||||
|
return $this->__initializer__;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* @internal generated method: use only when explicitly handling proxy specific loading logic
|
||||||
|
*/
|
||||||
|
public function __setCloner(\Closure $cloner = null)
|
||||||
|
{
|
||||||
|
$this->__cloner__ = $cloner;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* @internal generated method: use only when explicitly handling proxy specific cloning logic
|
||||||
|
*/
|
||||||
|
public function __getCloner()
|
||||||
|
{
|
||||||
|
return $this->__cloner__;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* @internal generated method: use only when explicitly handling proxy specific loading logic
|
||||||
|
* @static
|
||||||
|
*/
|
||||||
|
public function __getLazyProperties()
|
||||||
|
{
|
||||||
|
return self::$lazyPropertiesDefaults;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getId()
|
||||||
|
{
|
||||||
|
if ($this->__isInitialized__ === false) {
|
||||||
|
return (int) parent::getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$this->__initializer__ && $this->__initializer__->__invoke($this, 'getId', []);
|
||||||
|
|
||||||
|
return parent::getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function setDataboxId($databoxId)
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->__initializer__ && $this->__initializer__->__invoke($this, 'setDataboxId', [$databoxId]);
|
||||||
|
|
||||||
|
return parent::setDataboxId($databoxId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getDataboxId()
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->__initializer__ && $this->__initializer__->__invoke($this, 'getDataboxId', []);
|
||||||
|
|
||||||
|
return parent::getDataboxId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function setRecordId($recordId)
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->__initializer__ && $this->__initializer__->__invoke($this, 'setRecordId', [$recordId]);
|
||||||
|
|
||||||
|
return parent::setRecordId($recordId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getRecordId()
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->__initializer__ && $this->__initializer__->__invoke($this, 'getRecordId', []);
|
||||||
|
|
||||||
|
return parent::getRecordId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function setWork($work)
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->__initializer__ && $this->__initializer__->__invoke($this, 'setWork', [$work]);
|
||||||
|
|
||||||
|
return parent::setWork($work);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getWork()
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->__initializer__ && $this->__initializer__->__invoke($this, 'getWork', []);
|
||||||
|
|
||||||
|
return parent::getWork();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function setWorkOn($workOn)
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->__initializer__ && $this->__initializer__->__invoke($this, 'setWorkOn', [$workOn]);
|
||||||
|
|
||||||
|
return parent::setWorkOn($workOn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getWorkOn()
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->__initializer__ && $this->__initializer__->__invoke($this, 'getWorkOn', []);
|
||||||
|
|
||||||
|
return parent::getWorkOn();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getCreated()
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->__initializer__ && $this->__initializer__->__invoke($this, 'getCreated', []);
|
||||||
|
|
||||||
|
return parent::getCreated();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function setPublished(\DateTime $published)
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->__initializer__ && $this->__initializer__->__invoke($this, 'setPublished', [$published]);
|
||||||
|
|
||||||
|
return parent::setPublished($published);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getPublished()
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->__initializer__ && $this->__initializer__->__invoke($this, 'getPublished', []);
|
||||||
|
|
||||||
|
return parent::getPublished();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function setStatus($status)
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->__initializer__ && $this->__initializer__->__invoke($this, 'setStatus', [$status]);
|
||||||
|
|
||||||
|
return parent::setStatus($status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getStatus()
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->__initializer__ && $this->__initializer__->__invoke($this, 'getStatus', []);
|
||||||
|
|
||||||
|
return parent::getStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getWorkName()
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->__initializer__ && $this->__initializer__->__invoke($this, 'getWorkName', []);
|
||||||
|
|
||||||
|
return parent::getWorkName();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -164,3 +164,20 @@ $mainMenuLinkBackgroundHoverColor: transparent;
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.acceptDl-info {
|
||||||
|
background-color: #d9edf7;
|
||||||
|
border: 1px solid #bce8f1;
|
||||||
|
border-radius: 3px;
|
||||||
|
color: #3a87ad;
|
||||||
|
display: inline-block;
|
||||||
|
padding: 9px 24px 5px 9px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
text-shadow: 0 1px 0 rgba(255,255,255,.5);
|
||||||
|
a, label {
|
||||||
|
color: #3a87ad!important;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
1
resources/www/lightbox/images/chevron-left-solid.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="chevron-left" class="svg-inline--fa fa-chevron-left fa-w-10" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path fill="currentColor" d="M34.52 239.03L228.87 44.69c9.37-9.37 24.57-9.37 33.94 0l22.67 22.67c9.36 9.36 9.37 24.52.04 33.9L131.49 256l154.02 154.75c9.34 9.38 9.32 24.54-.04 33.9l-22.67 22.67c-9.37 9.37-24.57 9.37-33.94 0L34.52 272.97c-9.37-9.37-9.37-24.57 0-33.94z"></path></svg>
|
After Width: | Height: | Size: 482 B |
1
resources/www/lightbox/images/chevron-right-solid.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="chevron-right" class="svg-inline--fa fa-chevron-right fa-w-10" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path fill="currentColor" d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"></path></svg>
|
After Width: | Height: | Size: 527 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="file-download" class="svg-inline--fa fa-file-download fa-w-12" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path fill="#2196f3" d="M224 136V0H24C10.7 0 0 10.7 0 24v464c0 13.3 10.7 24 24 24h336c13.3 0 24-10.7 24-24V160H248c-13.2 0-24-10.8-24-24zm76.45 211.36l-96.42 95.7c-6.65 6.61-17.39 6.61-24.04 0l-96.42-95.7C73.42 337.29 80.54 320 94.82 320H160v-80c0-8.84 7.16-16 16-16h32c8.84 0 16 7.16 16 16v80h65.18c14.28 0 21.4 17.29 11.27 27.36zM377 105L279.1 7c-4.5-4.5-10.6-7-17-7H256v128h128v-6.1c0-6.3-2.5-12.4-7-16.9z"></path></svg>
|
After Width: | Height: | Size: 625 B |
1
resources/www/lightbox/images/file-download-solid.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="file-download" class="svg-inline--fa fa-file-download fa-w-12" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path fill="#ffffff" d="M224 136V0H24C10.7 0 0 10.7 0 24v464c0 13.3 10.7 24 24 24h336c13.3 0 24-10.7 24-24V160H248c-13.2 0-24-10.8-24-24zm76.45 211.36l-96.42 95.7c-6.65 6.61-17.39 6.61-24.04 0l-96.42-95.7C73.42 337.29 80.54 320 94.82 320H160v-80c0-8.84 7.16-16 16-16h32c8.84 0 16 7.16 16 16v80h65.18c14.28 0 21.4 17.29 11.27 27.36zM377 105L279.1 7c-4.5-4.5-10.6-7-17-7H256v128h128v-6.1c0-6.3-2.5-12.4-7-16.9z"></path></svg>
|
After Width: | Height: | Size: 625 B |
1
resources/www/lightbox/images/home-solid.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="home" class="svg-inline--fa fa-home fa-w-18" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="#ffffff" d="M280.37 148.26L96 300.11V464a16 16 0 0 0 16 16l112.06-.29a16 16 0 0 0 15.92-16V368a16 16 0 0 1 16-16h64a16 16 0 0 1 16 16v95.64a16 16 0 0 0 16 16.05L464 480a16 16 0 0 0 16-16V300L295.67 148.26a12.19 12.19 0 0 0-15.3 0zM571.6 251.47L488 182.56V44.05a12 12 0 0 0-12-12h-56a12 12 0 0 0-12 12v72.61L318.47 43a48 48 0 0 0-61 0L4.34 251.47a12 12 0 0 0-1.6 16.9l25.5 31A12 12 0 0 0 45.15 301l235.22-193.74a12.19 12.19 0 0 1 15.3 0L530.9 301a12 12 0 0 0 16.9-1.6l25.5-31a12 12 0 0 0-1.7-16.93z"></path></svg>
|
After Width: | Height: | Size: 708 B |
1
resources/www/lightbox/images/pause-solid.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="pause" class="svg-inline--fa fa-pause fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M144 479H48c-26.5 0-48-21.5-48-48V79c0-26.5 21.5-48 48-48h96c26.5 0 48 21.5 48 48v352c0 26.5-21.5 48-48 48zm304-48V79c0-26.5-21.5-48-48-48h-96c-26.5 0-48 21.5-48 48v352c0 26.5 21.5 48 48 48h96c26.5 0 48-21.5 48-48z"></path></svg>
|
After Width: | Height: | Size: 444 B |
1
resources/www/lightbox/images/play-solid.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="play" class="svg-inline--fa fa-play fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M424.4 214.7L72.4 6.6C43.8-10.3 0 6.1 0 47.9V464c0 37.5 40.7 60.1 72.4 41.3l352-208c31.4-18.5 31.5-64.1 0-82.6z"></path></svg>
|
After Width: | Height: | Size: 339 B |
@@ -99,7 +99,7 @@ img {
|
|||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
}
|
}
|
||||||
.display_id {
|
.display_id {
|
||||||
top: 5px;
|
top: 0;
|
||||||
margin: 0 0 0 5px;
|
margin: 0 0 0 5px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,8 +134,8 @@ img {
|
|||||||
background-color: #212121;
|
background-color: #212121;
|
||||||
}
|
}
|
||||||
.display_id {
|
.display_id {
|
||||||
top: 4px;
|
top: 5px;
|
||||||
left: 8px;
|
left: 5px;
|
||||||
}
|
}
|
||||||
.agreement {
|
.agreement {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -173,7 +173,9 @@ img {
|
|||||||
|
|
||||||
.display_id {
|
.display_id {
|
||||||
background-color: #FFFFFF;
|
background-color: #FFFFFF;
|
||||||
padding: 3px 6px;
|
padding: 3.5px 6px;
|
||||||
|
min-width: 15px;
|
||||||
|
text-align: center;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
z-index: 99;
|
z-index: 99;
|
||||||
color: #212121;
|
color: #212121;
|
||||||
@@ -214,6 +216,28 @@ img {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background-color: #1F1E1B;
|
background-color: #1F1E1B;
|
||||||
color: #BFBFBF;
|
color: #BFBFBF;
|
||||||
|
.PNB.choices {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.comment_button {
|
||||||
|
text-align: center;
|
||||||
|
background: #353430;
|
||||||
|
margin: 0;
|
||||||
|
width: 118px;
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
padding: 7px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 14px;
|
||||||
|
border: 0;
|
||||||
|
bottom: -30px;
|
||||||
|
.fa-comment.icon-white {
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 18px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#basket_options {
|
#basket_options {
|
||||||
@@ -230,6 +254,11 @@ img {
|
|||||||
#basket_infos .user_infos {
|
#basket_infos .user_infos {
|
||||||
height: 120px;
|
height: 120px;
|
||||||
top: auto;
|
top: auto;
|
||||||
|
bottom: 43px;
|
||||||
|
}
|
||||||
|
.lightbox-icon {
|
||||||
|
width: 10px;
|
||||||
|
padding-bottom: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#basket_infos {
|
#basket_infos {
|
||||||
@@ -284,7 +313,7 @@ img {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#right_column .right_column_wrapper {
|
#right_column .right_column_wrapper {
|
||||||
//top: 30px;
|
top: 30px;
|
||||||
bottom: 45px;
|
bottom: 45px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,6 +325,7 @@ img {
|
|||||||
#record_infos {
|
#record_infos {
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
margin-bottom: 80px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#record_compare {
|
#record_compare {
|
||||||
@@ -303,7 +333,10 @@ img {
|
|||||||
top: auto;
|
top: auto;
|
||||||
left: auto;
|
left: auto;
|
||||||
}
|
}
|
||||||
|
.download-feed{
|
||||||
|
color: #fff;
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
#record_compare .header, #record_compare .lightbox_container {
|
#record_compare .header, #record_compare .lightbox_container {
|
||||||
left: 5px;
|
left: 5px;
|
||||||
}
|
}
|
||||||
@@ -546,10 +579,14 @@ table th i {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.basket_downloader {
|
.basket_downloader {
|
||||||
background-color: #1F1E1B;
|
background-color: #ffffff;
|
||||||
margin: 0 10px;
|
margin: 0 10px;
|
||||||
padding: 2px;
|
padding: 4px 0;
|
||||||
border: 0;
|
border: 0;
|
||||||
|
transition: 0.3s all;
|
||||||
|
&:hover {
|
||||||
|
background-color: #e6e6e6;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
@@ -562,6 +599,13 @@ hr {
|
|||||||
.report {
|
.report {
|
||||||
margin: 0 10px;
|
margin: 0 10px;
|
||||||
vertical-align: bottom;
|
vertical-align: bottom;
|
||||||
|
}.back-home {
|
||||||
|
margin: 0 10px;
|
||||||
|
vertical-align: bottom;
|
||||||
|
width: 20px;
|
||||||
|
background: #1F1E1B;
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -669,3 +713,25 @@ a.btn-info {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** End Lightbox summary modal**/
|
/** End Lightbox summary modal**/
|
||||||
|
|
||||||
|
.humane{
|
||||||
|
position: fixed;
|
||||||
|
z-index: 100000;
|
||||||
|
font-family: Ubuntu, Arial, sans-serif;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 15px;
|
||||||
|
top: 100px;
|
||||||
|
right: 70px;
|
||||||
|
width: 400px;
|
||||||
|
background: #2d2d72;
|
||||||
|
color: rgb(255, 255, 255);
|
||||||
|
box-shadow: rgb(0, 0, 0) 0px 4px 4px -4px;
|
||||||
|
transform: translateY(-40px);
|
||||||
|
transition: all 0.3s ease-out 0s;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text {
|
||||||
|
padding: 0!important;
|
||||||
|
}
|
@@ -1,3 +1,40 @@
|
|||||||
|
$blue-tsr: #2196f3;
|
||||||
|
$grey-tsr: #aaa;
|
||||||
|
$iconsPath: '../../../assets/thesaurus/images/';
|
||||||
|
@mixin blue-btn {
|
||||||
|
color: #fff;
|
||||||
|
background: $blue-tsr;
|
||||||
|
padding: 5px;
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s;
|
||||||
|
border-color: darken($blue-tsr, 20%);
|
||||||
|
min-width: 120px;
|
||||||
|
margin: 0 10px;
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
&:hover {
|
||||||
|
background: darken($blue-tsr, 20%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin grey-btn {
|
||||||
|
color: #000;
|
||||||
|
background: $grey-tsr;
|
||||||
|
padding: 5px;
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s;
|
||||||
|
border-color: darken($grey-tsr, 20%);
|
||||||
|
min-width: 120px;
|
||||||
|
margin: 0 10px;
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
&:hover {
|
||||||
|
background: darken($grey-tsr, 20%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BODY, TD, INPUT {
|
BODY, TD, INPUT {
|
||||||
FONT-FAMILY: Verdana, Arial, helvetica, sans-serif;
|
FONT-FAMILY: Verdana, Arial, helvetica, sans-serif;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
@@ -8,11 +45,11 @@ FORM {
|
|||||||
margin: 0px;
|
margin: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
BODY.dialog {
|
.dialog {
|
||||||
background-color: ButtonFace;
|
background-color: ButtonFace;
|
||||||
}
|
}
|
||||||
|
|
||||||
BODY.dialog .x3Dbox {
|
.x3Dbox {
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
left: 0px;
|
left: 0px;
|
||||||
@@ -24,7 +61,7 @@ BODY.dialog .x3Dbox {
|
|||||||
border-right: 1px solid #ffffff;
|
border-right: 1px solid #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
BODY.dialog .x3Dbox .title {
|
.x3Dbox .title {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -9px;
|
top: -9px;
|
||||||
left: 20px;
|
left: 20px;
|
||||||
@@ -58,7 +95,7 @@ H3, H4 {
|
|||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.thbox {
|
.thbox {
|
||||||
BACKGROUND-COLOR: #ffffff;
|
BACKGROUND-COLOR: #ffffff;
|
||||||
border-top: 1px solid #d0d0d0;
|
border-top: 1px solid #d0d0d0;
|
||||||
border-left: 1px solid #d0d0d0;
|
border-left: 1px solid #d0d0d0;
|
||||||
@@ -69,7 +106,7 @@ DIV.thbox {
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.thbox .onglet {
|
.thbox .onglet {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -22px;
|
top: -22px;
|
||||||
left: 5px;
|
left: 5px;
|
||||||
@@ -87,20 +124,20 @@ DIV.thbox .onglet {
|
|||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.thbox HR {
|
.thbox HR {
|
||||||
COLOR: #d0d0d0;
|
COLOR: #d0d0d0;
|
||||||
height: 1px;
|
height: 1px;
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.glossaire {
|
.glossaire {
|
||||||
position: relative;
|
position: relative;
|
||||||
left: 4px;
|
left: 4px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.glossaire U {
|
.glossaire U {
|
||||||
position: relative;
|
position: relative;
|
||||||
left: 1px;
|
left: 1px;
|
||||||
TEXT-DECORATION: none;
|
TEXT-DECORATION: none;
|
||||||
@@ -116,30 +153,30 @@ DIV.glossaire U {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.glossaire U.nots {
|
.glossaire U.nots {
|
||||||
border: 1px solid #F0F0F0;
|
border: 1px solid #F0F0F0;
|
||||||
BACKGROUND-COLOR: #F0F0F0;
|
BACKGROUND-COLOR: #F0F0F0;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.glossaire DIV.S_ {
|
.glossaire .S_ {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
BACKGROUND-COLOR: #99a2d0;
|
BACKGROUND-COLOR: #99a2d0;
|
||||||
COLOR: #FFFFFF;
|
COLOR: #FFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.glossaire DIV.s_ {
|
.glossaire .s_ {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.glossaire DIV.r0_ {
|
.glossaire .r0_ {
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.glossaire DIV.r1_ {
|
.glossaire .r1_ {
|
||||||
COLOR: #FF4000;
|
COLOR: #FF4000;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.glossaire DIV.OB {
|
.glossaire .OB {
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
padding-top: 0px;
|
padding-top: 0px;
|
||||||
@@ -149,11 +186,11 @@ DIV.glossaire DIV.OB {
|
|||||||
border-bottom: 1px solid #cccccc;
|
border-bottom: 1px solid #cccccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.glossaire DIV.ob {
|
.glossaire .ob {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.glossaire DIV.hb {
|
.glossaire .hb {
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
padding-top: 0px;
|
padding-top: 0px;
|
||||||
@@ -163,46 +200,46 @@ DIV.glossaire DIV.hb {
|
|||||||
border-bottom: 1px solid #cccccc;
|
border-bottom: 1px solid #cccccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.glossaire DIV.ctroot {
|
.glossaire .ctroot {
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.glossaire P.sy {
|
.glossaire P.sy {
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.glossaire P.ta {
|
.glossaire P.ta {
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.glossaire P.tc {
|
.glossaire P.tc {
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.glossaire P.tce {
|
.glossaire P.tce {
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.tableContainer {
|
.tableContainer {
|
||||||
margin: 2px;
|
margin: 2px;
|
||||||
border: 1px solid #000000;
|
border: 1px solid #000000;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.tableContainerDragOver {
|
.tableContainerDragOver {
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
border: 3px solid #99a2d0;
|
border: 3px solid #99a2d0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.tableContainer DIV.tbody {
|
.tableContainer .tbody {
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.tableContainer TABLE {
|
.tableContainer TABLE {
|
||||||
table-layout: fixed;
|
table-layout: fixed;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.tableContainer THEAD TH {
|
.tableContainer THEAD TH {
|
||||||
background: #e0ece8;
|
background: #e0ece8;
|
||||||
border-left: 1px solid #ffffff;
|
border-left: 1px solid #ffffff;
|
||||||
border-right: 1px solid #c0ccc8;
|
border-right: 1px solid #c0ccc8;
|
||||||
@@ -216,15 +253,15 @@ DIV.tableContainer THEAD TH {
|
|||||||
margin: 0px;
|
margin: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.tableContainer TBODY TR.s_ {
|
.tableContainer TBODY TR.s_ {
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.tableContainer TBODY TR.S_ {
|
.tableContainer TBODY TR.S_ {
|
||||||
BACKGROUND-COLOR: #99a2d0;
|
BACKGROUND-COLOR: #99a2d0;
|
||||||
COLOR: #FFFFFF;
|
COLOR: #FFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.tableContainer TBODY TD {
|
.tableContainer TBODY TD {
|
||||||
border-left: 1px solid #ffffff;
|
border-left: 1px solid #ffffff;
|
||||||
border-right: 1px solid #cccccc;
|
border-right: 1px solid #cccccc;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
@@ -235,77 +272,68 @@ DIV.tableContainer TBODY TD {
|
|||||||
margin: 0px;
|
margin: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.menu {
|
.menu {
|
||||||
FONT-FAMILY: Arial, helvetica, sans-serif;
|
FONT-FAMILY: Arial, helvetica, sans-serif;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
border-left: 1px solid #ffffff;
|
|
||||||
border-top: 1px solid #ffffff;
|
|
||||||
border-right: 2px solid #000000;
|
|
||||||
border-bottom: 2px solid #000000;
|
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0px;
|
top: 0;
|
||||||
left: 0px;
|
left: 0;
|
||||||
background-color: #d4d0c8;
|
background-color: #535353;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.menu IMG {
|
.menu IMG {
|
||||||
padding: 0px;
|
padding-right: 2px;
|
||||||
margin: 0px;
|
margin: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
left: -10px;
|
|
||||||
top: 2px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.menu A {
|
.menu p {
|
||||||
|
padding: 2px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu a {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
display: block;
|
display: block;
|
||||||
position: relative;
|
position: relative;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: #000000;
|
color: #fff;
|
||||||
padding-top: 1px;
|
padding: 5px 6px;
|
||||||
padding-bottom: 1px;
|
background-color: #535353;
|
||||||
padding-left: 13px;
|
|
||||||
padding-right: 3px;
|
|
||||||
overflow: hidden;
|
|
||||||
border: none 0px #FFFFFF;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.menu A:hover {
|
.menu A:hover {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
display: block;
|
display: block;
|
||||||
position: relative;
|
position: relative;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
background-color: #000080;
|
background-color: #884c92;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.menu A.disabled {
|
.menu A.disabled {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
display: block;
|
display: block;
|
||||||
position: relative;
|
position: relative;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: #A0A0A0;
|
color: lighten(#535353, 10%);
|
||||||
padding-top: 1px;
|
|
||||||
padding-bottom: 1px;
|
|
||||||
padding-left: 13px;
|
|
||||||
padding-right: 3px;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.menu A.disabled:hover {
|
.menu A.disabled:hover {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
display: block;
|
display: block;
|
||||||
position: relative;
|
position: relative;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: #A0A0A0;
|
color: lighten(#535353, 5%);
|
||||||
background-color: #d4d0c8;
|
background-color: #535353;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIV.menu .line {
|
.menu .line {
|
||||||
display: block;
|
display: block;
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 0px;
|
height: 0px;
|
||||||
@@ -316,3 +344,90 @@ DIV.menu .line {
|
|||||||
border-top: 1px solid #555555;
|
border-top: 1px solid #555555;
|
||||||
border-bottom: 1px solid #ffffff;
|
border-bottom: 1px solid #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#delete_sy {
|
||||||
|
background: orange;
|
||||||
|
border: 1px solid darken(orange,20%);
|
||||||
|
color: #fff;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 1px 10px;
|
||||||
|
margin-left: 12px;
|
||||||
|
&.disabled {
|
||||||
|
background: grey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#DLG_PROPERTIES > #syMenu {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thesaurus_confirm_bottom_block {
|
||||||
|
margin-top: 20px;
|
||||||
|
text-align: center;
|
||||||
|
#ifrsample & {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.thesaurus-page {
|
||||||
|
.validate_btn {
|
||||||
|
@include blue-btn;
|
||||||
|
}
|
||||||
|
.cancel_btn {
|
||||||
|
@include grey-btn;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
|
||||||
|
float: none;
|
||||||
|
}
|
||||||
|
.ui-dialog-buttonset {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.ui-button {
|
||||||
|
&:nth-child(1) {
|
||||||
|
@include grey-btn
|
||||||
|
}
|
||||||
|
&:nth-child(2) {
|
||||||
|
@include blue-btn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-center {
|
||||||
|
text-align: center;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.populate_btn {
|
||||||
|
position: absolute;
|
||||||
|
background: #884c92;
|
||||||
|
z-index: 2;
|
||||||
|
right: 50px;
|
||||||
|
top: 50px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #fff;
|
||||||
|
padding: 7px 10px;
|
||||||
|
font-weight: bold;
|
||||||
|
border: 1px solid #d0d0d0;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: darken(#884c92, 20%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.thesaurus-page {
|
||||||
|
.ui-widget-header {
|
||||||
|
border: 1px solid darken(#884c92, 20%);
|
||||||
|
background: #884c92;
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#flagsMenu p {
|
||||||
|
color: #fff;
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
@@ -35,6 +35,11 @@
|
|||||||
{{ 'admin::workermanager:tab:metadata: title' |trans }}
|
{{ 'admin::workermanager:tab:metadata: title' |trans }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="worker-queue-monitor" role="presentation">
|
||||||
|
<a href="#worker-queue-monitor" aria-controls="worker-queue-monitor" role="tab" data-toggle="tab" data-url="/admin/worker-manager/queue-monitor">
|
||||||
|
{{ 'admin::workermanager:tab:queueMonitor: title' |trans }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -48,6 +53,7 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade" id="worker-pull-assets"></div>
|
<div role="tabpanel" class="tab-pane fade" id="worker-pull-assets"></div>
|
||||||
<div role="tabpanel" class="tab-pane fade" id="worker-subview"></div>
|
<div role="tabpanel" class="tab-pane fade" id="worker-subview"></div>
|
||||||
<div role="tabpanel" class="tab-pane fade" id="worker-metadata"></div>
|
<div role="tabpanel" class="tab-pane fade" id="worker-metadata"></div>
|
||||||
|
<div role="tabpanel" class="tab-pane fade" id="worker-queue-monitor"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@@ -42,7 +42,7 @@
|
|||||||
<table class="admintable">
|
<table class="admintable">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="sortable">{{ 'admin::workermanager:tab:workerinfo: databox_id' | trans }}</th>
|
<th class="sortable">{{ 'admin::workermanager:tab:workerinfo: databox_name' | trans }}</th>
|
||||||
<th class="sortable">{{ 'admin::workermanager:tab:workerinfo: record_id' | trans }}</th>
|
<th class="sortable">{{ 'admin::workermanager:tab:workerinfo: record_id' | trans }}</th>
|
||||||
<th class="sortable">{{ 'admin::workermanager:tab:workerinfo: work' | trans }}</th>
|
<th class="sortable">{{ 'admin::workermanager:tab:workerinfo: work' | trans }}</th>
|
||||||
<th class="sortable">{{ 'admin::workermanager:tab:workerinfo: work_on' | trans }}</th>
|
<th class="sortable">{{ 'admin::workermanager:tab:workerinfo: work_on' | trans }}</th>
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
|
|
||||||
{% for workerRow in workerRunningJob | sort | reverse %}
|
{% for workerRow in workerRunningJob | sort | reverse %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ workerRow.databoxId }}</td>
|
<td>{{ workerRow.databoxId | sbas_labels(app) }}</td>
|
||||||
<td>{{ workerRow.recordId }}</td>
|
<td>{{ workerRow.recordId }}</td>
|
||||||
<td>{{ workerRow.getWorkName }}</td>
|
<td>{{ workerRow.getWorkName }}</td>
|
||||||
<td>{{ workerRow.workOn }}</td>
|
<td>{{ workerRow.workOn }}</td>
|
||||||
|
@@ -0,0 +1,42 @@
|
|||||||
|
{% if not reload %}
|
||||||
|
<h1>{{ 'admin::workermanager:tab:queueMonitor: description' |trans }}</h1>
|
||||||
|
|
||||||
|
<button id="refresh-monitor" class="btn btn-success">
|
||||||
|
{{ 'admin::workermanager:tab:queueMonitor: Refresh list' |trans }}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<table class="admintable">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<th>{{ 'admin::workermanager:tab:queueMonitor: Message count' |trans }}</th>
|
||||||
|
<th>{{ 'admin::workermanager:tab:queueMonitor: Consumer count' |trans }}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody class="queue-list">
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{% for queueStatus in queuesStatus %}
|
||||||
|
<tr>
|
||||||
|
<th>{{ queueStatus.queueName }}</th>
|
||||||
|
<td>{{ queueStatus.messageCount }}</td>
|
||||||
|
<td>{{ queueStatus.consumerCount }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% if not reload %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
$("#refresh-monitor").on('click', function () {
|
||||||
|
$.ajax({
|
||||||
|
type: "GET",
|
||||||
|
url: "/admin/worker-manager/queue-monitor?reload=1",
|
||||||
|
success: function (data) {
|
||||||
|
$(".queue-list").empty().html(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endif %}
|
@@ -152,9 +152,8 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ _self.choose_title('download', choose_export_title, default_export_title) }}
|
{{ _self.choose_title('download', choose_export_title, default_export_title) }}
|
||||||
|
|
||||||
{% if app['conf'].get(['registry', 'actions', 'tou-validation-required-for-export']) == true %}
|
{% if app['conf'].get(['registry', 'actions', 'tou-validation-required-for-export']) == true %}
|
||||||
<div class="well-small">
|
<div class="well-small acceptDl-info">
|
||||||
<label for="TOU_acceptDL" class="checkbox">
|
<label for="TOU_acceptDL" class="checkbox">
|
||||||
<input type="checkbox" name="TOU_accept" id="TOU_acceptDL" value="1" />
|
<input type="checkbox" name="TOU_accept" id="TOU_acceptDL" value="1" />
|
||||||
{% set beginning_link = '<a href="' ~ path('get_tou') ~ '" class="TOUview">' %}
|
{% set beginning_link = '<a href="' ~ path('get_tou') ~ '" class="TOUview">' %}
|
||||||
@@ -177,21 +176,27 @@
|
|||||||
<input type="hidden" name="lst" value="{{lst}}"/>
|
<input type="hidden" name="lst" value="{{lst}}"/>
|
||||||
<input type="hidden" name="ssttid" value="{{ssttid}}"/>
|
<input type="hidden" name="ssttid" value="{{ssttid}}"/>
|
||||||
<div>
|
<div>
|
||||||
{{ 'export::mail: destinataire' | trans }}
|
<span style="min-width: 21px;display: inline-block; ">
|
||||||
|
{{ 'export::mail: destinataire' | trans }}</span>
|
||||||
<input type="text" value="" name="destmail" class="required span4">
|
<input type="text" value="" name="destmail" class="required span4">
|
||||||
|
<div class="acceptDl-info" style="padding-top: 4px; margin-left: 25px;">
|
||||||
|
<span style="font-style: italic">{{ 'Entrez plusieurs adresses email en les separant par des points-virgules' | trans }}</span>
|
||||||
|
</div>
|
||||||
{% set my_email = app.getAuthenticatedUser().getEmail() %}
|
{% set my_email = app.getAuthenticatedUser().getEmail() %}
|
||||||
{% if my_email != '' %}
|
<div class="acceptDl-info">
|
||||||
<label class="checkbox">
|
{% if my_email != '' %}
|
||||||
<input type="checkbox" name="reading_confirm" value="1" />
|
<label class="checkbox">
|
||||||
{% trans with {'%my_email%' : my_email} %}Recevoir un accuse de reception a %my_email%{% endtrans %}
|
<input type="checkbox" name="reading_confirm" value="1" />
|
||||||
</label>
|
{% trans with {'%my_email%' : my_email} %}Recevoir un accuse de reception a %my_email%{% endtrans %}
|
||||||
{% else %}
|
</label>
|
||||||
<label class="checkbox">
|
{% else %}
|
||||||
{{ 'Accuse de reception indisponible, vous n\'avez pas declare d\'adresse email' | trans }}
|
<label class="checkbox">
|
||||||
<input type="checkbox" name="reading_confirm" value="1" readonly />
|
{{ 'Accuse de reception indisponible, vous n\'avez pas declare d\'adresse email' | trans }}
|
||||||
</label>
|
<input type="checkbox" name="reading_confirm" value="1" readonly />
|
||||||
{% endif %}
|
</label>
|
||||||
<span style="font-style: italic; color: #999999;">{{ 'Entrez plusieurs adresses email en les separant par des points-virgules' | trans }}</span>
|
{% endif %}
|
||||||
|
<span style="font-style: italic; color: #999999;">{{ 'export:email:: acknowledgement info' | trans }}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p>{{ 'export::mail: contenu du mail' | trans }}</p>
|
<p>{{ 'export::mail: contenu du mail' | trans }}</p>
|
||||||
@@ -235,7 +240,7 @@
|
|||||||
{{ _self.choose_title('sendmail', choose_export_title, default_export_title) }}
|
{{ _self.choose_title('sendmail', choose_export_title, default_export_title) }}
|
||||||
|
|
||||||
{% if app['conf'].get(['registry', 'actions', 'tou-validation-required-for-export']) == true %}
|
{% if app['conf'].get(['registry', 'actions', 'tou-validation-required-for-export']) == true %}
|
||||||
<div class="well-small">
|
<div class="well-small acceptDl-info">
|
||||||
<label for="TOU_acceptMail" class="checkbox">
|
<label for="TOU_acceptMail" class="checkbox">
|
||||||
<input type="checkbox" name="TOU_accept" id="TOU_acceptMail" value="1" />
|
<input type="checkbox" name="TOU_accept" id="TOU_acceptMail" value="1" />
|
||||||
{% set beginning_link = '<a href="' ~ path('get_tou') ~ '" class="TOUview">' %}
|
{% set beginning_link = '<a href="' ~ path('get_tou') ~ '" class="TOUview">' %}
|
||||||
@@ -388,7 +393,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if app['conf'].get(['registry', 'actions', 'tou-validation-required-for-export']) == true %}
|
{% if app['conf'].get(['registry', 'actions', 'tou-validation-required-for-export']) == true %}
|
||||||
<div class="well-small">
|
<div class="well-small acceptDl-info">
|
||||||
<label for="TOU_acceptOrder" class="checkbox">
|
<label for="TOU_acceptOrder" class="checkbox">
|
||||||
<input type="checkbox" name="TOU_accept" id="TOU_acceptOrder" value="1" />
|
<input type="checkbox" name="TOU_accept" id="TOU_acceptOrder" value="1" />
|
||||||
{% set beginning_link = '<a href="' ~ path('get_tou') ~ '" class="TOUview">' %}
|
{% set beginning_link = '<a href="' ~ path('get_tou') ~ '" class="TOUview">' %}
|
||||||
@@ -469,7 +474,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if app['conf'].get(['registry', 'actions', 'tou-validation-required-for-export']) == true %}
|
{% if app['conf'].get(['registry', 'actions', 'tou-validation-required-for-export']) == true %}
|
||||||
<div class="well-small">
|
<div class="well-small acceptDl-info">
|
||||||
<label for="TOU_acceptFTP" class="checkbox">
|
<label for="TOU_acceptFTP" class="checkbox">
|
||||||
<input type="checkbox" name="TOU_accept" id="TOU_acceptFTP" value="1" />
|
<input type="checkbox" name="TOU_accept" id="TOU_acceptFTP" value="1" />
|
||||||
{% set beginning_link = '<a href="' ~ path('get_tou') ~ '" class="TOUview">' %}
|
{% set beginning_link = '<a href="' ~ path('get_tou') ~ '" class="TOUview">' %}
|
||||||
|
@@ -232,7 +232,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a target="_blank" href="https://docs.phraseanet.com/4.0/">
|
<a target="_blank" href="{{ 'https://docs.phraseanet.com/4.1/' ~ app['locale'] }}">
|
||||||
<span>
|
<span>
|
||||||
{{ 'phraseanet:: aide' | trans }}
|
{{ 'phraseanet:: aide' | trans }}
|
||||||
</span>
|
</span>
|
||||||
|
@@ -47,4 +47,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if basket_element.getBasket().getValidation() %}
|
||||||
|
<button class="comment_button btn btn-mini btn-inverse">
|
||||||
|
<i class="fa fa-comment icon-white" aria-hidden="true"></i>
|
||||||
|
{% set n = 0 %}
|
||||||
|
{% for validationData in basket_element.getValidationDatas() %}
|
||||||
|
{% if validationData.getNote() %}
|
||||||
|
{% set n = n+1 %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{{ n }}
|
||||||
|
</button>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
@@ -92,11 +92,12 @@
|
|||||||
<div class="PNB" style="height:30px;bottom:auto;">
|
<div class="PNB" style="height:30px;bottom:auto;">
|
||||||
<table border="0" cellspacing="0" cellpadding="0" style="width:100%;">
|
<table border="0" cellspacing="0" cellpadding="0" style="width:100%;">
|
||||||
<tr>
|
<tr>
|
||||||
<td style="width:20px;">
|
<td style="width:50px;">
|
||||||
|
<a href="/lightbox"><img title="{{ 'lightbox::recaptitulatif' | trans }}" class="back-home" src="/assets/lightbox/images/home-solid.svg"/></a>
|
||||||
</td>
|
</td>
|
||||||
<td style="width:40px;">
|
<td style="width:40px;">
|
||||||
<button class="ui-corner-all basket_downloader" title="{{ 'boutton::telecharger tous les documents' | trans }}">
|
<button class="ui-corner-all basket_downloader" title="{{ 'boutton::telecharger tous les documents' | trans }}">
|
||||||
<img src="/assets/lightbox/images/save.png"/>
|
<img width="15" src="/assets/lightbox/images/file-download-solid-blue.svg" >
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
@@ -1,25 +1,25 @@
|
|||||||
<span style="padding:10px 4px 7px;">
|
<span style="padding:10px 4px 7px;">
|
||||||
{% if feed_element %}
|
{% if feed_element %}
|
||||||
<button class="previous_button play btn btn-mini" title="{{ 'boutton::precedent' | trans }}">
|
<button class="previous_button play btn btn-mini" title="{{ 'boutton::precedent' | trans }}">
|
||||||
<i class="fa fa-chevron-left" aria-hidden="true"></i>
|
<img class="lightbox-icon" src="/assets/lightbox/images/chevron-left-solid.svg"/>
|
||||||
</button>
|
</button>
|
||||||
<button class="previous_button pause btn btn-mini btn-inverse" title="{{ 'boutton::precedent' | trans }}">
|
<button class="previous_button pause btn btn-mini btn-inverse" title="{{ 'boutton::precedent' | trans }}">
|
||||||
<i class="fa fa-chevron-left icon-white" aria-hidden="true"></i>
|
<img class="lightbox-icon" src="/assets/lightbox/images/chevron-left-solid.svg"/>
|
||||||
</button>
|
</button>
|
||||||
<button class="play_button btn btn-mini" title="{{ 'boutton::demarrer' | trans }}">
|
<button class="play_button btn btn-mini" title="{{ 'boutton::demarrer' | trans }}">
|
||||||
<i class="fa fa-play" aria-hidden="true"></i>
|
<img class="lightbox-icon" src="/assets/lightbox/images/play-solid.svg"/>
|
||||||
</button>
|
</button>
|
||||||
<button class="pause_button btn btn-mini" title="{{ 'boutton::pause' | trans }}">
|
<button class="pause_button btn btn-mini" title="{{ 'boutton::pause' | trans }}">
|
||||||
<i class="fa fa-pause" aria-hidden="true"></i>
|
<img class="lightbox-icon" src="/assets/lightbox/images/pause-solid.svg"/>
|
||||||
</button>
|
</button>
|
||||||
<button class="next_button play btn btn-mini" title="{{ 'boutton::suivant' | trans }}">
|
<button class="next_button play btn btn-mini" title="{{ 'boutton::suivant' | trans }}">
|
||||||
<i class="fa fa-chevron-right" aria-hidden="true"></i>
|
<img class="lightbox-icon" src="/assets/lightbox/images/chevron-right-solid.svg"/>
|
||||||
</button>
|
</button>
|
||||||
<button class="next_button pause btn btn-mini btn-inverse" title="{{ 'boutton::suivant' | trans }}">
|
<button class="next_button pause btn btn-mini btn-inverse" title="{{ 'boutton::suivant' | trans }}">
|
||||||
<i class="fa fa-chevron-right icon-white" aria-hidden="true"></i>
|
<img class="lightbox-icon" src="/assets/lightbox/images/chevron-right-solid.svg"/>
|
||||||
</button>
|
</button>
|
||||||
<button class="download_button btn btn-mini btn-inverse" title="{{ 'boutton::telecharger' | trans }}">
|
<button class="download_button btn btn-mini btn-inverse" title="{{ 'boutton::telecharger' | trans }}">
|
||||||
<i class="fa fa-arrow-circle-o-down icon-white" aria-hidden="true"></i>
|
<img class="lightbox-icon" src="/assets/lightbox/images/file-download-solid.svg"/>
|
||||||
</button>
|
</button>
|
||||||
<form name="download_form" style="display:none;">
|
<form name="download_form" style="display:none;">
|
||||||
<input type="hidden" name="basrec" value="{{feed_element.getRecord(app).get_serialize_key()}}"/>
|
<input type="hidden" name="basrec" value="{{feed_element.getRecord(app).get_serialize_key()}}"/>
|
||||||
|
@@ -11,10 +11,6 @@
|
|||||||
<link type="text/css" rel="stylesheet" href="/assets/lightbox/css/lightbox{% if not app.debug %}.min{% endif %}.css" media="screen"/>
|
<link type="text/css" rel="stylesheet" href="/assets/lightbox/css/lightbox{% if not app.debug %}.min{% endif %}.css" media="screen"/>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block icon %}
|
|
||||||
<link rel="shortcut icon" type="image/x-icon" href="/assets/lightbox/images/favicon.ico">
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div id="main_index" style="margin-top:50px;">
|
<div id="main_index" style="margin-top:50px;">
|
||||||
<table id="main_wrapper" cellspacing="0" cellpadding="0">
|
<table id="main_wrapper" cellspacing="0" cellpadding="0">
|
||||||
|
@@ -1,5 +1,8 @@
|
|||||||
{% extends "common/index_bootstrap.html.twig" %}
|
{% extends "common/index_bootstrap.html.twig" %}
|
||||||
|
|
||||||
|
{% block icon %}
|
||||||
|
<link rel="shortcut icon" type="image/x-icon" href="/assets/lightbox/images/favicon.ico">
|
||||||
|
{% endblock %}
|
||||||
{% block extra_content %}
|
{% block extra_content %}
|
||||||
<div id="DIALOG"></div>
|
<div id="DIALOG"></div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@@ -1,42 +1,31 @@
|
|||||||
<span style="padding:10px 4px 7px;">
|
<span style="padding:10px 4px 7px;">
|
||||||
{% if basket_element %}
|
{% if basket_element %}
|
||||||
<button class="previous_button play btn btn-mini" title="{{ 'boutton::precedent' | trans }}">
|
<button class="previous_button play btn btn-mini" title="{{ 'boutton::precedent' | trans }}">
|
||||||
<i class="fa fa-chevron-left" aria-hidden="true"></i>
|
<img class="lightbox-icon" src="/assets/lightbox/images/chevron-left-solid.svg"/>
|
||||||
</button>
|
</button>
|
||||||
<button class="previous_button pause btn btn-mini btn-inverse" title="{{ 'boutton::precedent' | trans }}" style="display:none">
|
<button class="previous_button pause btn btn-mini btn-inverse" title="{{ 'boutton::precedent' | trans }}" style="display:none">
|
||||||
<i class="fa fa-chevron-left icon-white" aria-hidden="true"></i>
|
<img class="lightbox-icon" src="/assets/lightbox/images/chevron-left-solid.svg"/>
|
||||||
</button>
|
</button>
|
||||||
<button class="play_button btn btn-mini" title="{{ 'boutton::demarrer' | trans }}">
|
<button class="play_button btn btn-mini" title="{{ 'boutton::demarrer' | trans }}">
|
||||||
<i class="fa fa-play" aria-hidden="true"></i>
|
<img class="lightbox-icon" src="/assets/lightbox/images/play-solid.svg"/>
|
||||||
</button>
|
</button>
|
||||||
<button class="pause_button btn btn-mini" title="{{ 'boutton::pause' | trans }}" style="display:none">
|
<button class="pause_button btn btn-mini" title="{{ 'boutton::pause' | trans }}" style="display:none">
|
||||||
<i class="fa fa-pause" aria-hidden="true"></i>
|
<img class="lightbox-icon" src="/assets/lightbox/images/pause-solid.svg"/>
|
||||||
</button>
|
</button>
|
||||||
<button class="next_button play btn btn-mini" title="{{ 'boutton::suivant' | trans }}">
|
<button class="next_button play btn btn-mini" title="{{ 'boutton::suivant' | trans }}">
|
||||||
<i class="fa fa-chevron-right" aria-hidden="true"></i>
|
<img class="lightbox-icon" src="/assets/lightbox/images/chevron-right-solid.svg"/>
|
||||||
</button>
|
</button>
|
||||||
<button class="next_button pause btn btn-mini btn-inverse" title="{{ 'boutton::suivant' | trans }}" style="display:none">
|
<button class="next_button pause btn btn-mini btn-inverse" title="{{ 'boutton::suivant' | trans }}" style="display:none">
|
||||||
<i class="fa fa-chevron-right icon-white" aria-hidden="true"></i>
|
<img class="lightbox-icon" src="/assets/lightbox/images/chevron-right-solid.svg"/>
|
||||||
</button>
|
</button>
|
||||||
<button class="download_button btn btn-mini btn-inverse" title="{{ 'boutton::telecharger' | trans }}">
|
<button class="download_button btn btn-mini btn-inverse" title="{{ 'boutton::telecharger' | trans }}">
|
||||||
<i class="fa fa-arrow-circle-o-down icon-white" aria-hidden="true"></i>
|
<img class="lightbox-icon" src="/assets/lightbox/images/file-download-solid.svg"/>
|
||||||
</button>
|
</button>
|
||||||
<form name="download_form" style="display:none;">
|
<form name="download_form" style="display:none;">
|
||||||
<input type="hidden" name="basrec" value="{{basket_element.getRecord(app).get_serialize_key()}}"/>
|
<input type="hidden" name="basrec" value="{{basket_element.getRecord(app).get_serialize_key()}}"/>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
|
||||||
{% if basket_element.getBasket().getValidation() %}
|
|
||||||
<button class="comment_button btn btn-mini btn-inverse">
|
|
||||||
<i class="fa fa-pencil-square-o icon-white" aria-hidden="true"></i>
|
|
||||||
{% set n = 0 %}
|
|
||||||
{% for validationData in basket_element.getValidationDatas() %}
|
|
||||||
{% if validationData.getNote() %}
|
|
||||||
{% set n = n+1 %}
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{{ n }}
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
{% set basket_element = basket.getElements().first() %}
|
{% set basket_element = basket.getElements().first() %}
|
||||||
<div class="PNB10">
|
<div class="PNB10">
|
||||||
|
<input type="hidden" id="export-send-mail-notif" value="{{ 'prod::export: send mail notification' | trans }} ">
|
||||||
<div class="PNB" id="top_container">
|
<div class="PNB" id="top_container">
|
||||||
<div id="record_wrapper" class="PNB single" style="right:250px;">
|
<div id="record_wrapper" class="PNB single" style="right:250px;">
|
||||||
<div id="record_main" class="PNB record_display_box" style="bottom:auto;right:auto;">
|
<div id="record_main" class="PNB record_display_box" style="bottom:auto;right:auto;">
|
||||||
@@ -155,11 +156,10 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td style="width:20px;">
|
<td style="width:20px;">
|
||||||
</td>
|
</td>
|
||||||
{% if basket.getValidation() %}
|
|
||||||
<td style="width:50px;">
|
<td style="width:50px;">
|
||||||
<img title="{{ 'lightbox::recaptitulatif' | trans }}" class="report" src="/assets/lightbox/images/retour.png"/>
|
<a href="/lightbox"><img title="{{ 'lightbox::recaptitulatif' | trans }}" class="back-home" src="/assets/lightbox/images/home-solid.svg"/></a>
|
||||||
</td>
|
</td>
|
||||||
{% endif %}
|
|
||||||
<td style="width:220px;">
|
<td style="width:220px;">
|
||||||
<select id="navigation" style='margin:0'>
|
<select id="navigation" style='margin:0'>
|
||||||
<optgroup label="{{ 'Validations' | trans }}">
|
<optgroup label="{{ 'Validations' | trans }}">
|
||||||
@@ -182,7 +182,7 @@
|
|||||||
</td>
|
</td>
|
||||||
<td style="width:50px;">
|
<td style="width:50px;">
|
||||||
<button style='width:30px;margin:0;' class="ui-corner-all basket_downloader" title="{{ 'boutton::telecharger tous les documents' | trans }}">
|
<button style='width:30px;margin:0;' class="ui-corner-all basket_downloader" title="{{ 'boutton::telecharger tous les documents' | trans }}">
|
||||||
<img src="/assets/lightbox/images/save.png"/>
|
<img width="15" src="/assets/lightbox/images/file-download-solid-blue.svg" >
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<div class="PNB">
|
<div class="PNB">
|
||||||
<div class="PNB header" style="height:40px;bottom:auto;">
|
<div class="PNB header" style="height:40px;bottom:auto;">
|
||||||
<table>
|
<table class="detailed_basket_browser">
|
||||||
<tr>
|
<tr>
|
||||||
<td style="width:230px;">
|
<td style="width:230px;">
|
||||||
<a href="#" class="back">
|
<a href="#" class="back">
|
||||||
@@ -23,9 +23,9 @@
|
|||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a class="basket_link" href="#">
|
<span class="basket_link" title="{{ Basket.getName() }}">
|
||||||
{{ Basket.getName() }}
|
{{ Basket.getName()|length > 55 ? Basket.getName()|slice(0, 52) ~ '...' : Basket.getName() }}
|
||||||
</a>
|
</span>
|
||||||
</h1>
|
</h1>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@@ -40,8 +40,8 @@
|
|||||||
|
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a class="basket_link" href="{{ path('prod_workzone_basket', { basket : Basket.getId() }) }}">
|
<a title="{{ Basket.getName()}}" class="basket_link" href="{{ path('prod_workzone_basket', { basket : Basket.getId() }) }}">
|
||||||
<span>{{ Basket.getName() }}</span>
|
<span> {{ Basket.getName()|length > 80 ? Basket.getName()|slice(0, 77) ~ '...' : Basket.getName() }}</span>
|
||||||
<br><span class="basketCount">
|
<br><span class="basketCount">
|
||||||
{{ Basket.getElements().count() }} {{ ' records' }}
|
{{ Basket.getElements().count() }} {{ ' records' }}
|
||||||
</span></a>
|
</span></a>
|
||||||
|
@@ -29,6 +29,16 @@
|
|||||||
{{ "video range extractor" | trans }}
|
{{ "video range extractor" | trans }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="#subtitleEditor" class="subtitleEditortoggle">
|
||||||
|
{{ "prod:videoeditor:subtitleTab:: title" | trans }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="#subtitleRequest" class="subtitleEditortoggle">
|
||||||
|
{{ "prod:videoeditor:subtitleRequestTab:: title" | trans }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -82,7 +92,9 @@
|
|||||||
</video>
|
</video>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="videotools-spinner ui-widget-overlay ui-front hidden" id="videotools-spinner" style="opacity: 0.9">
|
||||||
|
<img src="/assets/common/images/icons/loading.svg" alt="" id="gif-loader">
|
||||||
|
</div>
|
||||||
<div id="thumb_camera_button"></div>
|
<div id="thumb_camera_button"></div>
|
||||||
|
|
||||||
<div class="vertical-divider"></div>
|
<div class="vertical-divider"></div>
|
||||||
@@ -158,6 +170,108 @@
|
|||||||
<div id="rangeExtractor" class="">
|
<div id="rangeExtractor" class="">
|
||||||
<div class="video-range-editor-container"></div>
|
<div class="video-range-editor-container"></div>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="subtitleEditor" class="subtitleEditor video-subtitle-editor-container">
|
||||||
|
<input type="hidden" id="defaultStartValue" value="00:00:00.000">
|
||||||
|
<input type="hidden" id="defaultEndValue" value="00:00:02.000">
|
||||||
|
<div id="default-item" class="default-item hide">
|
||||||
|
<fieldset class='video-subtitle-item'><span class='number'>0</span>
|
||||||
|
<div class='item-field start-time' ><label>{{ "prod:videoeditor:subtitletab:: Start time" | trans }}</label><input class='time startTime' type='text' name='startTime' size='12' value="00:00:00.000"/></div>
|
||||||
|
<div class='item-field end-time'><label>{{ "prod:videoeditor:subtitletab:: End time" | trans }}</label><input class='time endTime' type='text' name='endTime' size='12'value="00:00:02.000" /></div>
|
||||||
|
<div class='item-field show-for-time'><label>{{ "prod:videoeditor:subtitletab:: Show for" | trans }}</label><input class='showForTime' readonly type='text' size='12' value="00:00:02.000"/></div>
|
||||||
|
<div class='item-field caption-text'><textarea class="captionText" name='captionText' placeholder='{{ "prod:videoeditor:subtitletab:: Caption placeholder" | trans }}' rows='2' ></textarea></div>
|
||||||
|
<div class='remove-item'><i class='fa fa-times-circle'></i></div>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
<form name="video_subtitle_data" id="video-subtitle-data">
|
||||||
|
<div class="video-subtitle-top">
|
||||||
|
<label>{{ "prod:videoeditor:subtitletab:: work on" | trans }}</label>
|
||||||
|
<select name="meta_struct_id" id="metaStructId">
|
||||||
|
{% for videoTextTrackField in videoTextTrackFields %}
|
||||||
|
<option value="{{ videoTextTrackField.meta_struct_id}}">{{ videoTextTrackField.label}}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
{% for videoTextTrackField in videoTextTrackFields %}
|
||||||
|
<input type="hidden" id="caption_{{ videoTextTrackField.meta_struct_id}}" value='{{ videoTextTrackField.value}}' name='databox_id'>
|
||||||
|
{% endfor %}
|
||||||
|
<input type="text" id="record-vtt">
|
||||||
|
<input type="hidden" value='{{ record.get_sbas_id() }}' name='databox_id'>
|
||||||
|
<input type="hidden" value='{{ record.get_record_id() }}' name='record_id'>
|
||||||
|
<input type="hidden" id="no_caption" value='{{ "prod:videoeditor:subtitletab:: No caption message" | trans }}'>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<form name="video_subtitle_list" id="video-subtitle-list">
|
||||||
|
<div class="video-subtitle-bottom">
|
||||||
|
<div class="video-subtitle-left">
|
||||||
|
<div class="video-subtitle-left-inner">
|
||||||
|
<div class="fields-wrapper">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="video-subtitle-left-button">
|
||||||
|
<button type="button" id="submit-subtitle" class="btn submit-subtitle btn-blue">{{ "prod:videoeditor:subtitletab:: save" | trans }}</button>
|
||||||
|
<button type="button" id="copy-subtitle" class="btn copy-subtitle btn-blue">{{ "prod:videoeditor:subtitletab:: copy to clipboard" | trans }}</button>
|
||||||
|
<button class="add-subtitle-vtt" tabindex="0" type="button" aria-label="Add VTT" title = {{ "prod:videoeditor:subtitletab:: add caption" | trans }}>
|
||||||
|
<i class="fa fa-plus"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="video-subtitle-right" style="overflow: hidden;">
|
||||||
|
<div class="video-subtitle-wrapper">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div id ="subtitleRequest" class="subtitleRequest">
|
||||||
|
<div class="video-subtitle-bottom">
|
||||||
|
<div class="video-subtitle-left">
|
||||||
|
<div class="video-request-left-inner">
|
||||||
|
<form id="video-subtitle-request" class="video-subtitle-request">
|
||||||
|
<p class="item">
|
||||||
|
<label>{{ "prod:videoeditor:subtitleRequestTab:label:: Provider" | trans }}</label>
|
||||||
|
<select name="subtitleProvider" id="subtitle_provider">
|
||||||
|
<option value="Ginger">Ginger</option>
|
||||||
|
</select>
|
||||||
|
</p>
|
||||||
|
<p class="item">
|
||||||
|
<label>{{ "prod:videoeditor:subtitleRequestTab:label:: Kind" | trans }}</label>
|
||||||
|
<select name="subtitle_kindr" id="subtitle_kindr">
|
||||||
|
<option value="autosubtitling">{{ "prod:videoeditor:subtitleRequestTab:: Autosubtitling" | trans }}</option>
|
||||||
|
</select>
|
||||||
|
</p>
|
||||||
|
<p class="item">
|
||||||
|
<label>{{ "prod:videoeditor:subtitleRequestTab:label:: Source Audio language" | trans }}</label>
|
||||||
|
<select name="subtitle_language_source" id="subtitle_language_source">
|
||||||
|
{% for videoTextTrackField in videoTextTrackFields %}
|
||||||
|
<option value="{{ videoTextTrackField.meta_struct_id}}">{{ videoTextTrackField.label}}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</p>
|
||||||
|
<p class="item">
|
||||||
|
<label>{{ "prod:videoeditor:subtitleRequestTab:label:: Language destination" | trans }}</label>
|
||||||
|
<select name="subtitle_language_destination" id="subtitle_language_destination">
|
||||||
|
{% for videoTextTrackField in videoTextTrackFields %}
|
||||||
|
<option value="{{ videoTextTrackField.meta_struct_id}}">{{ videoTextTrackField.label}}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</p>
|
||||||
|
<div class="video-subtitle-center-button">
|
||||||
|
<button type="button" id="submit-subtitle-request" class="btn submit-subtitle btn-blue">{{ "prod:videoeditor:subtitleRequestTab:: submit" | trans }}</button>
|
||||||
|
</div>
|
||||||
|
<input type="hidden" value='{{ record.get_sbas_id() }}' name='record_sbas_id'>
|
||||||
|
<input type="hidden" value='{{ record.get_record_id() }}' name='record_record_id'>
|
||||||
|
<p class="text-center alert-wrapper hide" id="request-status">
|
||||||
|
<span class="alert alert-info">{{ "prod:videoeditor:subtitleRequestTab:: Request in process" | trans }}</span>
|
||||||
|
</p>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="video-subtitle-right">
|
||||||
|
<div class="video-subtitle-wrapper">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -173,7 +287,14 @@
|
|||||||
>
|
>
|
||||||
</iframe>
|
</iframe>
|
||||||
</div>
|
</div>
|
||||||
|
<style>
|
||||||
|
.video-subtitle-editor-container .number {
|
||||||
|
float: none;
|
||||||
|
}
|
||||||
|
.video-subtitle-editor-container .editing .number {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var toolsConfig = {
|
var toolsConfig = {
|
||||||
selectionLength: {{ selectionLength }},
|
selectionLength: {{ selectionLength }},
|
||||||
@@ -217,6 +338,8 @@
|
|||||||
{% for subdef in previewHtml5 %}
|
{% for subdef in previewHtml5 %}
|
||||||
{
|
{
|
||||||
ratio: '{{ ratio }}',
|
ratio: '{{ ratio }}',
|
||||||
|
width: '{{ width }}',
|
||||||
|
height: '{{ height }}',
|
||||||
framerate: {{ record.exif[constant('media_subdef::TC_DATA_FRAMERATE')] | round(2) }},
|
framerate: {{ record.exif[constant('media_subdef::TC_DATA_FRAMERATE')] | round(2) }},
|
||||||
type: "{{ subdef.get_mime() }}",
|
type: "{{ subdef.get_mime() }}",
|
||||||
src: "{{ subdef.get_url() }}"
|
src: "{{ subdef.get_url() }}"
|
||||||
@@ -231,6 +354,28 @@
|
|||||||
preferences: {
|
preferences: {
|
||||||
overlapChapters: {% if overlapChapters != NULL %}{{ overlapChapters }}{% else %}1{% endif %},
|
overlapChapters: {% if overlapChapters != NULL %}{{ overlapChapters }}{% else %}1{% endif %},
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$('#submit-subtitle-request').on('click', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
console.log("auto-subtitle process");
|
||||||
|
$.ajax({
|
||||||
|
type: 'POST',
|
||||||
|
url: '/prod/tools/auto-subtitle/',
|
||||||
|
dataType: 'json',
|
||||||
|
data: {
|
||||||
|
databox_id: {{ record.getDataboxId }},
|
||||||
|
record_id: {{ record.getRecordId }},
|
||||||
|
subtitle_language_source: $('#subtitle_language_source option:selected').text(),
|
||||||
|
meta_struct_id_source: $('#subtitle_language_source').val(),
|
||||||
|
subtitle_language_destination: $('#subtitle_language_destination option:selected').text(),
|
||||||
|
meta_struct_id_destination: $('#subtitle_language_destination').val()
|
||||||
|
},
|
||||||
|
success: function success(data) {
|
||||||
|
console.log(data);
|
||||||
|
$('#request-status').removeClass('hide');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
@@ -45,7 +45,7 @@
|
|||||||
<label for="feed_add_title"><b>{{ 'publication : titre' | trans }}</b> <span>( {{ 'publication : title warning' | trans }} )</span></label>
|
<label for="feed_add_title"><b>{{ 'publication : titre' | trans }}</b> <span>( {{ 'publication : title warning' | trans }} )</span></label>
|
||||||
<input class="required_text input-block-level" style="max-width:500px" type="text" name="title" id="feed_add_title" value="{{title}}" />
|
<input class="required_text input-block-level" style="max-width:500px" type="text" name="title" id="feed_add_title" value="{{title}}" />
|
||||||
<label><span class="feed_title_warning feed_warning">{{ 'publication : title alert' | trans }}</span></label>
|
<label><span class="feed_title_warning feed_warning">{{ 'publication : title alert' | trans }}</span></label>
|
||||||
<label for="feed_add_subtitle"><b>{{ 'publication : sous titre' | trans }}</b> <span class="feed_subtitle_warning feed_warning">{{ 'publication : subtitle warning' | trans }}</span></label>
|
<label for="feed_add_subtitle"><b>{{ 'publication : sous titre' | trans }}</b> <span>( {{ 'publication : subtitle warning' | trans }} )</span></label>
|
||||||
<textarea id="feed_add_subtitle" style="max-width:500px" class="input-block-level" name="subtitle" rows="5">{{desc}}</textarea>
|
<textarea id="feed_add_subtitle" style="max-width:500px" class="input-block-level" name="subtitle" rows="5">{{desc}}</textarea>
|
||||||
<label><span class="feed_subtitle_warning feed_warning">{{ 'publication : subtitle alert' | trans }}</span></label>
|
<label><span class="feed_subtitle_warning feed_warning">{{ 'publication : subtitle alert' | trans }}</span></label>
|
||||||
<label for="feed_add_author_name"><b>{{ 'publication : autheur' | trans }}</b></label>
|
<label for="feed_add_author_name"><b>{{ 'publication : autheur' | trans }}</b></label>
|
||||||
|
@@ -1015,6 +1015,7 @@
|
|||||||
<input type="hidden" id="push-new-list-title" value="{{ 'prod::push: New list title' | trans }} ">
|
<input type="hidden" id="push-new-list-title" value="{{ 'prod::push: New list title' | trans }} ">
|
||||||
<input type="hidden" id="push-list-name-empty" value="{{ 'prod::push: List name can not be empty' | trans }} ">
|
<input type="hidden" id="push-list-name-empty" value="{{ 'prod::push: List name can not be empty' | trans }} ">
|
||||||
<input type="hidden" id="btn-add" value="{{ 'prod::push: add' | trans }} ">
|
<input type="hidden" id="btn-add" value="{{ 'prod::push: add' | trans }} ">
|
||||||
|
<input type="hidden" id="export-send-mail-notif" value="{{ 'prod::export: send mail notification' | trans }} ">
|
||||||
<script type="text/javascript" id="bitly_loader"></script>
|
<script type="text/javascript" id="bitly_loader"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
|
@@ -22,25 +22,24 @@
|
|||||||
<script type="text/javascript" src="/assets/thesaurus/js/thesaurus{% if not app.debug %}.min{% endif %}.js"></script>
|
<script type="text/javascript" src="/assets/thesaurus/js/thesaurus{% if not app.debug %}.min{% endif %}.js"></script>
|
||||||
{#<script type="text/javascript" src="{{ path('minifier', { 'f' : 'skins/thesaurus/xmlhttp.js' }) }}"></script>#}
|
{#<script type="text/javascript" src="{{ path('minifier', { 'f' : 'skins/thesaurus/xmlhttp.js' }) }}"></script>#}
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
function loaded()
|
//$('.close-dialog').trigger('click');
|
||||||
{
|
|
||||||
window.name="ACCEPT";
|
|
||||||
self.focus();
|
|
||||||
}
|
|
||||||
function ok()
|
function ok()
|
||||||
{
|
{
|
||||||
as = "";
|
as = "";
|
||||||
if((n=document.forms[0].as.length) > 0)
|
if($(".as_1").length > 0)
|
||||||
{
|
{
|
||||||
for(i=0; i<n && as==""; i++)
|
if($(".as_1")[0].checked) {
|
||||||
{
|
as = $(".as_1").val();
|
||||||
if(document.forms[0].as[i].checked)
|
}
|
||||||
as = document.forms[0].as[i].value;
|
if($(".as_2").length > 0 && $(".as_2")[0].checked) {
|
||||||
}
|
as = $(".as_2").val();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
as = document.forms[0].as.value;
|
if($(".as_3").length > 0) {
|
||||||
|
as = $(".as_3").val();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(as == "TS")
|
if(as == "TS")
|
||||||
{
|
{
|
||||||
@@ -59,14 +58,13 @@
|
|||||||
switch(refresh.item(i).getAttribute("type"))
|
switch(refresh.item(i).getAttribute("type"))
|
||||||
{
|
{
|
||||||
case "CT":
|
case "CT":
|
||||||
{{ opener }}.reloadCtermsBranch(refresh.item(i).getAttribute("id"));
|
reloadCtermsBranch(refresh.item(i).getAttribute("id"));
|
||||||
break;
|
break;
|
||||||
case "TH":
|
case "TH":
|
||||||
{{ opener }}.reloadThesaurusBranch(refresh.item(i).getAttribute("id"));
|
reloadThesaurusBranch(refresh.item(i).getAttribute("id"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.close();
|
|
||||||
}
|
}
|
||||||
else if(as == "SY")
|
else if(as == "SY")
|
||||||
{
|
{
|
||||||
@@ -85,19 +83,23 @@
|
|||||||
switch(refresh.item(i).getAttribute("type"))
|
switch(refresh.item(i).getAttribute("type"))
|
||||||
{
|
{
|
||||||
case "CT":
|
case "CT":
|
||||||
{{ opener }}.reloadCtermsBranch(refresh.item(i).getAttribute("id"));
|
reloadCtermsBranch(refresh.item(i).getAttribute("id"));
|
||||||
break;
|
break;
|
||||||
case "TH":
|
case "TH":
|
||||||
{{ opener }}.reloadThesaurusBranch(refresh.item(i).getAttribute("id"));
|
reloadThesaurusBranch(refresh.item(i).getAttribute("id"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.close();
|
|
||||||
}
|
}
|
||||||
|
$('.close-dialog').trigger('click');
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeModal() {
|
||||||
|
$('.close-dialog').trigger('click');
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body id="desktop" onload="loaded();" class="dialog">
|
<body id="desktop" class="dialog">
|
||||||
|
|
||||||
{% if not cterm_found %}
|
{% if not cterm_found %}
|
||||||
<center>
|
<center>
|
||||||
@@ -109,11 +111,9 @@
|
|||||||
<br/>
|
<br/>
|
||||||
{{ 'thesaurus:: refresh' | trans }}
|
{{ 'thesaurus:: refresh' | trans }}
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<div class="thesaurus_confirm_bottom_block">
|
||||||
<br/>
|
<input type="button" class="cancel_btn" id="cancel_button" value="{{ 'boutton::fermer' | trans }}" onclick="closeModal();">
|
||||||
<br/>
|
</div>
|
||||||
<br/>
|
|
||||||
<input style="position:relative; z-index:2; width:100px" type="button" id="cancel_button" value="{{ 'boutton::fermer' | trans }}" onclick="self.close();">
|
|
||||||
{% else %}
|
{% else %}
|
||||||
{% if not term_found %}
|
{% if not term_found %}
|
||||||
<center>
|
<center>
|
||||||
@@ -125,11 +125,9 @@
|
|||||||
<br/>
|
<br/>
|
||||||
{{ 'thesaurus:: refresh' | trans }}
|
{{ 'thesaurus:: refresh' | trans }}
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<div class="thesaurus_confirm_bottom_block">
|
||||||
<br/>
|
<input type="button" class="cancel_btn" id="cancel_button" value="{{ 'boutton::fermer' | trans }}" onclick="closeModal();">
|
||||||
<br/>
|
</div>
|
||||||
<br/>
|
|
||||||
<input style="position:relative; z-index:2; width:100px" type="button" id="cancel_button" value="{{ 'boutton::fermer' | trans }}" onclick="self.close();">
|
|
||||||
{% else %}
|
{% else %}
|
||||||
{% if acceptable %}
|
{% if acceptable %}
|
||||||
<center>
|
<center>
|
||||||
@@ -144,9 +142,9 @@
|
|||||||
{{ 'thesaurus:: Accepter le terme comme' | trans }}
|
{{ 'thesaurus:: Accepter le terme comme' | trans }}
|
||||||
<br/><br/><h4>{{ fullpath_src | raw }}</h4><br/><br/>
|
<br/><br/><h4>{{ fullpath_src | raw }}</h4><br/><br/>
|
||||||
<br/>
|
<br/>
|
||||||
<input type='radio' name='as' value='TS' checked>{{ 'thesaurus:: comme terme specifique' | trans }}
|
<input type='radio' name='as' class="as_1" value='TS' checked>{{ 'thesaurus:: comme terme specifique' | trans }}
|
||||||
<br/><br/>
|
<br/><br/>
|
||||||
<input type='radio' name='as' value='SY'>
|
<input type='radio' name='as' class="as_2" value='SY'>
|
||||||
{% set fullpath_tgt_raw = fullpath_tgt | raw %}
|
{% set fullpath_tgt_raw = fullpath_tgt | raw %}
|
||||||
{% trans with {'%fullpath_tgt_raw%' : fullpath_tgt_raw} %}thesaurus:: comme synonyme de %fullpath_tgt_raw%{% endtrans %}
|
{% trans with {'%fullpath_tgt_raw%' : fullpath_tgt_raw} %}thesaurus:: comme synonyme de %fullpath_tgt_raw%{% endtrans %}
|
||||||
<br/>
|
<br/>
|
||||||
@@ -155,13 +153,12 @@
|
|||||||
{{ 'thesaurus:: Accepter la branche comme' | trans }}
|
{{ 'thesaurus:: Accepter la branche comme' | trans }}
|
||||||
{{ 'thesaurus:: comme terme specifique' | trans }}
|
{{ 'thesaurus:: comme terme specifique' | trans }}
|
||||||
<br/><br/><h4>{{ fullpath_tgt | raw }}</h4><br/><br/>
|
<br/><br/><h4>{{ fullpath_tgt | raw }}</h4><br/><br/>
|
||||||
<input type='hidden' name='as' value='TS'>
|
<input type='hidden' name='as' class="as_3" value='TS'>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<br/>
|
<div class="thesaurus_confirm_bottom_block">
|
||||||
<br/>
|
<input class="cancel_btn" type="button" id="cancel_button" value="{{ 'boutton::annuler' | trans }}" onclick="closeModal();">
|
||||||
<input style="position:relative; z-index:2; width:100px" type="button" id="ok_button" value="{{ 'boutton::valider' | trans }}" onclick="ok();">
|
<input class="validate_btn" type="button" id="ok_button" value="{{ 'boutton::valider' | trans }}" onclick="ok();">
|
||||||
|
</div>
|
||||||
<input style="position:relative; z-index:2; width:100px" type="button" id="cancel_button" value="{{ 'boutton::annuler' | trans }}" onclick="self.close();">
|
|
||||||
</form>
|
</form>
|
||||||
</center>
|
</center>
|
||||||
{% else %}
|
{% else %}
|
||||||
@@ -171,13 +168,9 @@
|
|||||||
<br/>
|
<br/>
|
||||||
{% trans with {'%cfield%' : cfield} %}thesaurus:: A cet emplacement du thesaurus , un candidat du champ %cfield% ne peut etre accepte{% endtrans %}
|
{% trans with {'%cfield%' : cfield} %}thesaurus:: A cet emplacement du thesaurus , un candidat du champ %cfield% ne peut etre accepte{% endtrans %}
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<div class="thesaurus_confirm_bottom_block">
|
||||||
<br/>
|
<input class="cancel_btn" type="button" id="cancel_button" value="{{ 'boutton::annuler' | trans }}" onclick="closeModal();">
|
||||||
<br/>
|
</div>
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
<input style="position:relative; z-index:2; width:100px" type="button" id="cancel_button" value="{{ 'boutton::annuler' | trans }}" onclick="self.close();">
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@@ -13,12 +13,13 @@
|
|||||||
switch(button)
|
switch(button)
|
||||||
{
|
{
|
||||||
case "submit":
|
case "submit":
|
||||||
document.forms[0].action = "export_" + format + ".php";
|
$('.export-form').attr('action',"export_" + format + ".php");
|
||||||
document.forms[0].submit();
|
$('.export-form').submit();
|
||||||
|
$('.close-dialog').trigger('click');
|
||||||
break;
|
break;
|
||||||
case "cancel":
|
case "cancel":
|
||||||
self.returnValue = null;
|
self.returnValue = null;
|
||||||
self.close();
|
$('.close-dialog').trigger('click');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -49,19 +50,22 @@
|
|||||||
{
|
{
|
||||||
var i, f;
|
var i, f;
|
||||||
url = "./export_"+format+".php?bid={{ bid }}&piv={{ piv }}&id={{ id }}&typ={{ typ }}&dlg=0&smp=1";
|
url = "./export_"+format+".php?bid={{ bid }}&piv={{ piv }}&id={{ id }}&typ={{ typ }}&dlg=0&smp=1";
|
||||||
url += "&osl=" + (document.forms[0].osl[0].checked ? "1" : "0");
|
url += "&osl=" + ($('.osl_1')[0].checked ? "1" : $('.osl_0')[0].checked ? "0" : "0");
|
||||||
url += "&iln=" + (document.forms[0].iln.checked ? "1" : "0");
|
url += "&iln=" + ($('.iln')[0].checked ? "1" : "0");
|
||||||
url += "&hit=" + (document.forms[0].hit.checked ? "1" : "0");
|
url += "&hit=" + ($('.hit')[0].checked ? "1" : "0");
|
||||||
url += "&ilg=" + (document.forms[0].ilg.checked ? "1" : "0");
|
url += "&ilg=" + ($('.ilg')[0].checked ? "1" : "0");
|
||||||
document.getElementById("ifrsample").src = url;
|
document.getElementById("ifrsample").src = url;
|
||||||
}
|
}
|
||||||
|
$( document ).ready(function() {
|
||||||
|
loaded();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body onload="loaded();" class="dialog">
|
<body class="dialog">
|
||||||
<center>
|
<center>
|
||||||
<br/>
|
<br/>
|
||||||
<form onsubmit="clkBut('submit');return(false);" action="export_topics.php" target="EXPORT2">
|
<form class="export-form" action="export_topics.php" target="EXPORT2">
|
||||||
<input type="hidden" name="bid" value="{{ bid }}" >
|
<input type="hidden" name="bid" value="{{ bid }}">
|
||||||
<input type="hidden" name="piv" value="{{ piv }}" >
|
<input type="hidden" name="piv" value="{{ piv }}" >
|
||||||
<input type="hidden" name="id" value="{{ id }}" >
|
<input type="hidden" name="id" value="{{ id }}" >
|
||||||
<input type="hidden" name="typ" value="{{ typ }}" >
|
<input type="hidden" name="typ" value="{{ typ }}" >
|
||||||
@@ -82,23 +86,23 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id='subform_text' style="margin-left:10px;">
|
<div id='subform_text' style="margin-left:10px;">
|
||||||
<div style="white-space:nowrap">
|
<div style="white-space:nowrap">
|
||||||
<input type='radio' name='osl' checked value='1' onclick="chgFormat();">
|
<input type='radio' name='osl' class="osl_1" checked value='1' onclick="chgFormat();">
|
||||||
{{ 'thesaurus:: exporter avec les synonymes sur la meme ligne' | trans }}
|
{{ 'thesaurus:: exporter avec les synonymes sur la meme ligne' | trans }}
|
||||||
</div>
|
</div>
|
||||||
<div style="white-space:nowrap">
|
<div style="white-space:nowrap">
|
||||||
<input type='radio' name='osl' value='0' onclick="chgFormat();">
|
<input type='radio' name='osl' class="osl_0" value='0' onclick="chgFormat();">
|
||||||
{{ 'thesaurus:: exporter avec une ligne par synonyme' | trans }}
|
{{ 'thesaurus:: exporter avec une ligne par synonyme' | trans }}
|
||||||
</div>
|
</div>
|
||||||
<div style="white-space:nowrap">
|
<div style="white-space:nowrap">
|
||||||
<input type='checkbox' name='iln' value='1' onclick="chgFormat();">
|
<input type='checkbox' name='iln' class="iln" value='1' onclick="chgFormat();">
|
||||||
{{ 'thesaurus:: export : numeroter les lignes' | trans }}
|
{{ 'thesaurus:: export : numeroter les lignes' | trans }}
|
||||||
</div>
|
</div>
|
||||||
<div style="white-space:nowrap">
|
<div style="white-space:nowrap">
|
||||||
<input type='checkbox' name='ilg' value='1' onclick="chgFormat();">
|
<input type='checkbox' name='ilg' class="ilg" value='1' onclick="chgFormat();">
|
||||||
{{ 'thesaurus:: export : inclure la langue' | trans }}
|
{{ 'thesaurus:: export : inclure la langue' | trans }}
|
||||||
</div>
|
</div>
|
||||||
<div style="white-space:nowrap">
|
<div style="white-space:nowrap">
|
||||||
<input type='checkbox' name='hit' value='1' onclick="chgFormat();">
|
<input type='checkbox' name='hit' class="hit" value='1' onclick="chgFormat();">
|
||||||
{{ 'thesaurus:: export : inclure les hits' | trans }}
|
{{ 'thesaurus:: export : inclure les hits' | trans }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -110,10 +114,11 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
|
||||||
<input type="button" id="cancel_button" value="{{ 'boutton::annuler' | trans }}" onclick="clkBut('cancel');" style="width:100px;">
|
<div class="thesaurus_confirm_bottom_block">
|
||||||
|
<input type="button" id="cancel_button" class="cancel_btn" value="{{ 'boutton::annuler' | trans }}" onclick="clkBut('cancel');">
|
||||||
<input type="button" id="submit_button" value="{{ 'boutton::valider' | trans }}" onclick="clkBut('submit');" style="width:100px;">
|
<input type="button" id="submit_button" class="validate_btn" value="{{ 'boutton::valider' | trans }}" onclick="clkBut('submit');">
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</center>
|
</center>
|
||||||
</body>
|
</body>
|
||||||
|
@@ -11,12 +11,12 @@
|
|||||||
switch(button)
|
switch(button)
|
||||||
{
|
{
|
||||||
case "submit":
|
case "submit":
|
||||||
document.forms[0].target = (format == 'tofiles' ? "_self" : "EXPORT2");
|
$('.export-topics-form').submit();
|
||||||
document.forms[0].submit();
|
$('.close-dialog').trigger('click');
|
||||||
break;
|
break;
|
||||||
case "cancel":
|
case "cancel":
|
||||||
self.returnValue = null;
|
self.returnValue = null;
|
||||||
self.close();
|
$('.close-dialog').trigger('click');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,21 +45,25 @@
|
|||||||
}
|
}
|
||||||
function chgFormat()
|
function chgFormat()
|
||||||
{
|
{
|
||||||
var i, f;
|
var i;
|
||||||
for(i=0; i<document.forms[0].ofm.length; i++)
|
for(i=0; i<$('.ofm').length; i++)
|
||||||
{
|
{
|
||||||
f = document.forms[0].ofm[i].value;
|
if($(".ofm_1")[0].checked) {
|
||||||
if(document.forms[0].ofm[i].checked)
|
format = $(".ofm_1").val();
|
||||||
{
|
}
|
||||||
format = f;
|
if($(".ofm_2")[0].checked) {
|
||||||
|
format = $(".ofm_2").val();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$( document ).ready(function() {
|
||||||
|
loaded();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body onload="loaded();" class="dialog">
|
<body class="dialog">
|
||||||
<center>
|
<center>
|
||||||
<form onsubmit="clkBut('submit');return(false);" action="export_topics.php">
|
<form action="export_topics.php" class="export-topics-form" target="EXPORT2">
|
||||||
<input type="hidden" name="bid" value="{{ bid }}" >
|
<input type="hidden" name="bid" value="{{ bid }}" >
|
||||||
<input type="hidden" name="piv" value="{{ piv }}" >
|
<input type="hidden" name="piv" value="{{ piv }}" >
|
||||||
<input type="hidden" name="id" value="{{ id }}" >
|
<input type="hidden" name="id" value="{{ id }}" >
|
||||||
@@ -67,15 +71,15 @@
|
|||||||
<input type="hidden" name="dlg" value="{{ dlg }}" >
|
<input type="hidden" name="dlg" value="{{ dlg }}" >
|
||||||
<input type="hidden" name="obr" value="{{ obr }}" >
|
<input type="hidden" name="obr" value="{{ obr }}" >
|
||||||
|
|
||||||
<div style="padding:10px;">
|
<div style="padding: 5px 15px">
|
||||||
<div class="x3Dbox">
|
<div class="x3Dbox">
|
||||||
<span class="title">{{ 'thesaurus:: exporter' | trans }}</span>
|
<span class="title">{{ 'thesaurus:: exporter' | trans }}</span>
|
||||||
<div style="white-space:nowrap">
|
<div style="white-space:nowrap">
|
||||||
<input type='radio' name='ofm' checked value='tofiles' onclick="chgFormat();">
|
<input type='radio' name='ofm' class="ofm ofm_1" checked value='tofiles' onclick="chgFormat();">
|
||||||
{{ 'thesaurus:: exporter vers topics pour toutes les langues' | trans }}
|
{{ 'thesaurus:: exporter vers topics pour toutes les langues' | trans }}
|
||||||
</div>
|
</div>
|
||||||
<div style="white-space:nowrap">
|
<div style="white-space:nowrap">
|
||||||
<input type='radio' name='ofm' value='toscreen' onclick="chgFormat();">
|
<input type='radio' name='ofm' value='toscreen' class="ofm ofm_2" onclick="chgFormat();">
|
||||||
{% trans with {'%piv%' : piv} %}thesaurus:: exporter a l'ecran pour la langue %piv%{% endtrans %}
|
{% trans with {'%piv%' : piv} %}thesaurus:: exporter a l'ecran pour la langue %piv%{% endtrans %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -85,7 +89,7 @@
|
|||||||
<div class="x3Dbox">
|
<div class="x3Dbox">
|
||||||
<span class="title">{{ 'phraseanet:: tri' | trans }}</span>
|
<span class="title">{{ 'phraseanet:: tri' | trans }}</span>
|
||||||
<div style="white-space:nowrap">
|
<div style="white-space:nowrap">
|
||||||
<input type='checkbox' name='srt' checked onclick="chgFormat();">
|
<input type='checkbox' name='srt' checked >
|
||||||
{{ 'phraseanet:: tri par date' | trans }}
|
{{ 'phraseanet:: tri par date' | trans }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -95,15 +99,15 @@
|
|||||||
<div class="x3Dbox">
|
<div class="x3Dbox">
|
||||||
<span class="title">{{ 'thesaurus:: recherche' | trans }}</span>
|
<span class="title">{{ 'thesaurus:: recherche' | trans }}</span>
|
||||||
<div style="white-space:nowrap">
|
<div style="white-space:nowrap">
|
||||||
<input type='radio' name='sth' value="1" checked onclick="chgFormat();">
|
<input type='radio' name='sth' value="1" checked >
|
||||||
{{ 'thesaurus:: recherche thesaurus *:"query"' | trans }}
|
{{ 'thesaurus:: recherche thesaurus *:"query"' | trans }}
|
||||||
</div>
|
</div>
|
||||||
<div style="white-space:nowrap">
|
<div style="white-space:nowrap">
|
||||||
<input type='radio' name='sth' value="0" onclick="chgFormat();">
|
<input type='radio' name='sth' value="0" >
|
||||||
{{ 'thesaurus:: recherche fulltext' | trans }}
|
{{ 'thesaurus:: recherche fulltext' | trans }}
|
||||||
</div>
|
</div>
|
||||||
<div style="white-space:nowrap">
|
<div style="white-space:nowrap">
|
||||||
<input type='checkbox' name='sand' onclick="chgFormat();">
|
<input type='checkbox' name='sand' >
|
||||||
{{ 'thesaurus:: question complete (avec operateurs)' | trans }}
|
{{ 'thesaurus:: question complete (avec operateurs)' | trans }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -113,30 +117,31 @@
|
|||||||
<div class="x3Dbox">
|
<div class="x3Dbox">
|
||||||
<span class="title">{{ 'thesaurus:: presentation' | trans }}</span>
|
<span class="title">{{ 'thesaurus:: presentation' | trans }}</span>
|
||||||
<div style="white-space:nowrap">
|
<div style="white-space:nowrap">
|
||||||
<input type='radio' name='obrf' value="from_itf_closable" checked onclick="chgFormat();">
|
<input type='radio' name='obrf' value="from_itf_closable" checked >
|
||||||
{{ 'thesaurus:: presentation : branches refermables' | trans }}
|
{{ 'thesaurus:: presentation : branches refermables' | trans }}
|
||||||
</div>
|
</div>
|
||||||
<div style="white-space:nowrap">
|
<div style="white-space:nowrap">
|
||||||
<input type='radio' name='obrf' value="from_itf_static" onclick="chgFormat();">
|
<input type='radio' name='obrf' value="from_itf_static" >
|
||||||
{{ 'thesaurus:: presentation : branche ouvertes' | trans }}
|
{{ 'thesaurus:: presentation : branche ouvertes' | trans }}
|
||||||
</div>
|
</div>
|
||||||
<div style="white-space:nowrap">
|
<div style="white-space:nowrap">
|
||||||
<input type='radio' name='obrf' value="all_opened_closable" onclick="chgFormat();">
|
<input type='radio' name='obrf' value="all_opened_closable" >
|
||||||
{{ 'thesaurus:: tout deployer - refermable' | trans }}
|
{{ 'thesaurus:: tout deployer - refermable' | trans }}
|
||||||
</div>
|
</div>
|
||||||
<div style="white-space:nowrap">
|
<div style="white-space:nowrap">
|
||||||
<input type='radio' name='obrf' value="all_opened_static" onclick="chgFormat();">
|
<input type='radio' name='obrf' value="all_opened_static" >
|
||||||
{{ 'thesaurus:: tout deployer - statique' | trans }}
|
{{ 'thesaurus:: tout deployer - statique' | trans }}
|
||||||
</div>
|
</div>
|
||||||
<div style="white-space:nowrap">
|
<div style="white-space:nowrap">
|
||||||
<input type='radio' name='obrf' value="all_closed" onclick="chgFormat();">
|
<input type='radio' name='obrf' value="all_closed" >
|
||||||
{{ 'thesaurus:: tout fermer' | trans }}
|
{{ 'thesaurus:: tout fermer' | trans }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<input type="button" id="cancel_button" value="{{ 'boutton::annuler' | trans }}" onclick="clkBut('cancel');" style="width:100px;">
|
<div class="thesaurus_confirm_bottom_block">
|
||||||
|
<input type="button" id="cancel_button" class="cancel_btn" value="{{ 'boutton::annuler' | trans }}" onclick="clkBut('cancel');">
|
||||||
<input type="button" id="submit_button" value="{{ 'boutton::valider' | trans }}" onclick="clkBut('submit');" style="width:100px;">
|
<input type="button" id="submit_button" class="validate_btn" value="{{ 'boutton::valider' | trans }}" onclick="clkBut('submit');">
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</center>
|
</center>
|
||||||
</body>
|
</body>
|
||||||
|
@@ -32,12 +32,9 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% if ofm == 'tofiles' %}
|
{% if ofm == 'tofiles' %}
|
||||||
<center>
|
<div class="thesaurus_confirm_bottom_block">
|
||||||
<br/>
|
<input type="button" class="cancel_btn" value="{{ 'boutton::fermer' | trans }}" onclick=" self.close();" style="width:120px;">
|
||||||
<br/>
|
</div>
|
||||||
<br/>
|
|
||||||
<input type="button" value="{{ 'boutton::fermer' | trans }}" onclick="self.close();" style="width:100px;">
|
|
||||||
</center>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
@@ -15,13 +15,12 @@
|
|||||||
{
|
{
|
||||||
switch(button)
|
switch(button)
|
||||||
{
|
{
|
||||||
case "submit":
|
case "submit":=
|
||||||
document.forms[0].target='IFRIM';
|
$('.import-form').submit();
|
||||||
document.forms[0].submit();
|
|
||||||
break;
|
break;
|
||||||
case "cancel":
|
case "cancel":
|
||||||
self.returnValue = null;
|
self.returnValue = null;
|
||||||
self.close();
|
$('.close-dialog').trigger('click');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -32,8 +31,7 @@
|
|||||||
{
|
{
|
||||||
if(!err)
|
if(!err)
|
||||||
{
|
{
|
||||||
{{ opener }}.reload();
|
$('.close-dialog').trigger('click');
|
||||||
self.close();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -44,7 +42,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body onload="loaded();" class="dialog">
|
<body onload="loaded();" class="dialog">
|
||||||
<br/>
|
<br/>
|
||||||
<form onsubmit="clkBut('submit');return(false);" action="import.php" enctype="multipart/form-data" method="post">
|
<form onsubmit="clkBut('submit');return(false);" action="import.php" enctype="multipart/form-data" method="post" class="import-form" target="IFRIM">
|
||||||
<input type="hidden" name="bid" value="{{ bid }}" >
|
<input type="hidden" name="bid" value="{{ bid }}" >
|
||||||
<input type="hidden" name="piv" value="{{ piv }}" >
|
<input type="hidden" name="piv" value="{{ piv }}" >
|
||||||
<input type="hidden" name="id" value="{{ id }}" >
|
<input type="hidden" name="id" value="{{ id }}" >
|
||||||
@@ -57,7 +55,7 @@
|
|||||||
<input type="file" name="fil" /> (max 16Mo)
|
<input type="file" name="fil" /> (max 16Mo)
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
<div style="text-align:center">
|
<div class="text-center">
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="text-align:left"><input type="checkbox" disabled="disabled" name="dlk" checked="checked">{{ 'thesaurus:: supprimer les liens des champs tbranch' | trans }}</td>
|
<td style="text-align:left"><input type="checkbox" disabled="disabled" name="dlk" checked="checked">{{ 'thesaurus:: supprimer les liens des champs tbranch' | trans }}</td>
|
||||||
@@ -67,10 +65,11 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<br/>
|
<br/>
|
||||||
<input type="button" id="cancel_button" value="{{ 'boutton::annuler' | trans }}" onclick="clkBut('cancel');" style="width:100px;">
|
<div class="thesaurus_confirm_bottom_block">
|
||||||
|
<input type="button" id="cancel_button" value="{{ 'boutton::annuler' | trans }}" onclick="clkBut('cancel');" >
|
||||||
<input type="button" id="submit_button" value="{{ 'boutton::valider' | trans }}" onclick="clkBut('submit');" style="width:100px;">
|
<input type="button" id="submit_button" value="{{ 'boutton::valider' | trans }}" onclick="clkBut('submit');">
|
||||||
</div>
|
</div>
|
||||||
|
</divclass>
|
||||||
</form>
|
</form>
|
||||||
<iframe style="display:block; height:50px;" name="IFRIM"></iframe>
|
<iframe style="display:block; height:50px;" name="IFRIM"></iframe>
|
||||||
</body>
|
</body>
|
||||||
|
@@ -25,41 +25,55 @@
|
|||||||
switch(button)
|
switch(button)
|
||||||
{
|
{
|
||||||
case "submit":
|
case "submit":
|
||||||
// document.forms[0].target="LINKFIELD";
|
$('.link-field-1').submit(
|
||||||
document.forms[0].submit();
|
$.ajax({
|
||||||
|
url : 'linkfield2.php',
|
||||||
|
type : 'POST',
|
||||||
|
data : $('.link-field-1').serialize(),
|
||||||
|
success : function( data ) {
|
||||||
|
$("#DLG_LINK_FIELD_1").html('');
|
||||||
|
$("#DLG_LINK_FIELD_1").append(data);
|
||||||
|
},
|
||||||
|
error : function( xhr, err ) {
|
||||||
|
alert('Error');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case "cancel":
|
case "cancel":
|
||||||
self.close();
|
$('.close-dialog').trigger('click');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function loaded()
|
function loaded()
|
||||||
{
|
{
|
||||||
window.name="LINKFIELD";
|
|
||||||
ckField();
|
ckField();
|
||||||
}
|
}
|
||||||
|
$( document ).ready(function() {
|
||||||
|
loaded();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body onload="loaded();" class="dialog">
|
<body class="dialog">
|
||||||
<center>
|
|
||||||
<form action="linkfield2.php" method="post" target="LINKFIELD">
|
|
||||||
<input type="hidden" name="piv" value="{{ piv }}">
|
|
||||||
<input type="hidden" name="bid" value="{{ bid }}">
|
|
||||||
<input type="hidden" name="tid" value="{{ tid }}">
|
|
||||||
|
|
||||||
{% set branch = "<br/><b>" ~ fullBranch ~ "</b><br/>" %}
|
<form class="link-field-1" action="linkfield2.php" method="post" target="LINKFIELD" style="padding: 5px 15px">
|
||||||
{% trans with {'%branch%' : branch} %}thesaurus:: Lier la branche de thesaurus au champ %branch%{% endtrans %}
|
<input type="hidden" name="piv" value="{{ piv }}">
|
||||||
|
<input type="hidden" name="bid" value="{{ bid }}">
|
||||||
|
<input type="hidden" name="tid" value="{{ tid }}">
|
||||||
|
|
||||||
<div style="width:70%; height:200px; overflow:scroll;" class="x3Dbox">
|
{% set branch = "<br/><b>" ~ fullBranch ~ "</b><br/>" %}
|
||||||
{% for fieldname, checked in fieldnames %}
|
{% trans with {'%branch%' : branch} %}thesaurus:: Lier la branche de thesaurus au champ %branch%{% endtrans %}
|
||||||
<input type="checkbox" name="field[]" value="{{ fieldname }}" {% if checked %}checked{% endif %} ck0="{% if checked %}1{% else %}0{% endif %}" onclick="return(ckField());">{{ fieldname }}<br/>
|
|
||||||
{% endfor %}
|
<div style="width:100%; height:270px; overflow:scroll;" class="x3Dbox">
|
||||||
|
{% for fieldname, checked in fieldnames %}
|
||||||
|
<input type="checkbox" name="field[]" value="{{ fieldname }}" {% if checked %}checked{% endif %} ck0="{% if checked %}1{% else %}0{% endif %}" onclick="return(ckField());">{{ fieldname }}<br/>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<div class="thesaurus_confirm_bottom_block">
|
||||||
|
<input type="button" id="cancel_button" class="cancel_btn" value="{{ 'boutton::annuler' | trans }}" onclick="clkBut('cancel');">
|
||||||
|
<input type="button" id="submit_button" class="validate_btn" value="{{ 'boutton::valider' | trans }}" onclick="clkBut('submit');">
|
||||||
</div>
|
</div>
|
||||||
<br/>
|
|
||||||
<input type="button" id="submit_button" value="{{ 'boutton::valider' | trans }}" onclick="clkBut('submit');">
|
|
||||||
|
|
||||||
<input type="button" id="cancel_button" value="{{ 'boutton::annuler' | trans }}" onclick="clkBut('cancel');">
|
|
||||||
</form>
|
</form>
|
||||||
</center>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@@ -12,10 +12,23 @@
|
|||||||
switch(button)
|
switch(button)
|
||||||
{
|
{
|
||||||
case "submit":
|
case "submit":
|
||||||
document.forms[0].submit();
|
$('.link-field-2').submit(
|
||||||
|
$.ajax({
|
||||||
|
url : 'linkfield3.php',
|
||||||
|
type : 'POST',
|
||||||
|
data : $('.link-field-2').serialize(),
|
||||||
|
success : function( data ) {
|
||||||
|
$("#DLG_LINK_FIELD_1").html('');
|
||||||
|
$("#DLG_LINK_FIELD_1").append(data);
|
||||||
|
},
|
||||||
|
error : function( xhr, err ) {
|
||||||
|
alert('Error');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case "cancel":
|
case "cancel":
|
||||||
self.close();
|
$('.close-dialog').trigger('click');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -23,11 +36,15 @@
|
|||||||
{
|
{
|
||||||
window.name="LINKFIELD";
|
window.name="LINKFIELD";
|
||||||
}
|
}
|
||||||
|
$( document ).ready(function() {
|
||||||
|
loaded();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body onload="loaded();" class="dialog">
|
<body class="dialog">
|
||||||
<center>
|
<center>
|
||||||
<form action="linkfield3.php" method="post" target="LINKFIELD">
|
<form class="link-field-2" action="linkfield3.php" method="post" target="LINKFIELD">
|
||||||
|
<div class="text-center">
|
||||||
<input type="hidden" name="piv" value="{{ piv }}">
|
<input type="hidden" name="piv" value="{{ piv }}">
|
||||||
<input type="hidden" name="bid" value="{{ bid }}">
|
<input type="hidden" name="bid" value="{{ bid }}">
|
||||||
<input type="hidden" name="tid" value="{{ tid }}">
|
<input type="hidden" name="tid" value="{{ tid }}">
|
||||||
@@ -68,10 +85,11 @@
|
|||||||
{% else %}
|
{% else %}
|
||||||
<div style='position:absolute; top:5px; left:0px; width:100%; text-align:center; color:green'>{{ 'thesaurus:: pas de reindexation' | trans }}</div>
|
<div style='position:absolute; top:5px; left:0px; width:100%; text-align:center; color:green'>{{ 'thesaurus:: pas de reindexation' | trans }}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<br/>
|
</div>
|
||||||
<input type="button" id="submit_button" value="{{ 'boutton::valider' | trans }}" onclick="clkBut('submit');">
|
<div class="thesaurus_confirm_bottom_block">
|
||||||
|
<input type="button" id="cancel_button" class="cancel_btn" value="{{ 'boutton::annuler' | trans }}" onclick="clkBut('cancel');">
|
||||||
<input type="button" id="cancel_button" value="{{ 'boutton::annuler' | trans }}" onclick="clkBut('cancel');">
|
<input type="button" id="submit_button" class="validate_btn" value="{{ 'boutton::valider' | trans }}" onclick="clkBut('submit');">
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</center>
|
</center>
|
||||||
</body>
|
</body>
|
||||||
|
@@ -41,8 +41,9 @@
|
|||||||
<br/>
|
<br/>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<br/>
|
<div class="thesaurus_confirm_bottom_block">
|
||||||
<input type="button" value="{{ 'boutton::fermer' | trans }}" onclick="self.close();">
|
<input type="button" value="{{ 'boutton::fermer' | trans }}" class="cancel_btn" onclick="$('.close-dialog').trigger('click');">
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</center>
|
</center>
|
||||||
</body>
|
</body>
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
{#<script type="text/javascript" src="{{ path('minifier', { 'f' : 'skins/thesaurus/xmlhttp.js' }) }}"></script>#}
|
{#<script type="text/javascript" src="{{ path('minifier', { 'f' : 'skins/thesaurus/xmlhttp.js' }) }}"></script>#}
|
||||||
</head>
|
</head>
|
||||||
<body onload="loaded();" class="dialog" style="text-align:center">
|
<body onload="loaded();" class="dialog" style="text-align:center">
|
||||||
|
<div class="text-center">
|
||||||
{% if dlg is not none %}
|
{% if dlg is not none %}
|
||||||
{% set opener = 'window.dialogArguments.win' %}
|
{% set opener = 'window.dialogArguments.win' %}
|
||||||
{% else %}
|
{% else %}
|
||||||
@@ -37,8 +38,9 @@
|
|||||||
<br/>
|
<br/>
|
||||||
{{ prop_label }}
|
{{ prop_label }}
|
||||||
<br/>
|
<br/>
|
||||||
<center>
|
</div>
|
||||||
<form onsubmit="return(false);">
|
<div class="text-center">
|
||||||
|
<form onsubmit="return(false);" class="thesaurus_confirm_bottom_block">
|
||||||
<input type="hidden" name="bid" value="{{ bid }} ">
|
<input type="hidden" name="bid" value="{{ bid }} ">
|
||||||
<input type="hidden" name="pid" value="{{ pid }}">
|
<input type="hidden" name="pid" value="{{ pid }}">
|
||||||
<div class='x3Dbox' style='margin:15px; height:100px; overflow:auto;'>
|
<div class='x3Dbox' style='margin:15px; height:100px; overflow:auto;'>
|
||||||
@@ -50,34 +52,27 @@
|
|||||||
{{ 'thesaurus:: selectionner la provenance a accepter' | trans }}
|
{{ 'thesaurus:: selectionner la provenance a accepter' | trans }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<br/>
|
<br/>
|
||||||
<input type="button" id="cancel_button" value="{{ 'boutton::annuler' | trans }}" onclick="clkBut('cancel');" style="width:100px;">
|
<input type="button" id="cancel_button" class="cancel_btn" value="{{ 'boutton::annuler' | trans }}" onclick="clkBut('cancel');" >
|
||||||
|
|
||||||
<input type="button" id="submit_button" value="{{ 'boutton::valider' | trans }}" onclick="clkBut('submit');" style="width:100px;">
|
<input type="button" id="submit_button" class="validate_btn" value="{{ 'boutton::valider' | trans }}" onclick="clkBut('submit');">
|
||||||
</form>
|
</form>
|
||||||
</center>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
{% if nb_candidates_bad > 0 %}
|
{% if nb_candidates_bad > 0 %}
|
||||||
{% set prop_label = 'thesaurus:: est candidat en provenance des champs mais ne peut etre accepte a cet emplacement du thesaurus' | trans %}
|
{% set prop_label = 'thesaurus:: est candidat en provenance des champs mais ne peut etre accepte a cet emplacement du thesaurus' | trans %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% set prop_label = 'thesaurus:: n\'est pas present dans les candidats' | trans %}
|
{% set prop_label = 'thesaurus:: n\'est pas present dans les candidats' | trans %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
<br/>
|
<br/>
|
||||||
{{ zterm }}
|
{{ zterm }}
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
|
||||||
{{ prop_label }}
|
{{ prop_label }}
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<form class="thesaurus_confirm_bottom_block">
|
||||||
<br/>
|
<input type="button" id="cancel_button" class="cancel_btn" value="{{ 'boutton::annuler' | trans }}" onclick="clkBut('cancel');" >
|
||||||
<br/>
|
|
||||||
<form>
|
|
||||||
<input type="button" id="cancel_button" value="{{ 'boutton::annuler' | trans }}" onclick="clkBut('cancel');" style="width:100px;">
|
|
||||||
|
|
||||||
<input type="button" id="submit_button" value="{{ 'boutton::valider' | trans }}" onclick="clkBut('submit');" style="width:100px;">
|
<input type="button" id="submit_button" class="validate_btn" value="{{ 'boutton::valider' | trans }}" onclick="clkBut('submit');" >
|
||||||
</form>
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</body>
|
</body>
|
||||||
@@ -119,17 +114,19 @@
|
|||||||
switch(refresh.item(i).getAttribute("type"))
|
switch(refresh.item(i).getAttribute("type"))
|
||||||
{
|
{
|
||||||
case "CT":
|
case "CT":
|
||||||
{{ opener }}.reloadCtermsBranch(refresh.item(i).getAttribute("id"));
|
reloadCtermsBranch(refresh.item(i).getAttribute("id"));
|
||||||
break;
|
break;
|
||||||
case "TH":
|
case "TH":
|
||||||
{{ opener }}.reloadThesaurusBranch(refresh.item(i).getAttribute("id"));
|
reloadThesaurusBranch(refresh.item(i).getAttribute("id"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.close();
|
$("#NEWSY_DLG_CONFIRM").dialog('close');
|
||||||
|
$("#NEWSY_DLG_CONFIRM").html('');
|
||||||
break;
|
break;
|
||||||
case "cancel":
|
case "cancel":
|
||||||
self.close();
|
$("#NEWSY_DLG_CONFIRM").dialog('close');
|
||||||
|
$("#NEWSY_DLG_CONFIRM").html('');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -141,18 +138,18 @@
|
|||||||
switch(button)
|
switch(button)
|
||||||
{
|
{
|
||||||
case "submit":
|
case "submit":
|
||||||
{% if typ == "TS" %}
|
{% if typ == "TS" %}
|
||||||
url = "xmlhttp/newts.x.php";
|
url = "xmlhttp/newts.x.php";
|
||||||
{% else %}
|
{% else %}
|
||||||
url = "xmlhttp/newsy.x.php";
|
url = "xmlhttp/newsy.x.php";
|
||||||
{% endif %}
|
{% endif %}
|
||||||
parms = "bid={{ bid }}";
|
parms = "bid={{ bid }}";
|
||||||
parms += "&piv={{ piv }}";
|
parms += "&piv={{ piv }}";
|
||||||
parms += "&pid={{ pid }}";
|
parms += "&pid={{ pid }}";
|
||||||
parms += "&t={{ term | url_encode }}";
|
parms += "&t={{ term | url_encode }}";
|
||||||
{% if context is not none %}
|
{% if context is not none %}
|
||||||
parms += "&k={{ context | url_encode }}";
|
parms += "&k={{ context | url_encode }}";
|
||||||
{% endif %}
|
{% endif %}
|
||||||
parms += "&sylng={{ sylng }}";
|
parms += "&sylng={{ sylng }}";
|
||||||
parms += "&reindex=0";
|
parms += "&reindex=0";
|
||||||
|
|
||||||
@@ -163,17 +160,20 @@
|
|||||||
switch(refresh.item(i).getAttribute("type"))
|
switch(refresh.item(i).getAttribute("type"))
|
||||||
{
|
{
|
||||||
case "CT":
|
case "CT":
|
||||||
{{ opener }}.reloadCtermsBranch(refresh.item(i).getAttribute("id"));
|
$("#NEWSY_DLG_CONFIRM").dialog('close');
|
||||||
|
reloadCtermsBranch(refresh.item(i).getAttribute("id"));
|
||||||
break;
|
break;
|
||||||
case "TH":
|
case "TH":
|
||||||
{{ opener }}.reloadThesaurusBranch(refresh.item(i).getAttribute("id"));
|
$("#NEWSY_DLG_CONFIRM").dialog('close');
|
||||||
|
reloadThesaurusBranch(refresh.item(i).getAttribute("id"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.close();
|
|
||||||
break;
|
break;
|
||||||
case "cancel":
|
case "cancel":
|
||||||
self.close();
|
$("#NEWSY_DLG_CONFIRM").dialog('close');
|
||||||
|
$("#NEWSY_DLG_CONFIRM").html('');
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,11 +3,6 @@
|
|||||||
{% else %}
|
{% else %}
|
||||||
{% set opener = "opener" %}
|
{% set opener = "opener" %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
|
||||||
<html lang="{{ app['locale'] }}">
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
|
||||||
<title>{{ 'thesaurus:: Proprietes' | trans }}</title>
|
|
||||||
<link type="text/css" rel="stylesheet" href="/assets/thesaurus/css/thesaurus{% if not app.debug %}.min{% endif %}.css" />
|
<link type="text/css" rel="stylesheet" href="/assets/thesaurus/css/thesaurus{% if not app.debug %}.min{% endif %}.css" />
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
a
|
a
|
||||||
@@ -24,38 +19,31 @@
|
|||||||
font-weight:900;
|
font-weight:900;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script type="text/javascript" src="/assets/vendors/jquery/jquery{% if not app.debug %}.min{% endif %}.js"></script>
|
|
||||||
<script type="text/javascript" src="/assets/thesaurus/js/thesaurus{% if not app.debug %}.min{% endif %}.js"></script>
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
function loaded()
|
function loaded()
|
||||||
{
|
{
|
||||||
window.name="PROPERTIES";
|
|
||||||
self.focus();
|
self.focus();
|
||||||
}
|
}
|
||||||
|
$( document ).ready(function() {
|
||||||
|
loaded();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
</head>
|
<div class="menu" id="syMenu" style="z-index:999">
|
||||||
<body id="desktop" onload="loaded();" class="dialog">
|
<a href="javascript:void(0)" id="delete_sy">{{ 'thesaurus:properties:: Mettre dans le stock' | trans }}</a>
|
||||||
<div class="menu" id="flagsMenu" style="z-index:50">
|
</div>
|
||||||
{% for code, language in languages %}
|
<div id="desktop" class="dialog">
|
||||||
<a id='flagMenu_{{ code }}' href='javascript:void(0)' class=''>
|
|
||||||
<img src='/assets/common/images/lng/{{ code }}_flag_18.gif' />{{ language }}</a>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
<div class="menu" id="syMenu" style="z-index:50">
|
|
||||||
<a href="javascript:void(0)" id="delete_sy">{{ 'thesaurus::menu: supprimer' | trans }}</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style='text-align:right'>
|
<H4>{{ fullpath | raw }}</H4>
|
||||||
|
<div style='float:right'>
|
||||||
<b>id:</b> {{ id }}
|
<b>id:</b> {{ id }}
|
||||||
</div>
|
</div>
|
||||||
<H4>{{ fullpath | raw }}</H4><br/>
|
|
||||||
{% if typ == "CT" %}
|
{% if typ == "CT" %}
|
||||||
<br/>
|
<br/>
|
||||||
{% elseif typ == "TH" %}
|
{#{% elseif typ == "TH" %}
|
||||||
{% trans with {'%hits%' : hits} %}thesaurus:: %hits% reponses retournees{% endtrans %}
|
{% trans with {'%hits%' : hits} %}thesaurus:: %hits% reponses retournees{% endtrans %}
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<br/>#}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div id="TSY" class="tableContainer" style="margin:10px; position:relative; top:0px; left:0px">
|
<div id="TSY" class="tableContainer" style="margin:10px; position:relative; top:0px; left:0px">
|
||||||
<div>
|
<div>
|
||||||
@@ -71,9 +59,7 @@
|
|||||||
<th> </th>
|
<th> </th>
|
||||||
<th> </th>
|
<th> </th>
|
||||||
<th>{{ 'thesaurus:: synonymes' | trans }}</th>
|
<th>{{ 'thesaurus:: synonymes' | trans }}</th>
|
||||||
<th>{{ 'thesaurus:: hits' | trans }}</th>
|
<th colspan="3">{{ 'thesaurus:termePorperties:termeId' | trans }}</th>
|
||||||
<th>{{ 'thesaurus:: ids' | trans }}</th>
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
</table>
|
</table>
|
||||||
@@ -99,13 +85,13 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
{% if data['lng'] %}
|
{% if data['lng'] %}
|
||||||
<td id='FLG_{{ data['id'] }}'><img src='/assets/common/images/lng/{{ data['lng'] }}_flag_18.gif' /></td>
|
<td id='FLG_{{ data['id'] }}'>{{ data['lng'] }}</td>
|
||||||
{% else %}
|
{% else %}
|
||||||
<td id='FLG_{{ data['id'] }}'><img src='/assets/thesaurus/images/noflag.gif' /></td>
|
<td id='FLG_{{ data['id'] }}'></td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<td>{{ data['t'] }}</td>
|
<td>{{ data['t'] }}</td>
|
||||||
<td>{{ data['hits'] }}</td>
|
|
||||||
<td>{{ data['id'] }}</td>
|
<td>{{ data['id'] }}</td>
|
||||||
|
<td><span class="delete_term"></span></td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
@@ -115,13 +101,17 @@
|
|||||||
</div>
|
</div>
|
||||||
<center>
|
<center>
|
||||||
<form onsubmit="return(false);">
|
<form onsubmit="return(false);">
|
||||||
<input style="position:relative; z-index:2" type="button" id="close_button" value="{{ 'boutton::fermer' | trans }}" onclick="self.close();">
|
<div class="thesaurus_confirm_bottom_block">
|
||||||
|
<input type="button" id="close_button" class="close_button cancel_btn" value="{{ 'boutton::fermer' | trans }}" >
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</center>
|
</center>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
$(".close_button").on("click", function(){
|
||||||
|
$('.close-dialog').trigger('click');
|
||||||
|
});
|
||||||
// gui callback du menu des drapeaux
|
// gui callback du menu des drapeaux
|
||||||
var nsy = {{ synonyms | length }};
|
var nsy = {{ synonyms | length }};
|
||||||
|
|
||||||
function cbME_flags(action, cbParm, menuelem_id)
|
function cbME_flags(action, cbParm, menuelem_id)
|
||||||
{
|
{
|
||||||
if(action != "SELECT" || !menuelem_id) {
|
if(action != "SELECT" || !menuelem_id) {
|
||||||
@@ -148,17 +138,23 @@
|
|||||||
switch(refresh.item(i).getAttribute("type"))
|
switch(refresh.item(i).getAttribute("type"))
|
||||||
{
|
{
|
||||||
case "CT":
|
case "CT":
|
||||||
{{ opener }}.reloadCtermsBranch(refresh.item(i).getAttribute("id"));
|
reloadCtermsBranch(refresh.item(i).getAttribute("id"));
|
||||||
{{ opener }}.myGUI.select({{ opener }}.document.getElementById("THE_{{ id }}"));
|
myGUI.select(document.getElementById("THE_{{ id }}"));
|
||||||
break;
|
break;
|
||||||
case "TH":
|
case "TH":
|
||||||
{{ opener }}.reloadThesaurusBranch(refresh.item(i).getAttribute("id"));
|
reloadThesaurusBranch(refresh.item(i).getAttribute("id"));
|
||||||
{{ opener }}.myGUI.select({{ opener }}.document.getElementById("THE_{{ id }}"));
|
myGUI.select(document.getElementById("THE_{{ id }}"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$('.delete_term').click(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
$('#delete_sy').trigger('click');
|
||||||
|
});
|
||||||
|
|
||||||
// gui callback du menu des synonymes
|
// gui callback du menu des synonymes
|
||||||
function cbME_synonym(action, cbParm, menuelem_id)
|
function cbME_synonym(action, cbParm, menuelem_id)
|
||||||
{
|
{
|
||||||
@@ -169,6 +165,7 @@
|
|||||||
// pas d'action possible s'il ne reste qu'un seul synonyme
|
// pas d'action possible s'il ne reste qu'un seul synonyme
|
||||||
// alert(nsy);
|
// alert(nsy);
|
||||||
document.getElementById("delete_sy").className = "disabled";
|
document.getElementById("delete_sy").className = "disabled";
|
||||||
|
$('.delete_term').addClass('disabled');
|
||||||
// document.getElementById("reject_sy").className = "disabled";
|
// document.getElementById("reject_sy").className = "disabled";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -178,12 +175,14 @@
|
|||||||
// y'a des hits, on peut pas supprimer
|
// y'a des hits, on peut pas supprimer
|
||||||
// document.getElementById("reject_sy").className = "";
|
// document.getElementById("reject_sy").className = "";
|
||||||
document.getElementById("delete_sy").className = "";
|
document.getElementById("delete_sy").className = "";
|
||||||
|
$('.delete_term').removeClass('disabled');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// pas de hits : on peut supprimer
|
// pas de hits : on peut supprimer
|
||||||
// document.getElementById("reject_sy").className = "";
|
// document.getElementById("reject_sy").className = "";
|
||||||
document.getElementById("delete_sy").className = "";
|
document.getElementById("delete_sy").className = "";
|
||||||
|
$('.delete_term').removeClass('disabled');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -216,7 +215,7 @@
|
|||||||
ret = loadXMLDoc(url, parms, true);
|
ret = loadXMLDoc(url, parms, true);
|
||||||
|
|
||||||
sy_list = ret.getElementsByTagName("sy_list").item(0);
|
sy_list = ret.getElementsByTagName("sy_list").item(0);
|
||||||
refresh_sy(sy_list);
|
//refresh_sy(sy_list);
|
||||||
|
|
||||||
refresh = ret.getElementsByTagName("refresh");
|
refresh = ret.getElementsByTagName("refresh");
|
||||||
for(i=0; i<refresh.length; i++)
|
for(i=0; i<refresh.length; i++)
|
||||||
@@ -224,15 +223,24 @@
|
|||||||
switch(refresh.item(i).getAttribute("type"))
|
switch(refresh.item(i).getAttribute("type"))
|
||||||
{
|
{
|
||||||
case "CT":
|
case "CT":
|
||||||
{{ opener }}.reloadCtermsBranch(refresh.item(i).getAttribute("id"));
|
reloadCtermsBranch(refresh.item(i).getAttribute("id"));
|
||||||
{{ opener }}.myGUI.select({{ opener }}.document.getElementById("THE_{{ id }}"));
|
myGUI.select(document.getElementById("THE_{{ id }}"));
|
||||||
break;
|
break;
|
||||||
case "TH":
|
case "TH":
|
||||||
{{ opener }}.reloadThesaurusBranch(refresh.item(i).getAttribute("id"));
|
reloadThesaurusBranch(refresh.item(i).getAttribute("id"));
|
||||||
{{ opener }}.myGUI.select({{ opener }}.document.getElementById("THE_{{ id }}"));
|
myGUI.select(document.getElementById("THE_{{ id }}"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var new_url = $('#url_properties').val();
|
||||||
|
$.ajax({
|
||||||
|
type: "GET",
|
||||||
|
url: `${new_url}`,
|
||||||
|
success: function(data){
|
||||||
|
$('#DLG_PROPERTIES').html('');
|
||||||
|
$('#DLG_PROPERTIES').append(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -273,16 +281,16 @@
|
|||||||
td = tr.appendChild(document.createElement("td"));
|
td = tr.appendChild(document.createElement("td"));
|
||||||
td.id = "FLG_"+(nsy+1);
|
td.id = "FLG_"+(nsy+1);
|
||||||
// td.innerText = n.getAttribute("lng");
|
// td.innerText = n.getAttribute("lng");
|
||||||
img = td.appendChild(document.createElement("img"));
|
span = td.appendChild(document.createElement("span"));
|
||||||
img.setAttribute("src", "/assets/common/images/lng/"+n.getAttribute("lng")+"_flag_18.gif");
|
span.innerHTML = n.getAttribute("lng");
|
||||||
|
|
||||||
td = tr.appendChild(document.createElement("td"));
|
td = tr.appendChild(document.createElement("td"));
|
||||||
// td.colSpan = "2";
|
// td.colSpan = "2";
|
||||||
// td.setAttribute("colSpan", "3"); // attention au 'S' majuscule !!!
|
// td.setAttribute("colSpan", "3"); // attention au 'S' majuscule !!!
|
||||||
td.innerHTML = n.getAttribute("t");
|
td.innerHTML = n.getAttribute("t");
|
||||||
|
|
||||||
td = tr.appendChild(document.createElement("td"));
|
/*td = tr.appendChild(document.createElement("td"));
|
||||||
td.innerHTML = n.getAttribute("hits");
|
td.innerHTML = n.getAttribute("hits");*/
|
||||||
|
|
||||||
td = tr.appendChild(document.createElement("td"));
|
td = tr.appendChild(document.createElement("td"));
|
||||||
td.innerHTML = n.getAttribute("id");
|
td.innerHTML = n.getAttribute("id");
|
||||||
@@ -308,15 +316,6 @@
|
|||||||
;
|
;
|
||||||
if(tr)
|
if(tr)
|
||||||
myGUI.select(tr);
|
myGUI.select(tr);
|
||||||
switch(o.id.substr(0, 4))
|
|
||||||
{
|
|
||||||
case "FLG_": // le drapeau
|
|
||||||
document.getElementById("flagsMenu").runAsMenu( evt, tr );
|
|
||||||
break;
|
|
||||||
case "SYN_": // le synonyme
|
|
||||||
document.getElementById("syMenu").runAsMenu( evt, tr );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "MOUSEDOWN":
|
case "MOUSEDOWN":
|
||||||
@@ -335,6 +334,21 @@
|
|||||||
syChgPos(-1);
|
syChgPos(-1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch(o.id.substr(0, 4))
|
||||||
|
{
|
||||||
|
case "FLG_": // le drapeau
|
||||||
|
document.getElementById("flagsMenu").runAsMenu( evt, tr );
|
||||||
|
break;
|
||||||
|
case "SYN_": // le synonyme
|
||||||
|
if (stock == false)
|
||||||
|
{
|
||||||
|
document.getElementById("syMenu").runAsMenu(evt, tr);
|
||||||
|
$('.delete_term').html('');
|
||||||
|
$('.delete_term', tr).append($('#syMenu').html());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "DBLCLICK":
|
case "DBLCLICK":
|
||||||
@@ -368,12 +382,12 @@
|
|||||||
switch(refresh.item(i).getAttribute("type"))
|
switch(refresh.item(i).getAttribute("type"))
|
||||||
{
|
{
|
||||||
case "CT":
|
case "CT":
|
||||||
{{ opener }}.reloadCtermsBranch(refresh.item(i).getAttribute("id"));
|
reloadCtermsBranch(refresh.item(i).getAttribute("id"));
|
||||||
{{ opener }}.myGUI.select({{ opener }}.document.getElementById("THE_{{ id }}"));
|
myGUI.select(document.getElementById("THE_{{ id }}"));
|
||||||
break;
|
break;
|
||||||
case "TH":
|
case "TH":
|
||||||
{{ opener }}.reloadThesaurusBranch(refresh.item(i).getAttribute("id"));
|
reloadThesaurusBranch(refresh.item(i).getAttribute("id"));
|
||||||
{{ opener }}.myGUI.select({{ opener }}.document.getElementById("THE_{{ id }}"));
|
myGUI.select(document.getElementById("THE_{{ id }}"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -383,7 +397,5 @@
|
|||||||
myGUI.setClickable("TSY", cbDD_TSY);
|
myGUI.setClickable("TSY", cbDD_TSY);
|
||||||
myGUI.setAsMenu("flagsMenu", cbME_flags);
|
myGUI.setAsMenu("flagsMenu", cbME_flags);
|
||||||
myGUI.setAsMenu("syMenu", cbME_synonym);
|
myGUI.setAsMenu("syMenu", cbME_synonym);
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</div>
|
||||||
</html>
|
|
||||||
|