Merge branch 'master' into PHRAS-2964-41-change-column-size

This commit is contained in:
Nicolas Maillat
2020-03-09 15:23:34 +01:00
committed by GitHub
45 changed files with 10369 additions and 905 deletions

View File

@@ -1,12 +1,35 @@
.circleci .idea
.git
.settings .settings
nodes_modules /*.md
vendor /.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
View 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
View File

@@ -71,3 +71,7 @@ playbook.retry
npm-debug.log npm-debug.log
/Phrasea_datas /Phrasea_datas
.env.*
env.local
/volumes

View File

@@ -1,4 +1,3 @@
######################################################################### #########################################################################
# This image contains every build tools that will be used by the builder and # This image contains every build tools that will be used by the builder and
# the app images (usefull in dev mode) # the app images (usefull in dev mode)
@@ -11,7 +10,8 @@ RUN apt-get update \
ca-certificates \ ca-certificates \
gnupg2 \ gnupg2 \
&& apt-get update \ && apt-get update \
&& apt-get install -y --no-install-recommends zlib1g-dev \ && apt-get install -y --no-install-recommends \
zlib1g-dev \
git \ git \
ghostscript \ ghostscript \
gpac \ gpac \
@@ -36,18 +36,32 @@ RUN apt-get update \
xpdf \ xpdf \
&& 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 \
&& apt-get clean \ && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
&& 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-install -j$(nproc) gd \ && docker-php-ext-install -j$(nproc) gd \
&& docker-php-ext-install zip exif iconv mbstring pcntl sockets xsl intl pdo_mysql gettext bcmath mcrypt \ && 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 \ && docker-php-ext-enable redis amqp zmq imagick \
&& pecl clear-cache \ && pecl clear-cache \
&& docker-php-source delete \ && 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 COPY --from=composer:1.9.1 /usr/bin/composer /usr/bin/composer
@@ -56,73 +70,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://linuxize.com/post/how-to-install-node-js-on-ubuntu-18.04/
# https://yarnpkg.com/lang/en/docs/install/#debian-stable # https://yarnpkg.com/lang/en/docs/install/#debian-stable
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - \ 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 - \ && 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 \ && 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 \ && 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 \ WORKDIR /var/alchemy/Phraseanet
&& useradd -u 1000 app \
&& mkdir -p /home/app/.composer \
&& chown -R app: /home/app /var/alchemy
######################################################################### USER app
# This image is used to build the apps
#########################################################################
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/ ADD docker/phraseanet/ /
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
######################################################################### #########################################################################
# Phraseanet web application image # Phraseanet web application image
@@ -130,31 +104,29 @@ RUN mkdir -p /var/alchemy/Phraseanet/logs \
FROM phraseanet-system as phraseanet-fpm FROM phraseanet-system as phraseanet-fpm
RUN docker-php-source extract \ COPY --from=builder --chown=app /var/alchemy/Phraseanet /var/alchemy/Phraseanet
&& pecl install xdebug-2.9.0 \ ADD ./docker/phraseanet/root /
&& 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/ /
WORKDIR /var/alchemy/Phraseanet WORKDIR /var/alchemy/Phraseanet
ENTRYPOINT ["/phraseanet-entrypoint.sh"] ENTRYPOINT ["docker/phraseanet/entrypoint.sh"]
CMD ["/boot.sh"] CMD ["php-fpm", "-F"]
######################################################################### #########################################################################
# Phraseanet worker application image # Phraseanet worker application image
######################################################################### #########################################################################
FROM phraseanet-fpm as phraseanet-worker 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 # phraseanet-nginx
######################################################################### #########################################################################
FROM nginx:1.15 as phraseanet-nginx FROM nginx:1.17.8-alpine as phraseanet-nginx
RUN useradd -u 1000 app RUN adduser --uid 1000 --disabled-password app
ADD ./docker/nginx/ / ADD ./docker/nginx/root /
COPY --from=builder /var/alchemy/www /var/alchemy/Phraseanet/www COPY --from=builder /var/alchemy/Phraseanet/www /var/alchemy/Phraseanet/www
CMD ["/boot.sh"]
ENTRYPOINT ["/entrypoint.sh"]
CMD ["nginx", "-g", "daemon off;"]

View File

@@ -5,7 +5,10 @@ install:
make install_assets make install_assets
install_composer: 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: install_asset_dependencies:
yarn install yarn install

130
README.md
View File

@@ -32,7 +32,109 @@ You can also download a testing pre installed Virtual Machine in OVA format here
https://www.phraseanet.com/download/ 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:
![PhpStorm mapping](https://i.ibb.co/GMb43Cv/image.png)
> 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. 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. 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 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.

View File

@@ -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 .

View 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
View 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

View 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

File diff suppressed because it is too large Load Diff

12
docker/db/Dockerfile Normal file
View 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="]

View File

@@ -0,0 +1,3 @@
[mysqld]
max_allowed_packet=$MYSQL_MAX_ALLOWED_PACKET

View File

@@ -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;

View 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 "$@"

View File

@@ -0,0 +1,3 @@
FROM elasticsearch:2.4
RUN /usr/share/elasticsearch/bin/plugin install analysis-icu

View File

@@ -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;"

View 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 "$@"

View File

@@ -1,9 +0,0 @@
#!/bin/sh
set -e
if [ ! -z ${DOCKER_XDEBUG_ENABLED} ]; then
. usr-bin/docker-xdebug-enable
fi
exec "$@"

View File

@@ -1,4 +0,0 @@
#!/bin/sh
/sbin/ip route|awk '/default/ { print $3 }'
# TODO support MacOS & Windows host IP

View File

@@ -1,5 +0,0 @@
#!/bin/sh
unset HOST_IP
unset XDEBUG_CONFIG
unset XDEBUG_REMOTE_HOST

View File

@@ -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}";

View File

@@ -2,12 +2,12 @@
set -xe set -xe
if [ $INSTALL_ACCOUNT_EMAIL = ""]; then if [ -z "$INSTALL_ACCOUNT_EMAIL" ]; then
echo "INSTALL_ACCOUNT_EMAIL var is not set." echo "INSTALL_ACCOUNT_EMAIL var is not set."
exit 1 exit 1
fi fi
if [ $INSTALL_ACCOUNT_PASSWORD = ""]; then if [ -z "$INSTALL_ACCOUNT_PASSWORD" ]; then
echo "INSTALL_ACCOUNT_PASSWORD var is not set." echo "INSTALL_ACCOUNT_PASSWORD var is not set."
exit 1 exit 1
fi fi
@@ -35,11 +35,10 @@ fi
## Redis ## 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.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.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 /var/alchemy/Phraseanet/bin/setup system:config set main.cache.type redis
# RabbitMQ # RabbitMQ
bin/setup system:config set rabbitmq.server.host 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.port 5672
bin/setup system:config set rabbitmq.server.user $INSTALL_RABBITMQ_USER bin/setup system:config set rabbitmq.server.user $INSTALL_RABBITMQ_USER

View File

@@ -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
View 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 $@

View File

@@ -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 $@

View File

@@ -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'

View 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 "$@"

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

View File

@@ -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-02-27T14:59:20Z" source-language="en" target-language="de" datatype="plaintext" original="not.available"> <file date="2020-03-04T14:02:22Z" 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>

View File

@@ -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-02-27T15:00:00Z" source-language="en" target-language="en" datatype="plaintext" original="not.available"> <file date="2020-03-04T14:02:31Z" 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>

View File

@@ -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-02-27T15:00:28Z" source-language="en" target-language="fr" datatype="plaintext" original="not.available"> <file date="2020-03-04T14:02:43Z" 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>

View File

@@ -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-02-27T15:00:57Z" source-language="en" target-language="nl" datatype="plaintext" original="not.available"> <file date="2020-03-04T14:02:56Z" 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>

View File

@@ -474,6 +474,17 @@ class Basket extends \Alchemy\Phrasea\Model\Entities\Basket implements \Doctrine
return parent::hasRecord($app, $record); 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} * {@inheritDoc}
*/ */

