mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-17 15:03:25 +00:00
Merge branch 'master' into PHRAS-2741-worker-service-part1
This commit is contained in:
@@ -1,12 +1,35 @@
|
||||
.circleci
|
||||
.git
|
||||
.idea
|
||||
.settings
|
||||
nodes_modules
|
||||
vendor
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*.md
|
||||
/.circleci
|
||||
/.dockerignore
|
||||
/.env
|
||||
/.env.*
|
||||
/env.*
|
||||
/.git
|
||||
/.travis.yml
|
||||
/AUTHORS
|
||||
/CONTRIBUTORS
|
||||
/Dockerfile
|
||||
/LICENSE
|
||||
/bin
|
||||
!/bin/console
|
||||
!/bin/developer
|
||||
!/bin/setup
|
||||
/cache
|
||||
/config/configuration.yml
|
||||
/config/configuration-compiled.php
|
||||
!/config/configuration.sample.yml
|
||||
/datas
|
||||
/docker-compose.*
|
||||
/logs
|
||||
/nodes_modules
|
||||
/plugins
|
||||
/tmp
|
||||
/vendor
|
||||
/volumes
|
||||
/www/assets
|
||||
/www/custom
|
||||
/www/plugins
|
||||
/www/thumbnails
|
||||
npm-debug.log
|
||||
|
72
.env
Normal file
72
.env
Normal file
@@ -0,0 +1,72 @@
|
||||
# Registry from where you pull Docker images
|
||||
PHRASEANET_DOCKER_REGISTRY=local
|
||||
# Tag of the Docker images
|
||||
PHRASEANET_DOCKER_TAG=latest
|
||||
# APPLICATION PORT
|
||||
PHRASEANET_APP_PORT=8082
|
||||
# RabbitMQ configuration
|
||||
RABBITMQ_DEFAULT_USER=alchemy
|
||||
RABBITMQ_DEFAULT_PASS=vdh4dpe5Wy3R
|
||||
RABBITMQ_MANAGEMENT_PORT=10811
|
||||
# Mysql configuration
|
||||
MYSQL_ROOT_PASSWORD=root
|
||||
SERVER_NAME=phraseanet-docker
|
||||
|
||||
|
||||
# --------------- APPLICATION CONFIGURATION --------------------
|
||||
|
||||
# Max upload size
|
||||
MAX_BODY_SIZE=2G
|
||||
# Max input var
|
||||
MAX_INPUT_VARS=12000
|
||||
|
||||
# Enable opcache ? (0/1)
|
||||
OPCACHE_ENABLED=1
|
||||
# session cache limiter (off/on)
|
||||
SESSION_CACHE_LIMITER=off
|
||||
|
||||
# PHP LOG LEVEL : Possible Values: alert, error, warning, notice, debug
|
||||
PHP_LOG_LEVEL=warning
|
||||
|
||||
# --------------- APPLICATION STARTUP CONFIGURATION --------------------
|
||||
|
||||
# These variables are only used if the configuration.yml file is not present, in order to automate the installation procedure
|
||||
|
||||
# set here the first user / email couple
|
||||
INSTALL_ACCOUNT_EMAIL=admin@alchemy.fr
|
||||
INSTALL_ACCOUNT_PASSWORD=iJRqXU0MwbyJewQLBbra6IWHsWly
|
||||
# Database parameters
|
||||
INSTALL_DB_HOST=db
|
||||
INSTALL_DB_PORT=3306
|
||||
INSTALL_DB_USER=root
|
||||
INSTALL_DB_PASSWORD=root
|
||||
INSTALL_DB_TEMPLATE=en-simple
|
||||
INSTALL_APPBOX=ab_master
|
||||
INSTALL_DATABOX=db_databox1
|
||||
INSTALL_SERVER_NAME=localhost
|
||||
|
||||
# Mysql max allowed packet
|
||||
MYSQL_MAX_ALLOWED_PACKET=16M
|
||||
|
||||
|
||||
# --- DEV purpose ---
|
||||
|
||||
# PhpMyAdmin port
|
||||
PHRASEANET_PHPMYADMIN_PORT=8089
|
||||
|
||||
# Xdebug
|
||||
XDEBUG_ENABLED=1
|
||||
XDEBUG_PROFILER_ENABLED=0
|
||||
IDE_KEY=PHPSTORM
|
||||
PHRASEANET_SUBNET_IPS=172.32.0.0/16
|
||||
XDEBUG_REMOTE_HOST=172.32.0.1
|
||||
PHP_IDE_CONFIG=serverName=docker-server-phraseanet
|
||||
|
||||
# Volumes location for dev
|
||||
PHRASEANET_CONFIG_DIR=./config
|
||||
PHRASEANET_LOGS_DIR=./logs
|
||||
PHRASEANET_DATA_DIR=./datas
|
||||
PHRASEANET_DB_DIR=./volumes/db
|
||||
PHRASEANET_ELASTICSEARCH_DIR=./volumes/elasticsearch
|
||||
PHRASEANET_THUMBNAILS_DIR=./www/thumbnails
|
||||
PHRASEANET_TMP_DIR=./tmp
|
4
.gitignore
vendored
4
.gitignore
vendored
@@ -71,3 +71,7 @@ playbook.retry
|
||||
npm-debug.log
|
||||
|
||||
/Phrasea_datas
|
||||
|
||||
.env.*
|
||||
env.local
|
||||
/volumes
|
||||
|
144
Dockerfile
144
Dockerfile
@@ -1,4 +1,3 @@
|
||||
|
||||
#########################################################################
|
||||
# This image contains every build tools that will be used by the builder and
|
||||
# the app images (usefull in dev mode)
|
||||
@@ -11,7 +10,8 @@ RUN apt-get update \
|
||||
ca-certificates \
|
||||
gnupg2 \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y --no-install-recommends zlib1g-dev \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
zlib1g-dev \
|
||||
git \
|
||||
ghostscript \
|
||||
gpac \
|
||||
@@ -34,20 +34,40 @@ RUN apt-get update \
|
||||
unoconv \
|
||||
unzip \
|
||||
xpdf \
|
||||
libreoffice-base-core \
|
||||
libreoffice-impress \
|
||||
libreoffice-calc \
|
||||
libreoffice-math \
|
||||
libreoffice-writer \
|
||||
libreoffice-pdfimport \
|
||||
&& update-locale "LANG=fr_FR.UTF-8 UTF-8" \
|
||||
&& dpkg-reconfigure --frontend noninteractive locales \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
|
||||
&& docker-php-source extract \
|
||||
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
|
||||
&& docker-php-ext-install -j$(nproc) gd \
|
||||
&& docker-php-ext-install zip exif iconv mbstring pcntl sockets xsl intl pdo_mysql gettext bcmath mcrypt \
|
||||
&& pecl install redis amqp-1.9.3 zmq-beta imagick-beta \
|
||||
&& pecl install \
|
||||
redis \
|
||||
amqp-1.9.3 \
|
||||
zmq-beta \
|
||||
imagick-beta \
|
||||
xdebug-2.6.1 \
|
||||
&& docker-php-ext-enable redis amqp zmq imagick \
|
||||
&& pecl clear-cache \
|
||||
&& docker-php-source delete \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists \
|
||||
&& mkdir /entrypoint /var/alchemy \
|
||||
&& useradd -u 1000 app \
|
||||
&& mkdir -p /home/app/.composer \
|
||||
&& chown -R app: /home/app /var/alchemy
|
||||
|
||||
ENV XDEBUG_ENABLED=0
|
||||
|
||||
#########################################################################
|
||||
# This image is used to build the apps
|
||||
#########################################################################
|
||||
|
||||
FROM phraseanet-system as builder
|
||||
|
||||
COPY --from=composer:1.9.1 /usr/bin/composer /usr/bin/composer
|
||||
|
||||
@@ -56,73 +76,33 @@ COPY --from=composer:1.9.1 /usr/bin/composer /usr/bin/composer
|
||||
# https://linuxize.com/post/how-to-install-node-js-on-ubuntu-18.04/
|
||||
# https://yarnpkg.com/lang/en/docs/install/#debian-stable
|
||||
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - \
|
||||
&& apt install -y nodejs \
|
||||
&& curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
|
||||
&& echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \
|
||||
&& apt-get update && apt-get install -y --no-install-recommends yarn \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
nodejs \
|
||||
yarn \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/
|
||||
&& rm -rf /var/lib/apt/lists \
|
||||
&& mkdir -p /var/alchemy/Phraseanet \
|
||||
&& chown -R app:app /var/alchemy
|
||||
|
||||
RUN mkdir /entrypoint /var/alchemy \
|
||||
&& useradd -u 1000 app \
|
||||
&& mkdir -p /home/app/.composer \
|
||||
&& chown -R app: /home/app /var/alchemy
|
||||
WORKDIR /var/alchemy/Phraseanet
|
||||
|
||||
#########################################################################
|
||||
# This image is used to build the apps
|
||||
#########################################################################
|
||||
USER app
|
||||
|
||||
FROM phraseanet-system as builder
|
||||
# Warm up composer cache for faster builds
|
||||
COPY docker/caching/composer.* ./
|
||||
RUN composer install --prefer-dist --no-dev --no-progress --no-suggest --classmap-authoritative --no-interaction --no-scripts \
|
||||
&& rm -rf vendor composer.*
|
||||
# End warm up
|
||||
|
||||
WORKDIR /var/alchemy/
|
||||
COPY --chown=app . .
|
||||
|
||||
# Files that are needed at build stage
|
||||
RUN rm -rf docker/phraseanet/root \
|
||||
&& make install
|
||||
|
||||
COPY gulpfile.js /var/alchemy/
|
||||
COPY www/include /var/alchemy/www/include
|
||||
COPY www/scripts/apps /var/alchemy/www/scripts/apps
|
||||
COPY Makefile /var/alchemy/
|
||||
COPY package.json /var/alchemy/
|
||||
COPY phpunit.xml.dist /var/alchemy/
|
||||
COPY yarn.lock /var/alchemy/
|
||||
COPY bin /var/alchemy/bin
|
||||
COPY composer.json /var/alchemy/
|
||||
COPY composer.lock /var/alchemy/
|
||||
RUN make install_composer
|
||||
COPY resources /var/alchemy/resources
|
||||
|
||||
# Application build phase
|
||||
|
||||
RUN make clean_assets
|
||||
RUN make install_asset_dependencies
|
||||
RUN make install_assets
|
||||
|
||||
# Application code
|
||||
|
||||
COPY www /var/alchemy/www
|
||||
ADD ./docker/phraseanet/ /
|
||||
COPY lib /var/alchemy/lib
|
||||
COPY tmp /var/alchemy/tmp
|
||||
COPY config /var/alchemy/config
|
||||
COPY grammar /var/alchemy/grammar
|
||||
COPY templates-profiler /var/alchemy/templates-profiler
|
||||
COPY templates /var/alchemy/templates
|
||||
COPY tests /var/alchemy/tests
|
||||
|
||||
# Create needed folders
|
||||
|
||||
RUN mkdir -p /var/alchemy/Phraseanet/logs \
|
||||
&& chmod -R 777 /var/alchemy/Phraseanet/logs \
|
||||
&& mkdir -p /var/alchemy/Phraseanet/cache \
|
||||
&& chmod -R 777 /var/alchemy/Phraseanet/cache \
|
||||
&& mkdir -p /var/alchemy/Phraseanet/datas \
|
||||
&& chmod -R 777 /var/alchemy/Phraseanet/datas \
|
||||
&& mkdir -p /var/alchemy/Phraseanet/tmp \
|
||||
&& chmod -R 777 /var/alchemy/Phraseanet/tmp \
|
||||
&& mkdir -p /var/alchemy/Phraseanet/www/custom \
|
||||
&& chmod -R 777 /var/alchemy/Phraseanet/www/custom \
|
||||
&& mkdir -p /var/alchemy/Phraseanet/config \
|
||||
&& chmod -R 777 /var/alchemy/Phraseanet/config
|
||||
ADD docker/phraseanet/ /
|
||||
|
||||
#########################################################################
|
||||
# Phraseanet web application image
|
||||
@@ -130,31 +110,29 @@ RUN mkdir -p /var/alchemy/Phraseanet/logs \
|
||||
|
||||
FROM phraseanet-system as phraseanet-fpm
|
||||
|
||||
RUN docker-php-source extract \
|
||||
&& pecl install xdebug-2.9.0 \
|
||||
&& docker-php-ext-enable xdebug \
|
||||
#&& pecl clear-cache \
|
||||
&& docker-php-source delete
|
||||
|
||||
COPY --from=builder --chown=app /var/alchemy /var/alchemy/Phraseanet
|
||||
ADD ./docker/phraseanet/ /
|
||||
COPY --from=builder --chown=app /var/alchemy/Phraseanet /var/alchemy/Phraseanet
|
||||
ADD ./docker/phraseanet/root /
|
||||
WORKDIR /var/alchemy/Phraseanet
|
||||
ENTRYPOINT ["/phraseanet-entrypoint.sh"]
|
||||
CMD ["/boot.sh"]
|
||||
ENTRYPOINT ["docker/phraseanet/entrypoint.sh"]
|
||||
CMD ["php-fpm", "-F"]
|
||||
|
||||
#########################################################################
|
||||
# Phraseanet worker application image
|
||||
#########################################################################
|
||||
|
||||
FROM phraseanet-fpm as phraseanet-worker
|
||||
CMD ["/worker-boot.sh"]
|
||||
ENTRYPOINT ["docker/phraseanet/worker/entrypoint.sh"]
|
||||
CMD ["bin/console", "task-manager:scheduler:run"]
|
||||
|
||||
#########################################################################
|
||||
# phraseanet-nginx
|
||||
#########################################################################
|
||||
|
||||
FROM nginx:1.15 as phraseanet-nginx
|
||||
RUN useradd -u 1000 app
|
||||
ADD ./docker/nginx/ /
|
||||
COPY --from=builder /var/alchemy/www /var/alchemy/Phraseanet/www
|
||||
CMD ["/boot.sh"]
|
||||
FROM nginx:1.17.8-alpine as phraseanet-nginx
|
||||
RUN adduser --uid 1000 --disabled-password app
|
||||
ADD ./docker/nginx/root /
|
||||
COPY --from=builder /var/alchemy/Phraseanet/www /var/alchemy/Phraseanet/www
|
||||
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
|
5
Makefile
5
Makefile
@@ -5,7 +5,10 @@ install:
|
||||
make install_assets
|
||||
|
||||
install_composer:
|
||||
composer install --ignore-platform-reqs
|
||||
composer install --ignore-platform-reqs --no-dev --no-suggest --classmap-authoritative --no-interaction
|
||||
|
||||
install_composer_dev:
|
||||
composer install
|
||||
|
||||
install_asset_dependencies:
|
||||
yarn install
|
||||
|
130
README.md
130
README.md
@@ -32,7 +32,109 @@ You can also download a testing pre installed Virtual Machine in OVA format here
|
||||
|
||||
https://www.phraseanet.com/download/
|
||||
|
||||
# Development :
|
||||
# With Docker
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- docker-compose
|
||||
- docker >=v18.01-ce
|
||||
|
||||
## Get started
|
||||
|
||||
You should review the default env variables defined in `.env` file.
|
||||
Use `export` to override these values.
|
||||
|
||||
i.e:
|
||||
```bash
|
||||
export PHRASEANET_DOCKER_TAG=latest
|
||||
export INSTALL_ACCOUNT_EMAIL=foo@bar.com
|
||||
export INSTALL_ACCOUNT_PASSWORD=$3cr3t!
|
||||
export PHRASEANET_APP_PORT=8082
|
||||
```
|
||||
|
||||
### Using a env.local (custom .env)
|
||||
|
||||
It may be easier to deal with a local file to manage our env variables.
|
||||
|
||||
You can add your `env.local` at the root of this project and define a command alias in your `~/.bashrc`:
|
||||
|
||||
```bash
|
||||
alias dc="env $(cat env.local | grep -v '#' | tr '\n' ' ') docker-compose"
|
||||
```
|
||||
|
||||
### Running the application
|
||||
|
||||
If you are not interested in the development of Phraseanet, you can ignore everything in `.env` after the `DEV Purpose` part.
|
||||
|
||||
docker-compose -f docker-compose.yml up -d
|
||||
|
||||
Why this option `-f docker-compose.yml`?
|
||||
The development and integration concerns are separated using a `docker-compose.override.yml`. By default, `docker-compose` will include this files if it exists.
|
||||
If you don't work on phraseanet development, avoiding this `-f docker-compose.yml` parameters will throw errors. So you have to add this options on every `docker-compose` commands to avoid this inclusion.
|
||||
|
||||
> You can also delete the `docker-compose.override.yml` to get free from this behavior.
|
||||
|
||||
#### Running workers
|
||||
|
||||
```bash
|
||||
docker-compose -f docker-compose.yml run --rm worker <command>
|
||||
```
|
||||
|
||||
Where `<command>` can be:
|
||||
- `bin/console task-manager:scheduler:run` (default)
|
||||
- `bin/console worker:execute -m 2`
|
||||
- ...
|
||||
|
||||
|
||||
The default parameters allow you to reach the app with : `http://localhost:8082`
|
||||
|
||||
## Development mode
|
||||
|
||||
The development mode uses the `docker-compose-override.yml` file.
|
||||
|
||||
You can run it with:
|
||||
|
||||
docker-compose up -d
|
||||
|
||||
The environment is not ready yet: you have to fetch all dependencies.
|
||||
|
||||
This can be made easily from the builder container:
|
||||
|
||||
docker-compose run --rm -u app builder make install install_composer_dev
|
||||
|
||||
> Please note that the phraseanet image does not contain nor `composer` neither `node` tools. This allow the final image to be slim.
|
||||
> If you need to use dev tools, ensure you are running the `builder` image!
|
||||
|
||||
### Using Xdebug
|
||||
|
||||
Xdebug is enabled by default with the `docker-compose.override.yml`
|
||||
You can disable it by setting:
|
||||
|
||||
```bash
|
||||
export XDEBUG_ENABLED=0
|
||||
```
|
||||
|
||||
Remote host is fixed because of the subnet network from compose.
|
||||
|
||||
You need to configure file mapping in your IDE.
|
||||
For PhpStorm, you can follow this example:
|
||||
|
||||