View File

@@ -518,4 +518,15 @@ class LazaretFile extends \Alchemy\Phrasea\Model\Entities\LazaretFile implements
return parent::getRecordsToSubstitute($app, $includeReason); 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);
}
} }

View File

@@ -11,11 +11,19 @@
<div style="margin:5px 0;max-height:160px;overflow:hidden;text-overflow:ellipsis;"> <div style="margin:5px 0;max-height:160px;overflow:hidden;text-overflow:ellipsis;">
{{ basket.getDescription()|nl2br }} {{ basket.getDescription()|nl2br }}
</div> </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 nb_records = basket.getElements()|length %}
{% set date = app['date-formatter'].getPrettyString(basket.getUpdated()) %} {% set date = app['date-formatter'].getPrettyString(basket.getUpdated()) %}
<span class="expiredDate" style="width: 40%; display: inline-block">
{% if basket.getValidation() %}
{% set dateExpired = app['date-formatter'].getPrettyString(basket.getValidation().getExpires()) %}
{{ 'workzone:feedback:expiration' | trans }} : {{ dateExpired }}
{% endif %}
</span>
<div style="text-align:right;width: 50%;display: inline-block">
{% trans with {'%nb_records%' : nb_records} %}%nb_records% records{% endtrans %} {% trans with {'%nb_records%' : nb_records} %}%nb_records% records{% endtrans %}
- {{ date }} - {{ date }}
</div>
<hr/> <hr/>
<div style="position:relative;float:left;width:470px;"> <div style="position:relative;float:left;width:470px;">
{% for element in basket.getElements() %} {% for element in basket.getElements() %}