|
||||
|
||||
> Configure the `Absolute path on the server` to `/var/alchemy/Phraseanet` at the project root path (i.e. `~/projects/Phraseanet`).
|
||||
|
||||
#### Xdebug on MacOS
|
||||
|
||||
You have to set the following env:
|
||||
```bash
|
||||
XDEBUG_REMOTE_HOST=host.docker.internal
|
||||
```
|
||||
|
||||
> Don't forget to recreate your container (`docker-compose up -d phraseanet`)
|
||||
|
||||
# With Vagrant (deprecated)
|
||||
|
||||
## Development :
|
||||
|
||||
For development purpose Phraseanet is shipped with ready to use development environments using vagrant.
|
||||
You can easily choose betweeen a complete build or a prebuild box, with a specific PHP version.
|
||||
@@ -50,29 +152,3 @@ Ex:
|
||||
|
||||
|
||||
For development with Phraseanet API see https://docs.phraseanet.com/4.0/en/Devel/index.html
|
||||
|
||||
|
||||
# Docker build
|
||||
|
||||
WARNING : still in a work-in-progress status and can be used only for test purposes.
|
||||
|
||||
The docker distribution come with 3 differents containers :
|
||||
* An nginx that act as the front http server.
|
||||
* The php-fpm who serves the php files through nginx.
|
||||
* The worker who execute Phraseanet scheduler.
|
||||
|
||||
## How to build
|
||||
|
||||
You can build all the images with the following command at the root directory, choosing an arbirary TAG name :
|
||||
|
||||
./build.sh <TAG>
|
||||
|
||||
It will build and tag the following images :
|
||||
|
||||
local/phraseanet-worker:<TAG>
|
||||
local/phraseanet-fpm:<TAG>
|
||||
local/phraseanet-nginx:<TAG>
|
||||
|
||||
# Deploy the application
|
||||
|
||||
Once the images are built, you can deploy the entire phraseanet stack using the repository : https://github.com/alchemy-fr/phraseanet-docker and follow the instruction inside its `README.md` file.
|
||||
|
@@ -54,7 +54,7 @@ use Alchemy\Phrasea\Command\Task\TaskStart;
|
||||
use Alchemy\Phrasea\Command\Task\TaskState;
|
||||
use Alchemy\Phrasea\Command\Task\TaskStop;
|
||||
use Alchemy\Phrasea\Command\User\UserCreateCommand;
|
||||
use Alchemy\Phrasea\Command\User\UserSetPasswordCommand;
|
||||
use Alchemy\Phrasea\Command\User\UserPasswordCommand;
|
||||
use Alchemy\Phrasea\Command\User\UserListCommand;
|
||||
use Alchemy\Phrasea\Command\UpgradeDBDatas;
|
||||
|
||||
@@ -132,7 +132,7 @@ $cli->command(new MountDataboxCommand('databox:mount'));
|
||||
|
||||
$cli->command(new UserCreateCommand('user:create'));
|
||||
|
||||
$cli->command(new UserSetPasswordCommand('user:set-password'));
|
||||
$cli->command(new UserPasswordCommand('user:password'));
|
||||
|
||||
$cli->command(new UserListCommand('user:list'));
|
||||
|
||||
|
13
build.sh
13
build.sh
@@ -1,13 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -xe
|
||||
|
||||
# nginx server
|
||||
docker build --target phraseanet-nginx -t local/phraseanet-nginx:$1 .
|
||||
|
||||
# php-fpm application
|
||||
docker build --target phraseanet-fpm -t local/phraseanet-fpm:$1 .
|
||||
|
||||
# worker
|
||||
docker build --target phraseanet-worker -t local/phraseanet-worker:$1 .
|
||||
|
79
docker-compose.override.yml
Normal file
79
docker-compose.override.yml
Normal file
@@ -0,0 +1,79 @@
|
||||
version: "3.4"
|
||||
services:
|
||||
phpmyadmin:
|
||||
image: phpmyadmin/phpmyadmin
|
||||
restart: on-failure
|
||||
ports:
|
||||
- ${PHRASEANET_PHPMYADMIN_PORT}:80
|
||||
depends_on:
|
||||
- db
|
||||
|
||||
gateway:
|
||||
volumes:
|
||||
- .:/var/alchemy/Phraseanet
|
||||
- ./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
|
||||
|
||||
|
||||
|
||||
builder:
|
||||
build:
|
||||
context: .
|
||||
target: builder
|
||||
command: exit 0
|
||||
volumes:
|
||||
- .:/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:
|
||||
environment:
|
||||
- XDEBUG_ENABLED
|
||||
- XDEBUG_CONFIG=remote_host=${XDEBUG_REMOTE_HOST} idekey=${IDE_KEY} remote_enable=1 profiler_enable=${XDEBUG_PROFILER_ENABLED} profiler_output_dir=/var/alchemy/Phraseanet/cache/profiler
|
||||
- PHP_IDE_CONFIG
|
||||
volumes:
|
||||
- .:/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_TMP_DIR}:/var/alchemy/Phraseanet/tmp:rw
|
||||
|
||||
worker:
|
||||
volumes:
|
||||
- .:/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_TMP_DIR}:/var/alchemy/Phraseanet/tmp:rw
|
||||
|
||||
rabbitmq:
|
||||
ports:
|
||||
- ${RABBITMQ_MANAGEMENT_PORT}:15672
|
||||
|
||||
db:
|
||||
volumes:
|
||||
- ${PHRASEANET_DB_DIR}:/var/lib/mysql:rw
|
||||
|
||||
mailhog:
|
||||
image: mailhog/mailhog
|
||||
ports:
|
||||
- 1025:1025
|
||||
- 8025:8025
|
||||
|
||||
elasticsearch:
|
||||
ports:
|
||||
- 9200:9200
|
||||
volumes:
|
||||
- ${PHRASEANET_ELASTICSEARCH_DIR}:/usr/share/elasticsearch/data:rw
|
||||
|
||||
networks:
|
||||
default:
|
||||
ipam:
|
||||
config:
|
||||
- subnet: $PHRASEANET_SUBNET_IPS
|
123
docker-compose.yml
Normal file
123
docker-compose.yml
Normal file
@@ -0,0 +1,123 @@
|
||||
version: "3.4"
|
||||
|
||||
services:
|
||||
gateway:
|
||||
build:
|
||||
context: .
|
||||
target: phraseanet-nginx
|
||||
image: $PHRASEANET_DOCKER_REGISTRY/phraseanet-nginx:$PHRASEANET_DOCKER_TAG
|
||||
restart: on-failure
|
||||
volumes:
|
||||
- data_vol:/var/alchemy/Phraseanet/datas:rw
|
||||
- thumbnails_vol:/var/alchemy/Phraseanet/www/thumbnails:rw
|
||||
depends_on:
|
||||
- phraseanet
|
||||
environment:
|
||||
- MAX_BODY_SIZE
|
||||
ports:
|
||||
- ${PHRASEANET_APP_PORT}:80
|
||||
|
||||
phraseanet:
|
||||
build:
|
||||
context: .
|
||||
target: phraseanet-fpm
|
||||
image: $PHRASEANET_DOCKER_REGISTRY/phraseanet-fpm:$PHRASEANET_DOCKER_TAG
|
||||
restart: on-failure
|
||||
depends_on:
|
||||
- db
|
||||
- redis
|
||||
- rabbitmq
|
||||
- elasticsearch
|
||||
environment:
|
||||
- MAX_BODY_SIZE
|
||||
- MAX_INPUT_VARS
|
||||
- OPCACHE_ENABLED
|
||||
- SESSION_CACHE_LIMITER
|
||||
- PHP_LOG_LEVEL
|
||||
- INSTALL_ACCOUNT_EMAIL
|
||||
- INSTALL_ACCOUNT_PASSWORD
|
||||
- INSTALL_DB_HOST
|
||||
- INSTALL_DB_PORT
|
||||
- INSTALL_DB_USER
|
||||
- INSTALL_DB_PASSWORD
|
||||
- INSTALL_DB_TEMPLATE
|
||||
- INSTALL_APPBOX
|
||||
- INSTALL_DATABOX
|
||||
- INSTALL_SERVER_NAME
|
||||
- INSTALL_RABBITMQ_USER=$RABBITMQ_DEFAULT_USER
|
||||
- INSTALL_RABBITMQ_PASSWORD=$RABBITMQ_DEFAULT_PASS
|
||||
volumes:
|
||||
- config_vol:/var/alchemy/Phraseanet/config:rw
|
||||
- data_vol:/var/alchemy/Phraseanet/datas:rw
|
||||
- tmp_vol:/var/alchemy/Phraseanet/tmp:rw
|
||||
- logs_vol:/var/alchemy/Phraseanet/logs:rw
|
||||
- thumbnails_vol:/var/alchemy/Phraseanet/www/thumbnails:rw
|
||||
|
||||
worker:
|
||||
build:
|
||||
context: .
|
||||
target: phraseanet-worker
|
||||
image: $PHRASEANET_DOCKER_REGISTRY/phraseanet-worker:$PHRASEANET_DOCKER_TAG
|
||||
restart: on-failure
|
||||
depends_on:
|
||||
- db
|
||||
- redis
|
||||
- rabbitmq
|
||||
- elasticsearch
|
||||
environment:
|
||||
- MAX_BODY_SIZE
|
||||
- MAX_INPUT_VARS
|
||||
- OPCACHE_ENABLED
|
||||
- SESSION_CACHE_LIMITER
|
||||
- PHP_LOG_LEVEL
|
||||
volumes:
|
||||
- config_vol:/var/alchemy/Phraseanet/config:rw
|
||||
- data_vol:/var/alchemy/Phraseanet/datas:rw
|
||||
- tmp_vol:/var/alchemy/Phraseanet/tmp:rw
|
||||
- logs_vol:/var/alchemy/Phraseanet/logs:rw
|
||||
- thumbnails_vol:/var/alchemy/Phraseanet/www/thumbnails:rw
|
||||
|
||||
db:
|
||||
image: $PHRASEANET_DOCKER_REGISTRY/phraseanet-db:$PHRASEANET_DOCKER_TAG
|
||||
build: ./docker/db
|
||||
restart: on-failure
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD
|
||||
- MYSQL_MAX_ALLOWED_PACKET
|
||||
volumes:
|
||||
- db_vol:/var/lib/mysql
|
||||
|
||||
rabbitmq:
|
||||
image: rabbitmq:3-management
|
||||
restart: on-failure
|
||||
environment:
|
||||
- RABBITMQ_DEFAULT_USER
|
||||
- RABBITMQ_DEFAULT_PASS
|
||||
|
||||
redis:
|
||||
image: redis
|
||||
restart: on-failure
|
||||
|
||||
elasticsearch:
|
||||
image: $PHRASEANET_DOCKER_REGISTRY/phraseanet-elasticsearch:$PHRASEANET_DOCKER_TAG
|
||||
build: ./docker/elasticsearch
|
||||
restart: on-failure
|
||||
volumes:
|
||||
- elasticsearch_vol:/usr/share/elasticsearch/data
|
||||
|
||||
volumes:
|
||||
config_vol:
|
||||
driver: local
|
||||
data_vol:
|
||||
driver: local
|
||||
tmp_vol:
|
||||
driver: local
|
||||
db_vol:
|
||||
driver: local
|
||||
elasticsearch_vol:
|
||||
driver: local
|
||||
thumbnails_vol:
|
||||
driver: local
|
||||
# to be replacer by stdout/stderr
|
||||
logs_vol:
|
||||
driver: local
|
154
docker/caching/composer.json
Normal file
154
docker/caching/composer.json
Normal file
@@ -0,0 +1,154 @@
|
||||
{
|
||||
"name": "phraseanet/phraseanet",
|
||||
"description": "Phraseanet",
|
||||
"license": "GPL-3.0",
|
||||
"config": {
|
||||
"bin-dir": "bin/"
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "package",
|
||||
"package": {
|
||||
"name": "facebook/php-sdk",
|
||||
"version": "3.2.3",
|
||||
"source": {
|
||||
"url": "https://github.com/facebookarchive/facebook-php-sdk.git",
|
||||
"type": "git",
|
||||
"reference": "3.2.3"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "package",
|
||||
"package": {
|
||||
"name": "exiftool/exiftool",
|
||||
"version": "11",
|
||||
"source": {
|
||||
"url": "https://github.com/exiftool/exiftool.git",
|
||||
"type": "git",
|
||||
"reference": "11.84"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/alchemy-fr/tcpdf-clone"
|
||||
},
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/romainneutron/ProcessManager.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/alchemy-fr/imagine"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/alchemy-fr/JMSTranslationBundle"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/alchemy-fr/embed-bundle.git"
|
||||
},
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/alchemy-fr/fractal.git"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.5.9",
|
||||
"ext-intl": "*",
|
||||
"alchemy-fr/tcpdf-clone": "~6.0",
|
||||
"alchemy/embed-bundle": "^2.0.7",
|
||||
"alchemy/geonames-api-consumer": "~0.1.0",
|
||||
"alchemy/mediavorus": "^0.4.4",
|
||||
"alchemy/oauth2php": "1.1.0",
|
||||
"alchemy/phlickr": "0.2.9",
|
||||
"alchemy/phpexiftool": "^0.7.0",
|
||||
"alchemy/rest-bundle": "^0.0.5",
|
||||
"alchemy/symfony-cors": "^0.1.0",
|
||||
"alchemy/task-manager": "2.0.x-dev@dev",
|
||||
"alchemy/zippy": "^0.3.0",
|
||||
"beberlei/assert": "^2.3",
|
||||
"cocur/slugify": "^2.0",
|
||||
"dailymotion/sdk": "~1.5",
|
||||
"data-uri/data-uri": "~0.1.0",
|
||||
"dflydev/doctrine-orm-service-provider": "~1.0",
|
||||
"doctrine/cache": "1.6.x-dev",
|
||||
"doctrine/dbal": "^2.4.0",
|
||||
"doctrine/migrations": "^1.0.0",
|
||||
"doctrine/orm": "^2.4.0",
|
||||
"elasticsearch/elasticsearch": "~2.0",
|
||||
"firebase/php-jwt": "^3.0.0",
|
||||
"gedmo/doctrine-extensions": "~2.3.0",
|
||||
"goodby/csv": "^1.3.0",
|
||||
"google/apiclient": "^2.0",
|
||||
"guzzle/guzzle": "~3.0",
|
||||
"hoa/compiler": "~2.0",
|
||||
"hoa/console": "~2.0",
|
||||
"hoa/dispatcher": "~0.0",
|
||||
"hoa/router": "~2.0",
|
||||
"igorw/get-in": "~1.0",
|
||||
"imagine/imagine": "0.6.x-dev",
|
||||
"jms/serializer": "~0.10",
|
||||
"jms/translation-bundle": "dev-rebase-2015-10-20",
|
||||
"justinrainbow/json-schema": "2.0.3 as 1.6.1",
|
||||
"league/flysystem": "^1.0",
|
||||
"league/flysystem-aws-s3-v2": "^1.0",
|
||||
"league/fractal": "dev-webgalleries#af1acc0275438571bc8c1d08a05a4b5af92c9f97 as 0.13.0",
|
||||
"media-alchemyst/media-alchemyst": "^0.5.5",
|
||||
"monolog/monolog": "~1.3",
|
||||
"mrclay/minify": "~2.1.6",
|
||||
"neutron/process-manager": "2.0.x-dev@dev",
|
||||
"neutron/recaptcha": "~0.1.0",
|
||||
"neutron/silex-filesystem-provider": "~1.0",
|
||||
"neutron/silex-imagine-provider": "~0.1.0",
|
||||
"neutron/temporary-filesystem": "~2.1",
|
||||
"pagerfanta/pagerfanta": "^1.0",
|
||||
"php-ffmpeg/php-ffmpeg": "~0.5.0",
|
||||
"php-xpdf/php-xpdf": "~0.2.1",
|
||||
"exiftool/exiftool": "^11",
|
||||
"ramsey/uuid": "^3.0",
|
||||
"roave/security-advisories": "dev-master",
|
||||
"silex/silex": "^1.3.0",
|
||||
"silex/web-profiler": "~1.0",
|
||||
"simple-bus/doctrine-orm-bridge": "^4.0",
|
||||
"simple-bus/jms-serializer-bridge": "^1.0",
|
||||
"simple-bus/message-bus": "^2.1",
|
||||
"simple-bus/serialization": "^2.0",
|
||||
"sorien/silex-dbal-profiler": "^1.1",
|
||||
"sorien/silex-pimple-dumper": "^1.0",
|
||||
"swiftmailer/swiftmailer": "~5.4.5",
|
||||
"symfony/symfony": "~2.7.10|~2.8.3",
|
||||
"themattharris/tmhoauth": "~0.7",
|
||||
"twig/extensions": "^1.2.0",
|
||||
"twig/twig": "~1.14, >=1.14.2",
|
||||
"vierbergenlars/php-semver": "~2.1",
|
||||
"webmozart/json": "^1.1",
|
||||
"willdurand/negotiation": "^2.0.0-alpha1",
|
||||
"zend/gdata": "~1.12.1",
|
||||
"alchemy/worker-bundle": "^0.1.6",
|
||||
"alchemy/queue-bundle": "^0.1.5",
|
||||
"google/recaptcha": "^1.1",
|
||||
"facebook/graph-sdk": "^5.6",
|
||||
"box/spout": "^2.7",
|
||||
"paragonie/random-lib": "^2.0",
|
||||
"czproject/git-php": "^3.17"
|
||||
},
|
||||
"require-dev": {
|
||||
"mikey179/vfsstream": "~1.5",
|
||||
"phpunit/phpunit": "^4.8|^5.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Alchemy\\": "lib",
|
||||
"": "lib/classes"
|
||||
}
|
||||
},
|
||||
"include-path": ["vendor/zend/gdata/library"],
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "4.1.x-dev"
|
||||
}
|
||||
}
|
||||
}
|
8839
docker/caching/composer.lock
generated
Normal file
8839
docker/caching/composer.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
12
docker/db/Dockerfile
Normal file
12
docker/db/Dockerfile
Normal file
@@ -0,0 +1,12 @@
|
||||
FROM mariadb:10.4.5
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y \
|
||||
gettext \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/
|
||||
|
||||
ADD ./docker/ /
|
||||
|
||||
ENTRYPOINT ["/phraseanet-entrypoint.sh"]
|
||||
CMD ["mysqld","--sql_mode="]
|
3
docker/db/docker/custom.cnf
Normal file
3
docker/db/docker/custom.cnf
Normal file
@@ -0,0 +1,3 @@
|
||||
[mysqld]
|
||||
|
||||
max_allowed_packet=$MYSQL_MAX_ALLOWED_PACKET
|
@@ -0,0 +1,5 @@
|
||||
CREATE DATABASE ab_master CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
CREATE DATABASE db_databox1 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
CREATE DATABASE db_unitTest CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
CREATE DATABASE db_dataset1 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
CREATE DATABASE db_dataset2 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
7
docker/db/docker/phraseanet-entrypoint.sh
Executable file
7
docker/db/docker/phraseanet-entrypoint.sh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -eo pipefail
|
||||
shopt -s nullglob
|
||||
|
||||
envsubst < /custom.cnf > /etc/mysql/conf.d/custom.cnf
|
||||
docker-entrypoint.sh "$@"
|
3
docker/elasticsearch/Dockerfile
Normal file
3
docker/elasticsearch/Dockerfile
Normal file
@@ -0,0 +1,3 @@
|
||||
FROM elasticsearch:2.4
|
||||
|
||||
RUN /usr/share/elasticsearch/bin/plugin install analysis-icu
|
@@ -1,6 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -xe
|
||||
|
||||
cat nginx.conf.sample | sed "s/\$MAX_BODY_SIZE/$MAX_BODY_SIZE/g" > /etc/nginx/conf.d/default.conf
|
||||
nginx -g "daemon off;"
|
7
docker/nginx/root/entrypoint.sh
Executable file
7
docker/nginx/root/entrypoint.sh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -xe
|
||||
|
||||
cat /nginx.conf.sample | sed "s/\$MAX_BODY_SIZE/$MAX_BODY_SIZE/g" > /etc/nginx/conf.d/default.conf
|
||||
|
||||
exec "$@"
|
@@ -1,9 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
if [ ! -z ${DOCKER_XDEBUG_ENABLED} ]; then
|
||||
. usr-bin/docker-xdebug-enable
|
||||
fi
|
||||
|
||||
exec "$@"
|
@@ -1,4 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
/sbin/ip route|awk '/default/ { print $3 }'
|
||||
# TODO support MacOS & Windows host IP
|
@@ -1,5 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
unset HOST_IP
|
||||
unset XDEBUG_CONFIG
|
||||
unset XDEBUG_REMOTE_HOST
|
@@ -1,9 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
HOST_IP=$(docker-get-host-ip);
|
||||
|
||||
export HOST_IP
|
||||
export XDEBUG_CONFIG="remote_enable=1 remote_host=${HOST_IP} idekey=PHPSTORM";
|
||||
export XDEBUG_REMOTE_HOST="${HOST_IP}";
|
@@ -2,12 +2,12 @@
|
||||
|
||||
set -xe
|
||||
|
||||
if [ $INSTALL_ACCOUNT_EMAIL = ""]; then
|
||||
if [ -z "$INSTALL_ACCOUNT_EMAIL" ]; then
|
||||
echo "INSTALL_ACCOUNT_EMAIL var is not set."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ $INSTALL_ACCOUNT_PASSWORD = ""]; then
|
||||
if [ -z "$INSTALL_ACCOUNT_PASSWORD" ]; then
|
||||
echo "INSTALL_ACCOUNT_PASSWORD var is not set."
|
||||
exit 1
|
||||
fi
|
||||
@@ -35,11 +35,10 @@ fi
|
||||
## Redis
|
||||
/var/alchemy/Phraseanet/bin/setup system:config set main.cache.options.host redis
|
||||
/var/alchemy/Phraseanet/bin/setup system:config set main.cache.options.port 6379
|
||||
/var/alchemy/Phraseanet/bin/setup system:config set main.cache.options.domain $INSTALL_SERVER_NAME
|
||||
/var/alchemy/Phraseanet/bin/setup system:config set main.cache.options.namespace $INSTALL_SERVER_NAME
|
||||
/var/alchemy/Phraseanet/bin/setup system:config set main.cache.type redis
|
||||
|
||||
# RabbitMQ
|
||||
|
||||
bin/setup system:config set rabbitmq.server.host rabbitmq
|
||||
bin/setup system:config set rabbitmq.server.port 5672
|
||||
bin/setup system:config set rabbitmq.server.user $INSTALL_RABBITMQ_USER
|
||||
|
@@ -1,17 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -xe
|
||||
|
||||
chown -R app:app /var/alchemy/Phraseanet/config
|
||||
chown -R app:app /var/alchemy/Phraseanet/datas
|
||||
chown -R app:app /var/alchemy/Phraseanet/tmp
|
||||
chown -R app:app /var/alchemy/Phraseanet/www/thumbnails
|
||||
FILE=/var/alchemy/Phraseanet/config/configuration.yml
|
||||
if [ -f "$FILE" ]; then
|
||||
echo "$FILE exist, skip setup."
|
||||
else
|
||||
echo "$FILE doesn't exist, entering setup..."
|
||||
runuser app -c '/auto-install.sh'
|
||||
fi
|
||||
|
||||
php-fpm -F
|
29
docker/phraseanet/entrypoint.sh
Executable file
29
docker/phraseanet/entrypoint.sh
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
envsubst < "docker/phraseanet/php.ini.sample" > /usr/local/etc/php/php.ini
|
||||
envsubst < "docker/phraseanet/php-fpm.conf.sample" > /usr/local/etc/php-fpm.conf
|
||||
|
||||
chown -R app:app \
|
||||
config \
|
||||
datas \
|
||||
tmp \
|
||||
logs \
|
||||
www/thumbnails
|
||||
|
||||
FILE=config/configuration.yml
|
||||
|
||||
if [ -f "$FILE" ]; then
|
||||
echo "$FILE exists, skip setup."
|
||||
else
|
||||
echo "$FILE doesn't exist, entering setup..."
|
||||
runuser app -c docker/phraseanet/auto-install.sh
|
||||
fi
|
||||
|
||||
if [ ${XDEBUG_ENABLED} == "1" ]; then
|
||||
echo "XDEBUG is enabled. YOU MAY KEEP THIS FEATURE DISABLED IN PRODUCTION."
|
||||
docker-php-ext-enable xdebug
|
||||
fi
|
||||
|
||||
bash -e docker-php-entrypoint $@
|
@@ -1,19 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
envsubst < /php.ini.sample > /usr/local/etc/php/php.ini
|
||||
envsubst < /php-fpm.conf.sample > /usr/local/etc/php-fpm.conf
|
||||
echo "XDEBUG=$XDEBUG"
|
||||
if [ $XDEBUG = "ON" ]; then
|
||||
echo "XDEBUG IS ENABLED. YOU MAY KEEP THIS FEATURE DISABLED IN PRODUCTION."
|
||||
echo "xdebug.remote_enable=1" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
|
||||
echo "xdebug.remote_autostart=1" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
|
||||
echo "xdebug.remote_host=$XDEBUG_SERVER" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
|
||||
echo "xdebug.remote_port=$XDEBUG_REMOTE_PORT" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
|
||||
echo "xdebug.remote_handler=dbgp" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
|
||||
echo "xdebug.remote_connect_back=0" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
|
||||
#echo "xdebug.idekey=11896" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
|
||||
fi
|
||||
|
||||
bash -e docker-php-entrypoint $@
|
@@ -1,4 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
mkdir /var/alchemy/Phraseanet/tmp/locks && chown -R app:app /var/alchemy/Phraseanet/tmp
|
||||
runuser app -c 'php /var/alchemy/Phraseanet/bin/console task-manager:scheduler:run'
|
18
docker/phraseanet/worker/entrypoint.sh
Executable file
18
docker/phraseanet/worker/entrypoint.sh
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
DOCKER_DIR="./docker/phraseanet"
|
||||
|
||||
mkdir -p "${APP_DIR}/tmp/locks" \
|
||||
&& chown -R app:app "${APP_DIR}/tmp"
|
||||
|
||||
envsubst < "${DOCKER_DIR}/php.ini.sample" > /usr/local/etc/php/php.ini
|
||||
envsubst < "${DOCKER_DIR}/php-fpm.conf.sample" > /usr/local/etc/php-fpm.conf
|
||||
|
||||
if [ ${XDEBUG_ENABLED} == "1" ]; then
|
||||
echo "XDEBUG is enabled. YOU MAY KEEP THIS FEATURE DISABLED IN PRODUCTION."
|
||||
docker-php-ext-enable xdebug
|
||||
fi
|
||||
|
||||
runuser -u app "$@"
|
@@ -246,6 +246,7 @@ class UserApplicationsCommand extends Command
|
||||
$account->getUser()->getId(),
|
||||
$application->getName(),
|
||||
$application->getClientId(),
|
||||
$application->getClientSecret(),
|
||||
$application->getRedirectUri(),
|
||||
($token) ? $token->getOauthToken() : '-',
|
||||
$application->isPasswordGranted() ? "true": "false"
|
||||
@@ -253,7 +254,7 @@ class UserApplicationsCommand extends Command
|
||||
}
|
||||
|
||||
$applicationTable = $this->getHelperSet()->get('table');
|
||||
$headers = ['app_id', 'user_id', 'name', 'client_id', 'callback_url', 'generated token', 'grant_password status'];
|
||||
$headers = ['app_id', 'user_id', 'name', 'client_id', 'client_secret', 'callback_url', 'generated token', 'grant_password status'];
|
||||
|
||||
if ($jsonformat ) {
|
||||
foreach ($applicationList as $appList) {
|
||||
@@ -312,7 +313,7 @@ class UserApplicationsCommand extends Command
|
||||
$application->isPasswordGranted() ? "true": "false"
|
||||
];
|
||||
|
||||
$headers = ['client secret', 'client ID', 'Authorize endpoint url', 'Access endpoint', 'generated token', 'grant_password status'];
|
||||
$headers = ['client_secret', 'client_id', 'Authorize endpoint url', 'Access endpoint', 'generated token', 'grant_password status'];
|
||||
if ($jsonformat ) {
|
||||
$createdAppInfo = array_combine($headers, $applicationCreated);
|
||||
echo json_encode($createdAppInfo);
|
||||
|
@@ -30,8 +30,8 @@ class UserListCommand extends Command
|
||||
{
|
||||
parent::__construct('user:list');
|
||||
|
||||
$this->setDescription('List of all user (experimental)')
|
||||
->addOption('user_id', null, InputOption::VALUE_OPTIONAL, ' The id of user export only info this user ')
|
||||
$this->setDescription('List of all user <comment>(experimental)</>')
|
||||
->addOption('user_id', null, InputOption::VALUE_OPTIONAL, 'The id of user export only info this user ')
|
||||
->addOption('user_email', null, InputOption::VALUE_OPTIONAL, 'The mail of user export only info this user .')
|
||||
->addOption('database_id', null, InputOption::VALUE_OPTIONAL, 'Id of database.')
|
||||
->addOption('collection_id', null, InputOption::VALUE_OPTIONAL, 'Id of the collection.')
|
||||
@@ -39,7 +39,6 @@ class UserListCommand extends Command
|
||||
->addOption('guest', null, InputOption::VALUE_NONE, 'Only guest user')
|
||||
->addOption('created', null, InputOption::VALUE_OPTIONAL, 'Created at with operator,aaaa-mm-jj hh:mm:ss.')
|
||||
->addOption('updated', null, InputOption::VALUE_OPTIONAL, 'Update at with operator,aaaa-mm-jj hh:mm:ss.')
|
||||
->addOption('application', null, InputOption::VALUE_NONE, 'List application of user work only if --user_id is set')
|
||||
->addOption('right', null, InputOption::VALUE_NONE, 'Show right information')
|
||||
->addOption('adress', null, InputOption::VALUE_NONE, 'Show adress information')
|
||||
->addOption('models', null, InputOption::VALUE_NONE, "Show only defined models, if --user_id is set with --models it's the template owner")
|
||||
@@ -58,7 +57,6 @@ class UserListCommand extends Command
|
||||
$collectionId = $input->getOption('collection_id');
|
||||
$lockStatus = $input->getOption('mail_lock_status');
|
||||
$guest = $input->getOption('guest');
|
||||
$application = $input->getOption('application');
|
||||
$withAdress = $input->getOption('adress');
|
||||
$created = $input->getOption('created');
|
||||
$updated = $input->getOption('updated');
|
||||
@@ -77,11 +75,6 @@ class UserListCommand extends Command
|
||||
if($lockStatus && !$models) $query->addSqlFilter('Users.mail_locked = 1');
|
||||
if($guest && !$models) $query->include_invite(true)->addSqlFilter('Users.guest = 1');
|
||||
|
||||
if ($application and !$userId) {
|
||||
$output->writeln('<error>You must provide --user_id when using --application option</error>');
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @var UserRepository $userRepository */
|
||||
$userRepository = $this->container['repo.users'];
|
||||
|
||||
@@ -94,11 +87,7 @@ class UserListCommand extends Command
|
||||
}
|
||||
|
||||
$userList = [];
|
||||
$showApplication = false;
|
||||
foreach ($users as $key => $user) {
|
||||
if ($userId and $application) {
|
||||
$showApplication = true;
|
||||
}
|
||||
$userList[] = $this->listUser($user, $withAdress, $withRight);
|
||||
|
||||
$userListRaw[] = array_combine($this->headerTable($withAdress, $withRight), $this->listUser($user, $withAdress, $withRight));
|
||||
@@ -113,15 +102,6 @@ class UserListCommand extends Command
|
||||
->setRows($userList)
|
||||
->render($output);
|
||||
;
|
||||
|
||||
|
||||
if ($showApplication) {
|
||||
$applicationTable = $this->getHelperSet()->get('table');
|
||||
$applicationTable->setHeaders(array(
|
||||
array(new TableCell('Applications', array('colspan' => 5))),
|
||||
['name','callback','client_secret','client_id','token'],
|
||||
))->setRows($this->getApplicationOfUser($users[0]))->render($output);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -215,37 +195,6 @@ class UserListCommand extends Command
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
* @return array
|
||||
*/
|
||||
private function getApplicationOfUser(User $user)
|
||||
{
|
||||
$apiRepository = $this->container['repo.api-applications'];
|
||||
$applications = $apiRepository->findByUser($user);
|
||||
|
||||
if (empty($applications)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$accountRepository = $this->container['repo.api-accounts'];
|
||||
$apiOauthRepository = $this->container['repo.api-oauth-tokens'];
|
||||
$usersApplication = [];
|
||||
foreach ($applications as $application) {
|
||||
$account = $accountRepository->findByUserAndApplication($user, $application);
|
||||
$token = $account ? $apiOauthRepository->findDeveloperToken($account) : null;
|
||||
$usersApplication[] = [
|
||||
$application->getName(),
|
||||
$application->getRedirectUri(),
|
||||
$application->getClientSecret(),
|
||||
$application->getClientId(),
|
||||
($token) ? $token->getOauthToken() : '-'
|
||||
];
|
||||
}
|
||||
|
||||
return $usersApplication;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $withAdress
|
||||
* @param $withRight
|
||||
|
178
lib/Alchemy/Phrasea/Command/User/UserPasswordCommand.php
Normal file
178
lib/Alchemy/Phrasea/Command/User/UserPasswordCommand.php
Normal file
@@ -0,0 +1,178 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Command\User;
|
||||
|
||||
use Alchemy\Phrasea\Application\Helper\NotifierAware;
|
||||
use Alchemy\Phrasea\Command\Command;
|
||||
use Alchemy\Phrasea\Core\LazyLocator;
|
||||
use Alchemy\Phrasea\Model\Entities\User;
|
||||
use Alchemy\Phrasea\Notification\Receiver;
|
||||
use Alchemy\Phrasea\Notification\Mail\MailRequestPasswordUpdate;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
class UserPasswordCommand extends Command
|
||||
{
|
||||
use NotifierAware;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct($name = null)
|
||||
{
|
||||
parent::__construct('user:password');
|
||||
|
||||
$this->setDescription('Set user password in Phraseanet <comment>(experimental)</>')
|
||||
->addOption('user_id', null, InputOption::VALUE_REQUIRED, 'The id of user.')
|
||||
->addOption('generate', null, InputOption::VALUE_NONE, 'Generate and set with a random value')
|
||||
->addOption('password', null, InputOption::VALUE_OPTIONAL, 'Set the user password to the input value')
|
||||
->addOption('send_renewal_email', null, InputOption::VALUE_NONE, 'Send email link to user for password renewing, work only if --password or --generate are not define')
|
||||
->addOption('password_hash', null, InputOption::VALUE_OPTIONAL, 'Define a password hashed, work only with password_nonce')
|
||||
->addOption('password_nonce', null, InputOption::VALUE_OPTIONAL, 'Define a password nonce, work only with password_hash')
|
||||
->addOption('dump', null, InputOption::VALUE_NONE, 'Return the password hashed and nonce')
|
||||
->addOption('jsonformat', null, InputOption::VALUE_NONE, 'Output in json format')
|
||||
->addOption('yes', 'y', InputOption::VALUE_NONE, 'Answer yes to all questions')
|
||||
|
||||
->setHelp('');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function doExecute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$dialog = $this->getHelperSet()->get('dialog');
|
||||
$userRepository = $this->container['repo.users'];
|
||||
$userManipulator = $this->container['manipulator.user'];
|
||||
|
||||
$user = $userRepository->find($input->getOption('user_id'));
|
||||
$password = $input->getOption('password');
|
||||
$generate = $input->getOption('generate');
|
||||
$sendRenewalEmail = $input->getOption('send_renewal_email');
|
||||
$dump = $input->getOption('dump');
|
||||
$passwordHash = $input->getOption('password_hash');
|
||||
$passwordNonce = $input->getOption('password_nonce');
|
||||
$jsonformat = $input->getOption('jsonformat');
|
||||
$yes = $input->getOption('yes');
|
||||
|
||||
|
||||
if ($user === null) {
|
||||
$output->writeln('<info>Not found User.</info>');
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ($passwordHash && $passwordNonce) {
|
||||
$user->setNonce($passwordNonce);
|
||||
$user->setPassword($passwordHash);
|
||||
$userManipulator->updateUser($user);
|
||||
|
||||
$output->writeln('<info>password set with hashed pass</info>');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ($dump) {
|
||||
$oldHash = $user->getPassword();
|
||||
$oldNonce = $user->getNonce();
|
||||
}
|
||||
|
||||
if ($generate) {
|
||||
$oldHash = $user->getPassword();
|
||||
$oldNonce = $user->getNonce();
|
||||
|
||||
$password = $this->container['random.medium']->generateString(64);
|
||||
} else {
|
||||
if (!$password && $sendRenewalEmail) {
|
||||
$this->sendPasswordSetupMail($user);
|
||||
$output->writeln('<info>email link sended for password renewing!</info>');
|
||||
|
||||
return 0;
|
||||
} elseif (!$password && !$sendRenewalEmail && ! $dump) {
|
||||
$output->writeln('<error>choose one option to set a password!</error>');
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ($password) {
|
||||
if (!$yes) {
|
||||
do {
|
||||
$continue = mb_strtolower($dialog->ask($output, '<question>Do you want really set password to this user? (y/N)</question>', 'N'));
|
||||
} while (!in_array($continue, ['y', 'n']));
|
||||
|
||||
if ($continue !== 'y') {
|
||||
$output->writeln('Aborting !');
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
$oldHash = $user->getPassword();
|
||||
$oldNonce = $user->getNonce();
|
||||
|
||||
$userManipulator->setPassword($user,$password);
|
||||
}
|
||||
|
||||
if ($dump) {
|
||||
if ($jsonformat) {
|
||||
$hash['password_hash'] = $oldHash;
|
||||
$hash['nonce'] = $oldNonce;
|
||||
|
||||
echo json_encode($hash);
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
$output->writeln('<info>password_hash :</info>' . $oldHash);
|
||||
$output->writeln('<info>nonce :</info>' . $oldNonce);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (($password || $generate)) {
|
||||
if ($jsonformat) {
|
||||
$hash['new_password'] = $password;
|
||||
$hash['previous_password_hash'] = $oldHash;
|
||||
$hash['previous_nonce'] = $oldNonce;
|
||||
|
||||
echo json_encode($hash);
|
||||
} else {
|
||||
$output->writeln('<info>new_password :</info>' . $password);
|
||||
$output->writeln('<info>previous_password_hash :</info>' . $oldHash);
|
||||
$output->writeln('<info>previous_nonce :</info>' . $oldNonce);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send mail for renew password
|
||||
* @param User $user
|
||||
*/
|
||||
private function sendPasswordSetupMail(User $user)
|
||||
{
|
||||
$this->setDelivererLocator(new LazyLocator($this->container, 'notification.deliverer'));
|
||||
$receiver = Receiver::fromUser($user);
|
||||
|
||||
$token = $this->container['manipulator.token']->createResetPasswordToken($user);
|
||||
|
||||
$url = $this->container['url_generator']->generate('login_renew_password', [ 'token' => $token->getValue() ], true);
|
||||
$mail = MailRequestPasswordUpdate::create($this->container, $receiver);
|
||||
$servername = $this->container['conf']->get('servername');
|
||||
$mail->setButtonUrl($url);
|
||||
$mail->setLogin($user->getLogin());
|
||||
$mail->setExpiration(new \DateTime('+1 day'));
|
||||
|
||||
$this->deliver($mail);
|
||||
}
|
||||
|
||||
}
|
@@ -1,79 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Command\User;
|
||||
|
||||
use Alchemy\Phrasea\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
|
||||
class UserSetPasswordCommand extends Command
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct($name = null)
|
||||
{
|
||||
parent::__construct('user:set-password');
|
||||
|
||||
$this->setDescription('Set user password in Phraseanet')
|
||||
->addOption('user_id', null, InputOption::VALUE_REQUIRED, 'The id of user.')
|
||||
->addOption('generate', null, InputOption::VALUE_NONE, 'Generate the password')
|
||||
->addOption('password', null, InputOption::VALUE_OPTIONAL, 'The password')
|
||||
->setHelp('');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function doExecute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
|
||||
$dialog = $this->getHelperSet()->get('dialog');
|
||||
$userRepository = $this->container['repo.users'];
|
||||
$userManipulator = $this->container['manipulator.user'];
|
||||
$user = $userRepository->find($input->getOption('user_id'));
|
||||
$password = $input->getOption('password');
|
||||
$generate = $input->getOption('generate');
|
||||
|
||||
if ($user === null) {
|
||||
$output->writeln('<info>Not found User.</info>');
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ($generate) {
|
||||
$password = $this->container['random.medium']->generateString(64);
|
||||
} else {
|
||||
if (!$password) {
|
||||
$output->writeln('<error>--password option not specified</error>');
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
$continue = mb_strtolower($dialog->ask($output, '<question>Do you want really set password to this user? (y/N)</question>', 'N'));
|
||||
} while (!in_array($continue, ['y', 'n']));
|
||||
|
||||
if ($continue !== 'y') {
|
||||
$output->writeln('Aborting !');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$userManipulator->setPassword($user,$password);
|
||||
$output->writeln('New password: <info>' . $password . '</info>');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
@@ -450,6 +450,51 @@ class LightboxController extends Controller
|
||||
return $this->app->json($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Basket $basket
|
||||
* @return Response
|
||||
*/
|
||||
public function ajaxGetElementsAction(Basket $basket)
|
||||
{
|
||||
$ret = [
|
||||
'error' => false,
|
||||
'datas' => [
|
||||
'counts' => [
|
||||
'yes' => 0,
|
||||
'no' => 0,
|
||||
'nul' => 0,
|
||||
'total' => 0
|
||||
]
|
||||
]
|
||||
];
|
||||
try {
|
||||
if (!$basket->getValidation()) {
|
||||
throw new Exception('There is no validation session attached to this basket');
|
||||
}
|
||||
foreach ($basket->getElements() as $element) {
|
||||
$vd = $element->getUserValidationDatas($this->getAuthenticatedUser());
|
||||
if($vd->getAgreement() === true) {
|
||||
$ret['datas']['counts']['yes']++;
|
||||
}
|
||||
elseif($vd->getAgreement() === false) {
|
||||
$ret['datas']['counts']['no']++;
|
||||
}
|
||||
elseif($vd->getAgreement() === null) {
|
||||
$ret['datas']['counts']['nul']++;
|
||||
}
|
||||
$ret['datas']['counts']['total']++;
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$ret = [
|
||||
'error' => true,
|
||||
'datas' => $e->getMessage()
|
||||
];
|
||||
}
|
||||
|
||||
return $this->app->json($ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Basket $basket
|
||||
* @throws Exception
|
||||
|
@@ -105,6 +105,11 @@ class Lightbox implements ControllerProviderInterface, ServiceProviderInterface
|
||||
->assert('basket', '\d+')
|
||||
;
|
||||
|
||||
$controllers->get('/ajax/GET_ELEMENTS/{basket}/', 'controller.lightbox:ajaxGetElementsAction')
|
||||
->bind('lightbox_ajax_get_elements')
|
||||
->assert('basket', '\d+')
|
||||
;
|
||||
|
||||
return $controllers;
|
||||
}
|
||||
|
||||
|
@@ -17,7 +17,7 @@ class Version
|
||||
* @var string
|
||||
*/
|
||||
|
||||
private $number = '4.1.0-alpha.23a';
|
||||
private $number = '4.1.0-alpha.25a';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
|
82
lib/classes/patch/410alpha25a.php
Normal file
82
lib/classes/patch/410alpha25a.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2019 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
use Alchemy\Phrasea\Application;
|
||||
use Alchemy\Phrasea\Core\Configuration\PropertyAccess;
|
||||
|
||||
class patch_410alpha25a implements patchInterface
|
||||
{
|
||||
/** @var string */
|
||||
private $release = '4.1.0-alpha.25a';
|
||||
/** @var array */
|
||||
private $concern = [base::APPLICATION_BOX];
|
||||
/**
|
||||
* Returns the release version.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_release()
|
||||
{
|
||||
return $this->release;
|
||||
}
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function concern()
|
||||
{
|
||||
return $this->concern;
|
||||
}
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function require_all_upgrades()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDoctrineMigrations()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function apply(base $appbox, Application $app)
|
||||
{
|
||||
/** @var PropertyAccess $conf */
|
||||
$conf = $app['conf'];
|
||||
$oldOptions = $conf->get(['main', 'search-engine', 'options'], []);
|
||||
$newOptions = [];
|
||||
$facets = [];
|
||||
// preserve former settings from conf (tech facets)
|
||||
foreach($oldOptions as $k=>$v) {
|
||||
if(substr($k, -16) === '_aggregate_limit') {
|
||||
// this option is moved under "facets"
|
||||
$k = substr($k, 0, strlen($k)-16); // keep field name
|
||||
$facets['_'.$k] = ['limit' => $v];
|
||||
}
|
||||
else {
|
||||
$newOptions[$k] = $v;
|
||||
}
|
||||
}
|
||||
// add facets for fields
|
||||
foreach($app->getDataboxes() as $databox) {
|
||||
foreach($databox->get_meta_structure() as $field) {
|
||||
$facets[$field->get_name()] = ['limit' => $field->getFacetValuesLimit()];
|
||||
}
|
||||
}
|
||||
// facets in the end of settings
|
||||
$newOptions['facets'] = $facets;
|
||||
$conf->set(['main', 'search-engine', 'options'], $newOptions);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -90,13 +90,14 @@ class phraseadate
|
||||
|
||||
$compareTo = new DateTime('now');
|
||||
$diff = $compareTo->format('U') - $date->format('U');
|
||||
$yearDiff = $compareTo->format('Y') - $date->format('Y');
|
||||
$dayDiff = floor($diff / 86400);
|
||||
|
||||
if (is_nan($dayDiff) || $dayDiff > 365000) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$date_string = $this->formatDate($date, $this->app['locale'], 'DAY_MONTH');
|
||||
$date_string = $this->formatDate($date, $this->app['locale'], ($yearDiff != 0) ? 'DAY_MONTH_YEAR' : 'DAY_MONTH');
|
||||
|
||||
if ($dayDiff == 0) {
|
||||
if ($diff < 60) {
|
||||
|
@@ -1328,7 +1328,7 @@
|
||||
<field>
|
||||
<name>host</name>
|
||||
|
||||
<type>char(64)</type>
|
||||
<type>char(255)</type>
|
||||
<null></null>
|
||||
<extra></extra>
|
||||
|
||||
@@ -1403,7 +1403,7 @@
|
||||
</field>
|
||||
<field>
|
||||
<name>label_en</name>
|
||||
<type>char(50)</type>
|
||||
<type>char(128)</type>
|
||||
<null>YES</null>
|
||||
<extra></extra>
|
||||
<default></default>
|
||||
@@ -1411,7 +1411,7 @@
|
||||
</field>
|
||||
<field>
|
||||
<name>label_fr</name>
|
||||
<type>char(50)</type>
|
||||
<type>char(128)</type>
|
||||
<null>YES</null>
|
||||
<extra></extra>
|
||||
<default></default>
|
||||
@@ -1419,7 +1419,7 @@
|
||||
</field>
|
||||
<field>
|
||||
<name>label_de</name>
|
||||
<type>char(50)</type>
|
||||
<type>char(128)</type>
|
||||
<null>YES</null>
|
||||
<extra></extra>
|
||||
<default></default>
|
||||
@@ -1427,7 +1427,7 @@
|
||||
</field>
|
||||
<field>
|
||||
<name>label_nl</name>
|
||||
<type>char(50)</type>
|
||||
<type>char(128)</type>
|
||||
<null>YES</null>
|
||||
<extra></extra>
|
||||
<default></default>
|
||||
|
@@ -65,7 +65,7 @@
|
||||
"normalize-css": "^2.1.0",
|
||||
"npm": "^6.0.0",
|
||||
"npm-modernizr": "^2.8.3",
|
||||
"phraseanet-production-client": "0.34.142-d",
|
||||
"phraseanet-production-client": "0.34.150-d",
|
||||
"requirejs": "^2.3.5",
|
||||
"tinymce": "^4.0.28",
|
||||
"underscore": "^1.8.3",
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
<?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">
|
||||
<file date="2020-02-27T14:59:20Z" source-language="en" target-language="de" datatype="plaintext" original="not.available">
|
||||
<file date="2020-03-13T14:06:24Z" source-language="en" target-language="de" datatype="plaintext" original="not.available">
|
||||
<header>
|
||||
<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>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<?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">
|
||||
<file date="2020-02-27T15:00:00Z" source-language="en" target-language="en" datatype="plaintext" original="not.available">
|
||||
<file date="2020-03-13T14:06:35Z" source-language="en" target-language="en" datatype="plaintext" original="not.available">
|
||||
<header>
|
||||
<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>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<?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">
|
||||
<file date="2020-02-27T15:00:28Z" source-language="en" target-language="fr" datatype="plaintext" original="not.available">
|
||||
<file date="2020-03-13T14:06:47Z" source-language="en" target-language="fr" datatype="plaintext" original="not.available">
|
||||
<header>
|
||||
<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>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<?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">
|
||||
<file date="2020-02-27T15:00:57Z" source-language="en" target-language="nl" datatype="plaintext" original="not.available">
|
||||
<file date="2020-03-13T14:07:03Z" source-language="en" target-language="nl" datatype="plaintext" original="not.available">
|
||||
<header>
|
||||
<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>
|
||||
|
@@ -474,6 +474,17 @@ class Basket extends \Alchemy\Phrasea\Model\Entities\Basket implements \Doctrine
|
||||
return parent::hasRecord($app, $record);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getElementByRecord(\Alchemy\Phrasea\Application $app, \record_adapter $record)
|
||||
{
|
||||
|
||||
$this->__initializer__ && $this->__initializer__->__invoke($this, 'getElementByRecord', [$app, $record]);
|
||||
|
||||
return parent::getElementByRecord($app, $record);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
@@ -518,4 +518,15 @@ class LazaretFile extends \Alchemy\Phrasea\Model\Entities\LazaretFile implements
|
||||
return parent::getRecordsToSubstitute($app, $includeReason);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getStatus(\Alchemy\Phrasea\Application $app)
|
||||
{
|
||||
|
||||
$this->__initializer__ && $this->__initializer__->__invoke($this, 'getStatus', [$app]);
|
||||
|
||||
return parent::getStatus($app);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -543,6 +543,23 @@ hr {
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.modal-footer .btn-primary {
|
||||
color: #fff!important;
|
||||
background-color: #007bff!important;
|
||||
border-color: #007bff!important;
|
||||
}
|
||||
.modal-header .close {
|
||||
display: inline-block;
|
||||
float: right;
|
||||
width: 25px;
|
||||
opacity: 1;
|
||||
background: #e1e1e1;
|
||||
}
|
||||
|
||||
.hide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
button.confirm_report {
|
||||
background: #38c !important;
|
||||
color: #fff !important;
|
||||
|
@@ -13,5 +13,7 @@
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
||||
{% endif %}
|
||||
|
||||
|
@@ -4,10 +4,12 @@
|
||||
<script type="text/javascript" src="/assets/production/commons{% if not app.debug %}.min{% endif %}.js"></script>
|
||||
<script type="text/javascript" src="/assets/production/lightbox-mobile{% if not app.debug %}.min{% endif %}.js"></script>
|
||||
{# <script type="text/javascript" src="/assets/lightbox/js/lightbox-mobile{% if not app.debug %}.min{% endif %}.js"></script>#}
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block stylesheet %}
|
||||
<link type="text/css" rel="stylesheet" href="/assets/lightbox/css/lightbox-mobile{% if not app.debug %}.min{% endif %}.css" />
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
|
||||
{% endblock %}
|
||||
|
||||
{% block icon %}
|
||||
@@ -62,7 +64,6 @@
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="about" data-role="page">
|
||||
<div data-role="header">
|
||||
<a href="#home" data-rel="back" data-icon="arrow-l">{{ 'Back' | trans }}</a>
|
||||
@@ -99,6 +100,7 @@
|
||||
{{ 'Validations' | trans }}
|
||||
<span>{{_self.valid_baskets_length(baskets_collection)}}</span>
|
||||
</p>
|
||||
|
||||
<p class="lightbox-msg">
|
||||
{{ 'Voici vos validations en cours' | trans }}
|
||||
</p>
|
||||
@@ -168,7 +170,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script>
|
||||
var lightboxApp = lightboxMobileApplication.bootstrap({
|
||||
lang: '{{ app.locale }}',
|
||||
|
@@ -4,6 +4,7 @@
|
||||
{% block javascript %}
|
||||
<script type="text/javascript" src="/assets/production/commons{% if not app.debug %}.min{% endif %}.js"></script>
|
||||
<script type="text/javascript" src="/assets/production/lightbox-mobile{% if not app.debug %}.min{% endif %}.js"></script>
|
||||
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
{% if basket.getValidation() %}
|
||||
@@ -14,13 +15,15 @@
|
||||
releasable: {% if basket.getValidation().getParticipant(app.getAuthenticatedUser()).isReleasable() %}"{{ 'Do you want to send your report ?' | trans }}"{% else %}false{% endif %}
|
||||
});
|
||||
|
||||
//var releasable = {% if basket.getValidation().getParticipant(app.getAuthenticatedUser()).isReleasable() %}"{{ 'Do you want to send your report ?' | trans }}"{% else %}false{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block stylesheet %}
|
||||
<link type="text/css" rel="stylesheet" href="/assets/lightbox/css/lightbox-mobile{% if not app.debug %}.min{% endif %}.css" />
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
@@ -41,7 +44,40 @@
|
||||
{% set basket_length = basket.getElements().count() %}
|
||||
{% trans with {'%basket_length%' : basket_length} %}%basket_length% documents{% endtrans %}
|
||||
</p>
|
||||
|
||||
|
||||
{% if basket.getValidation() %}
|
||||
<div id="FeedbackRelease" class="modal fade" role="dialog" style="display: none">
|
||||
<div class="modal-dialog">
|
||||
<!-- Modal content-->
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
×</button>
|
||||
<h4 class="modal-title">{{ 'lightbox:feedback:sendreport:warnwindows:title' | trans }}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>{{'lightbox:feedback:sendreport:warnwindows:message ' | trans}}</p>
|
||||
|
||||
<p>{{ 'lightbox:feedback:sendreport:warnwindows:record_approved'| trans }} : <span class="record_accepted"></span>
|
||||
|
||||
</p>
|
||||
<hr>
|
||||
<p>
|
||||
{{'lightbox:feedback:sendreport:warnwindows:record_rejected'| trans }} : <span class="record_refused"></span>
|
||||
</p>
|
||||
<hr>
|
||||
<p>
|
||||
{{'lightbox:feedback:sendreport:warnwindows:record_unexpressed'| trans }} : <span class="record_null"></span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal" style="width:auto">{{ 'lightbox:feedback:sendreport:warnwindows:cancel'| trans }}</button>
|
||||
<button type="button" class="btn btn-primary" id="validate-release" style="width:auto">{{ 'lightbox:feedback:sendreport:warnwindows:validate'| trans }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="report_wrapper">
|
||||
<a id="report_summary" class="report_btn report_summary" href="#" onclick="$.ajax({
|
||||
type: 'GET',
|
||||
@@ -92,7 +128,11 @@
|
||||
|
||||
<div class="btn-container">
|
||||
{% if basket.getValidation() and basket.getValidation().getParticipant(app.getAuthenticatedUser()).getCanAgree() %}
|
||||
<button class="confirm_report" style="width:100%;" title="{{ 'validation::envoyer mon rapport' | trans }}">
|
||||
<button class="confirm_report" style="width:100%;" title="{{ 'validation::envoyer mon rapport' | trans }}" onclick="
|
||||
|
||||
|
||||
|
||||
">
|
||||
{{ 'validation::envoyer mon rapport' | trans }}
|
||||
<img src="/assets/common/images/icons/loader1F1E1B.gif" style="visibility:hidden;" class="loader"/>
|
||||
</button>
|
||||
@@ -100,7 +140,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
@@ -116,6 +116,39 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="FeedbackRelease" class="modal fade" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<!-- Modal content-->
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
×</button>
|
||||
<h4 class="modal-title">{{ 'lightbox:feedback:sendreport:warnwindows:title' | trans }}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>{{'lightbox:feedback:sendreport:warnwindows:message ' | trans}}</p>
|
||||
|
||||
<p>{{ 'lightbox:feedback:sendreport:warnwindows:record_approved'| trans }} : <span class="record_accepted"></span>
|
||||
|
||||
</p>
|
||||
<hr>
|
||||
<p>
|
||||
{{'lightbox:feedback:sendreport:warnwindows:record_rejected'| trans }} : <span class="record_refused"></span>
|
||||
</p>
|
||||
<hr>
|
||||
<p>
|
||||
{{'lightbox:feedback:sendreport:warnwindows:record_unexpressed'| trans }} : <span class="record_null"></span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">{{ 'lightbox:feedback:sendreport:warnwindows:cancel'| trans }}</button>
|
||||
<button type="button" class="btn btn-primary" id="validate-release">{{ 'lightbox:feedback:sendreport:warnwindows:validate'| trans }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="PNB" id="bottom_container">
|
||||
<div class="PNB" style="height:30px;bottom:auto;">
|
||||
<table border="0" cellspacing="0" cellpadding="0" style="width:100%;">
|
||||
|
@@ -8,14 +8,23 @@
|
||||
|
||||
{% block content %}
|
||||
<div class="noToolTipResize" style="margin:5px;width:{{ width - 40 }}px;height:auto !important;height:380px;max-height:380px;min-height:220px;position:relative;">
|
||||
<span class="expiredDate">
|
||||
{% if basket.getValidation() %}
|
||||
{% set dateExpired = app['date-formatter'].getPrettyString(basket.getValidation().getExpires()) %}
|
||||
{{ 'workzone:feedback:expiration' | trans }} : {{ dateExpired }}
|
||||
{% endif %}
|
||||
</span>
|
||||
<div style="margin:5px 0;max-height:160px;overflow:hidden;text-overflow:ellipsis;">
|
||||
{{ basket.getDescription()|nl2br }}
|
||||
</div>
|
||||
<div style="margin:5px 0;text-align:right;font-style:italic;position:relative;">
|
||||
<div style="margin:5px 0;font-style:italic;position:relative;width: 100%">
|
||||
{% set nb_records = basket.getElements()|length %}
|
||||
{% set date = app['date-formatter'].getPrettyString(basket.getUpdated()) %}
|
||||
{% trans with {'%nb_records%' : nb_records} %}%nb_records% records{% endtrans %}
|
||||
- {{ date }}
|
||||
|
||||
<div style="text-align:right">
|
||||
{% trans with {'%nb_records%' : nb_records} %}%nb_records% records{% endtrans %}
|
||||
- {{ 'prod:workzone:basket:creation-date' | trans }} : {{ date }}
|
||||
</div>
|
||||
<hr/>
|
||||
<div style="position:relative;float:left;width:470px;">
|
||||
{% for element in basket.getElements() %}
|
||||
|
@@ -1,3 +1,4 @@
|
||||
|
||||
<div>
|
||||
<button class="tools-accordion">Actions</button>
|
||||
<div class="tools-panel">
|
||||
@@ -88,8 +89,30 @@
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if basket.getValidation() %}
|
||||
<div class="feedback-info">
|
||||
{% set nb_records = basket.getElements()|length %}
|
||||
{% set date = app['date-formatter'].getPrettyString(basket.getUpdated()) %}
|
||||
|
||||
<p class="create-date">
|
||||
{{ 'prod:workzone:basket:creation-date' | trans }} : {{ date }}
|
||||
</p>
|
||||
<div class="record-number"> {% trans with {'%nb_records%' : nb_records} %}%nb_records% records{% endtrans %}</div>
|
||||
|
||||
{% set dateExpired = app['date-formatter'].getPrettyString(basket.getValidation().getExpires()) %}
|
||||
<div class="expiredDate">
|
||||
<span>{{ 'workzone:feedback:expiration' | trans }} :</span>
|
||||
<form class="update-feed-validation">
|
||||
<input type="hidden" name="feedback-id" value={{ basket.getValidation().getId}} />
|
||||
<input type="hidden" name="feedback-deadline-format" class="alternate" />
|
||||
<input type="text" class="btn datepicker" name="feedback-deadline" value="{{ dateExpired }}">
|
||||
<button type="submit" class="submit" title="{{ 'workzone:feedback:update' | trans }}"><i class="fa fa-save"></i></button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="basket-content">
|
||||
{% set basket_length = basket.getElements()|length %}
|
||||
<div class="alert_datas_changed ui-corner-all">{{ 'Certaines donnees du panier ont change' | trans }} <a class="basket_refresher" href="#">{{ 'rafraichir' | trans }}</a></div>
|
||||
{% if basket_length == 0 %}
|
||||
@@ -102,10 +125,38 @@
|
||||
|
||||
{% if basket.getValidation() %}
|
||||
{{ Macros.display_validation(app, basket, ordre) }}
|
||||
|
||||
{% else %}
|
||||
{{ Macros.display_basket(app, basket) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
$( ".update-feed-validation" ).on( "submit", function( event ) {
|
||||
event.preventDefault();
|
||||
console.log( $( this ).serialize() );
|
||||
});
|
||||
$( function() {
|
||||
$.datepicker.regional['default'] = {
|
||||
closeText: "{{ 'workzone:datepicker:closeText' | trans }}",
|
||||
prevText: "{{ 'workzone:datepicker:prevText' | trans }}",
|
||||
nextText: "{{ 'workzone:datepicker:nextText' | trans }}",
|
||||
currentText: "{{ 'workzone:datepicker:currentText' | trans }}",
|
||||
monthNames: [ "{{ 'workzone:datepicker:january' | trans }}", "{{ 'workzone:datepicker:february' | trans }}", "{{ 'workzone:datepicker:march' | trans }}", "{{ 'workzone:datepicker:april' | trans }}", "{{ 'workzone:datepicker:may' | trans }}", "{{ 'workzone:datepicker:june' | trans }}",
|
||||
"{{ 'workzone:datepicker:july' | trans }}", "{{ 'workzone:datepicker:august' | trans }}", "{{ 'workzone:datepicker:september' | trans }}", "{{ 'workzone:datepicker:october' | trans }}", "{{ 'workzone:datepicker:november' | trans }}", "{{ 'workzone:datepicker:december' | trans }}" ],
|
||||
dayNames: [ "{{ 'workzone:datepicker:sunday' | trans }}", "{{ 'workzone:datepicker:monday' | trans }}", "{{ 'workzone:datepicker:tuesday' | trans }}", "{{ 'workzone:datepicker:wednesday' | trans }}", "{{ 'workzone:datepicker:thursday' | trans }}", "{{ 'workzone:datepicker:friday' | trans }}", "{{ 'workzone:datepicker:saturday' | trans }}" ],
|
||||
dayNamesMin: [ "D","L","M","M","J","V","S" ],
|
||||
dateFormat: "d MM yy",
|
||||
altField: ".alternate",
|
||||
altFormat: "yy-mm-dd"
|
||||
|
||||
};
|
||||
|
||||
$( ".datepicker" ).datepicker( $.datepicker.regional[ 'default' ]);
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
@@ -37,10 +37,11 @@
|
||||
{% set content = WorkZone.getContent(srt) %}
|
||||
<div id="validations-block" class="validations-block">
|
||||
{% for basket in content.get(constant('\\Alchemy\\Phrasea\\Helper\\WorkZone::VALIDATIONS')) %}
|
||||
|
||||
<div tooltipsrc="{{ path('prod_tooltip_basket', { 'basket' : basket.getId() }) }}"
|
||||
id="SSTT_{{basket.getId()}}"
|
||||
class="basketTips ui-accordion-header ui-state-default
|
||||
ui-corner-all header SSTT basket {% if not basket.isRead() %}unread{% endif %}
|
||||
ui-corner-all header SSTT basket {% if not basket.getId() %}unread{% endif %}
|
||||
{% if basket.getId() == selected_id and selected_type == 'basket' %}active{% endif %}">
|
||||
<a class="workzone-menu-title" href="{{ path('prod_baskets_basket', { 'basket' : basket.getId() }) }}">
|
||||
<span>
|
||||
@@ -52,6 +53,7 @@
|
||||
{{basket.getName()|e}}
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<div class="menu">
|
||||
<table>
|
||||
<tr>
|
||||
@@ -113,6 +115,7 @@
|
||||
</div>
|
||||
<div id="all_baskets-block" class="all_baskets-block">
|
||||
{% for basket in content.get(constant('\\Alchemy\\Phrasea\\Helper\\WorkZone::BASKETS')) %}
|
||||
|
||||
<div tooltipsrc="{{ path('prod_tooltip_basket', { 'basket' : basket.getId() }) }}"
|
||||
id="SSTT_{{basket.getId()}}"
|
||||
class="basketTips ui-accordion-header ui-state-default
|
||||
|
@@ -7577,10 +7577,10 @@ phraseanet-common@^0.4.5-d:
|
||||
js-cookie "^2.1.0"
|
||||
pym.js "^1.3.1"
|
||||
|
||||
phraseanet-production-client@0.34.142-d:
|
||||
version "0.34.142-d"
|
||||
resolved "https://registry.yarnpkg.com/phraseanet-production-client/-/phraseanet-production-client-0.34.142-d.tgz#9b66d9722e316c9af0ec35c9f497932b70c28c2e"
|
||||
integrity sha512-U4gholdgWgjas16yerS+XqfrTcAhOCMMwXSbj8sapCdHUxy1GnSSelKcx/OTp+IPU/0oWpjT0I6M27azxhA/Sw==
|
||||
phraseanet-production-client@0.34.150-d:
|
||||
version "0.34.150-d"
|
||||
resolved "https://registry.yarnpkg.com/phraseanet-production-client/-/phraseanet-production-client-0.34.150-d.tgz#625ea96c045719b405fe9b707b632b1290aca285"
|
||||
integrity sha512-JrtPq6dCTCBxX6kGViXZj4Sc26PMFIaifT3PVD1WHLUCNd/U3nnHzpzKUgVC0ibqOj4aVwA8JW/oMilGEe3cmg==
|
||||
dependencies:
|
||||
"@mapbox/mapbox-gl-language" "^0.9.2"
|
||||
"@turf/turf" "^5.1.6"
|
||||
|
Reference in New Issue
Block a user