View File

@@ -88,8 +88,12 @@
{% endfor %} {% endfor %}
{% endif %} {% endif %}
</div> </div>
{% if basket.getValidation() %}
{% set dateExpired = app['date-formatter'].getPrettyString(basket.getValidation().getExpires()) %}
<span class="expiredDate" style="float: right; padding: 8px;margin-top: -39px;">
{{ 'workzone:feedback:expiration' | trans }} : {{ dateExpired }}</span>
{% endif %}
</div> </div>
<div class="basket-content">
{% set basket_length = basket.getElements()|length %} {% 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> <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 %} {% if basket_length == 0 %}
@@ -102,6 +106,7 @@
{% if basket.getValidation() %} {% if basket.getValidation() %}
{{ Macros.display_validation(app, basket, ordre) }} {{ Macros.display_validation(app, basket, ordre) }}
{% else %} {% else %}
{{ Macros.display_basket(app, basket) }} {{ Macros.display_basket(app, basket) }}
{% endif %} {% endif %}

View File

@@ -37,10 +37,11 @@
{% set content = WorkZone.getContent(srt) %} {% set content = WorkZone.getContent(srt) %}
<div id="validations-block" class="validations-block"> <div id="validations-block" class="validations-block">
{% for basket in content.get(constant('\\Alchemy\\Phrasea\\Helper\\WorkZone::VALIDATIONS')) %} {% for basket in content.get(constant('\\Alchemy\\Phrasea\\Helper\\WorkZone::VALIDATIONS')) %}
<div tooltipsrc="{{ path('prod_tooltip_basket', { 'basket' : basket.getId() }) }}" <div tooltipsrc="{{ path('prod_tooltip_basket', { 'basket' : basket.getId() }) }}"
id="SSTT_{{basket.getId()}}" id="SSTT_{{basket.getId()}}"
class="basketTips ui-accordion-header ui-state-default 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 %}"> {% if basket.getId() == selected_id and selected_type == 'basket' %}active{% endif %}">
<a class="workzone-menu-title" href="{{ path('prod_baskets_basket', { 'basket' : basket.getId() }) }}"> <a class="workzone-menu-title" href="{{ path('prod_baskets_basket', { 'basket' : basket.getId() }) }}">
<span> <span>
@@ -52,6 +53,7 @@
{{basket.getName()|e}} {{basket.getName()|e}}
</span> </span>
</a> </a>
<div class="menu"> <div class="menu">
<table> <table>
<tr> <tr>
@@ -113,6 +115,7 @@
</div> </div>
<div id="all_baskets-block" class="all_baskets-block"> <div id="all_baskets-block" class="all_baskets-block">
{% for basket in content.get(constant('\\Alchemy\\Phrasea\\Helper\\WorkZone::BASKETS')) %} {% for basket in content.get(constant('\\Alchemy\\Phrasea\\Helper\\WorkZone::BASKETS')) %}
<div tooltipsrc="{{ path('prod_tooltip_basket', { 'basket' : basket.getId() }) }}" <div tooltipsrc="{{ path('prod_tooltip_basket', { 'basket' : basket.getId() }) }}"
id="SSTT_{{basket.getId()}}" id="SSTT_{{basket.getId()}}"
class="basketTips ui-accordion-header ui-state-default class="basketTips ui-accordion-header ui-state-default