Merge branch 'master' into PHRAS-2680-webhook-privacy-and-security

This commit is contained in:
Nicolas Maillat
2019-12-12 12:07:02 +01:00
committed by GitHub
26 changed files with 752 additions and 312 deletions

View File

@@ -107,6 +107,53 @@ jobs:
- store_artifacts: - store_artifacts:
path: /tmp/circleci-test-results path: /tmp/circleci-test-results
build_phraseanet-fpm:
machine:
image: ubuntu-1604:201903-01
docker_layer_caching: true
working_directory: ~/alchemy-fr/Phraseanet
steps:
- checkout
- aws-ecr/ecr-login:
region: AWS_DEFAULT_REGION
- run: docker build --target phraseanet-fpm -t ${AWS_ACCOUNT_URL}/phraseanet-fpm:${CIRCLE_BRANCH} .
- aws-ecr/push-image:
account-url: AWS_ACCOUNT_URL
repo: "phraseanet-fpm"
tag: "${CIRCLE_BRANCH}"
build_phraseanet-worker:
machine:
image: ubuntu-1604:201903-01
docker_layer_caching: true
working_directory: ~/alchemy-fr/Phraseanet
steps:
- checkout
- aws-ecr/ecr-login:
region: AWS_DEFAULT_REGION
- run: docker build --target phraseanet-worker -t ${AWS_ACCOUNT_URL}/phraseanet-worker:${CIRCLE_BRANCH} .
- aws-ecr/push-image:
account-url: AWS_ACCOUNT_URL
repo: "phraseanet-worker"
tag: "${CIRCLE_BRANCH}"
build_phraseanet-nginx:
machine:
image: ubuntu-1604:201903-01
docker_layer_caching: true
working_directory: ~/alchemy-fr/Phraseanet
steps:
- checkout
- aws-ecr/ecr-login:
region: AWS_DEFAULT_REGION
- run: docker build --target phraseanet-nginx -t ${AWS_ACCOUNT_URL}/phraseanet-nginx:${CIRCLE_BRANCH} .
- aws-ecr/push-image:
account-url: AWS_ACCOUNT_URL
repo: "phraseanet-nginx"
tag: "${CIRCLE_BRANCH}"
workflows: workflows:
version: 2 version: 2
oldfashion: oldfashion:
@@ -114,36 +161,9 @@ workflows:
- build - build
newfashion: newfashion:
jobs: jobs:
- aws-ecr/build_and_push_image: - build_phraseanet-fpm:
account-url: AWS_ACCOUNT_URL
aws-access-key-id: AWS_ACCESS_KEY_ID
aws-secret-access-key: AWS_SECRET_ACCESS_KEY
context: "AWS London" context: "AWS London"
create-repo: true - build_phraseanet-worker:
dockerfile: Dockerfile
extra-build-args: "--target phraseanet-fpm"
region: AWS_DEFAULT_REGION
repo: "phraseanet-fpm"
tag: "${CIRCLE_BRANCH}"
- aws-ecr/build_and_push_image:
account-url: AWS_ACCOUNT_URL
aws-access-key-id: AWS_ACCESS_KEY_ID
aws-secret-access-key: AWS_SECRET_ACCESS_KEY
context: "AWS London" context: "AWS London"
create-repo: true - build_phraseanet-nginx:
dockerfile: Dockerfile
extra-build-args: "--target phraseanet-nginx"
region: AWS_DEFAULT_REGION
repo: "phraseanet-nginx"
tag: "${CIRCLE_BRANCH}"
- aws-ecr/build_and_push_image:
account-url: AWS_ACCOUNT_URL
aws-access-key-id: AWS_ACCESS_KEY_ID
aws-secret-access-key: AWS_SECRET_ACCESS_KEY
context: "AWS London" context: "AWS London"
create-repo: true
dockerfile: Dockerfile
extra-build-args: "--target phraseanet-worker"
region: AWS_DEFAULT_REGION
repo: "phraseanet-worker"
tag: "${CIRCLE_BRANCH}"

12
.dockerignore Normal file
View File

@@ -0,0 +1,12 @@
.circleci
.git
.settings
nodes_modules
vendor

View File

@@ -1,5 +1,10 @@
FROM php:7.0-fpm-stretch as builder
#########################################################################
# This image contains every build tools that will be used by the builder and
# the app images (usefull in dev mode)
#########################################################################
FROM php:7.0-fpm-stretch as phraseanet-system
RUN apt-get update \ RUN apt-get update \
&& apt-get install -y \ && apt-get install -y \
apt-transport-https \ apt-transport-https \
@@ -23,6 +28,7 @@ RUN apt-get update \
libxslt-dev \ libxslt-dev \
libzmq3-dev \ libzmq3-dev \
locales \ locales \
gettext \
mcrypt \ mcrypt \
swftools \ swftools \
unoconv \ unoconv \
@@ -61,9 +67,19 @@ RUN mkdir /entrypoint /var/alchemy \
&& mkdir -p /home/app/.composer \ && mkdir -p /home/app/.composer \
&& chown -R app: /home/app /var/alchemy && chown -R app: /home/app /var/alchemy
#########################################################################
# This image is used to build the apps
#########################################################################
FROM phraseanet-system as builder
WORKDIR /var/alchemy/ WORKDIR /var/alchemy/
# Files that are needed at build stage
COPY gulpfile.js /var/alchemy/ 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 Makefile /var/alchemy/
COPY package.json /var/alchemy/ COPY package.json /var/alchemy/
COPY phpunit.xml.dist /var/alchemy/ COPY phpunit.xml.dist /var/alchemy/
@@ -73,11 +89,16 @@ COPY composer.json /var/alchemy/
COPY composer.lock /var/alchemy/ COPY composer.lock /var/alchemy/
RUN make install_composer RUN make install_composer
COPY resources /var/alchemy/resources COPY resources /var/alchemy/resources
COPY www /var/alchemy/www
# Application build phase
RUN make clean_assets RUN make clean_assets
RUN make install_asset_dependencies RUN make install_asset_dependencies
RUN make install_assets RUN make install_assets
# Application code
COPY www /var/alchemy/www
ADD ./docker/phraseanet/ / ADD ./docker/phraseanet/ /
COPY lib /var/alchemy/lib COPY lib /var/alchemy/lib
COPY tmp /var/alchemy/tmp COPY tmp /var/alchemy/tmp
@@ -86,6 +107,9 @@ COPY grammar /var/alchemy/grammar
COPY templates-profiler /var/alchemy/templates-profiler COPY templates-profiler /var/alchemy/templates-profiler
COPY templates /var/alchemy/templates COPY templates /var/alchemy/templates
COPY tests /var/alchemy/tests COPY tests /var/alchemy/tests
# Create needed folders
RUN mkdir -p /var/alchemy/Phraseanet/logs \ RUN mkdir -p /var/alchemy/Phraseanet/logs \
&& chmod -R 777 /var/alchemy/Phraseanet/logs \ && chmod -R 777 /var/alchemy/Phraseanet/logs \
&& mkdir -p /var/alchemy/Phraseanet/cache \ && mkdir -p /var/alchemy/Phraseanet/cache \
@@ -99,69 +123,11 @@ RUN mkdir -p /var/alchemy/Phraseanet/logs \
&& mkdir -p /var/alchemy/Phraseanet/config \ && mkdir -p /var/alchemy/Phraseanet/config \
&& chmod -R 777 /var/alchemy/Phraseanet/config && chmod -R 777 /var/alchemy/Phraseanet/config
# Phraseanet #########################################################################
FROM php:7.0-fpm-stretch as phraseanet-fpm # Phraseanet web application image
RUN apt-get update \ #########################################################################
&& apt-get install -y \
apt-transport-https \
ca-certificates \
gnupg2 \
&& apt-get update \
&& apt-get install -y --no-install-recommends zlib1g-dev \
gettext \
git \
ghostscript \
gpac \
imagemagick \
libav-tools \
libfreetype6-dev \
libicu-dev \
libjpeg62-turbo-dev \
libmagickwand-dev \
libmcrypt-dev \
libpng-dev \
librabbitmq-dev \
libssl-dev \
libxslt-dev \
libzmq3-dev \
locales \
mcrypt \
swftools \
unoconv \
unzip \
xpdf \
&& update-locale "LANG=fr_FR.UTF-8 UTF-8" \
&& dpkg-reconfigure --frontend noninteractive locales \
&& 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 \
&& docker-php-ext-enable redis amqp zmq imagick \
&& pecl clear-cache \
&& docker-php-source delete \
&& rm -rf /var/lib/apt/lists/*
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \ FROM phraseanet-system as phraseanet-fpm
&& php -r "if (hash_file('sha384', 'composer-setup.php') === 'a5c698ffe4b8e849a443b120cd5ba38043260d5c4023dbf93e1558871f1f07f58274fc6f4c93bcfd858c6bd0775cd8d1') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" \
&& php composer-setup.php --install-dir=/usr/local/bin --filename=composer \
&& php -r "unlink('composer-setup.php');"
# Node Installation (node + yarn)
# Reference :
# 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 clean \
&& rm -rf /var/lib/apt/lists/
RUN mkdir /entrypoint /var/alchemy \
&& useradd -u 1000 app \
&& mkdir -p /home/app/.composer \
&& chown -R app: /home/app /var/alchemy
COPY --from=builder --chown=app /var/alchemy /var/alchemy/Phraseanet COPY --from=builder --chown=app /var/alchemy /var/alchemy/Phraseanet
ADD ./docker/phraseanet/ / ADD ./docker/phraseanet/ /
@@ -169,11 +135,17 @@ WORKDIR /var/alchemy/Phraseanet
ENTRYPOINT ["/phraseanet-entrypoint.sh"] ENTRYPOINT ["/phraseanet-entrypoint.sh"]
CMD ["/boot.sh"] CMD ["/boot.sh"]
# phraseanet-worker #########################################################################
# Phraseanet worker application image
#########################################################################
FROM phraseanet-fpm as phraseanet-worker FROM phraseanet-fpm as phraseanet-worker
CMD ["/worker-boot.sh"] CMD ["/worker-boot.sh"]
#########################################################################
# phraseanet-nginx # phraseanet-nginx
#########################################################################
FROM nginx:1.15 as phraseanet-nginx FROM nginx:1.15 as phraseanet-nginx
RUN useradd -u 1000 app RUN useradd -u 1000 app
ADD ./docker/nginx/ / ADD ./docker/nginx/ /

View File

@@ -1,18 +0,0 @@
ARG phraseanet
FROM $phraseanet
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
iproute2 \
&& rm -rf /var/lib/apt/lists/* \
&& pecl install xdebug \
&& docker-php-ext-enable xdebug \
&& pecl clear-cache
ADD ./docker/phraseanet-debug/ /
RUN chmod +x /entrypoint.sh /usr/local/bin/docker-*
ENTRYPOINT ["/entrypoint.sh"]
CMD ["php-fpm"]

View File

@@ -1,5 +1,7 @@
#!/bin/bash #!/bin/bash
set -xe
# nginx server # nginx server
docker build --target phraseanet-nginx -t local/phraseanet-nginx:$1 . docker build --target phraseanet-nginx -t local/phraseanet-nginx:$1 .

View File

@@ -354,7 +354,7 @@ class SubdefsController extends Controller
Subdef::TYPE_VIDEO => [ Subdef::TYPE_VIDEO => [
"definitions" => [ "definitions" => [
"video codec H264" => null, "video codec H264" => null,
"144P H264 128 kbps ACC 128kbps" => [ "144P H264 128 kbps MP3 128kbps" => [
Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOBITRATE => "128",
Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_AUDIOSAMPLERATE => "44100",
Video::OPTION_BITRATE => "128", Video::OPTION_BITRATE => "128",
@@ -362,10 +362,10 @@ class SubdefsController extends Controller
Video::OPTION_SIZE => "256", Video::OPTION_SIZE => "256",
Video::OPTION_FRAMERATE => "25", Video::OPTION_FRAMERATE => "25",
Video::OPTION_VCODEC => "libx264", Video::OPTION_VCODEC => "libx264",
Video::OPTION_ACODEC => "libfaac", Video::OPTION_ACODEC => "libmp3lame",
Subdef::OPTION_DEVICE => ["all"] Subdef::OPTION_DEVICE => ["all"]
], ],
"240P H264 256 kbps ACC 128kbps" => [ "240P H264 256 kbps MP3 128kbps" => [
Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOBITRATE => "128",
Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_AUDIOSAMPLERATE => "44100",
Video::OPTION_BITRATE => "256", Video::OPTION_BITRATE => "256",
@@ -373,10 +373,10 @@ class SubdefsController extends Controller
Video::OPTION_SIZE => "426", Video::OPTION_SIZE => "426",
Video::OPTION_FRAMERATE => "25", Video::OPTION_FRAMERATE => "25",
Video::OPTION_VCODEC => "libx264", Video::OPTION_VCODEC => "libx264",
Video::OPTION_ACODEC => "libfaac", Video::OPTION_ACODEC => "libmp3lame",
Subdef::OPTION_DEVICE => ["all"] Subdef::OPTION_DEVICE => ["all"]
], ],
"360P H264 576 kbps ACC 128kbps" => [ "360P H264 576 kbps MP3 128kbps" => [
Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOBITRATE => "128",
Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_AUDIOSAMPLERATE => "44100",
Video::OPTION_BITRATE => "576", Video::OPTION_BITRATE => "576",
@@ -384,10 +384,10 @@ class SubdefsController extends Controller
Video::OPTION_SIZE => "480", Video::OPTION_SIZE => "480",
Video::OPTION_FRAMERATE => "25", Video::OPTION_FRAMERATE => "25",
Video::OPTION_VCODEC => "libtheora", Video::OPTION_VCODEC => "libtheora",
Video::OPTION_ACODEC => "libfaac", Video::OPTION_ACODEC => "libmp3lame",
Subdef::OPTION_DEVICE => ["all"] Subdef::OPTION_DEVICE => ["all"]
], ],
"480P H264 750 kbps ACC 128kbps" => [ "480P H264 750 kbps MP3 128kbps" => [
Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOBITRATE => "128",
Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_AUDIOSAMPLERATE => "44100",
Video::OPTION_BITRATE => "750", Video::OPTION_BITRATE => "750",
@@ -395,10 +395,10 @@ class SubdefsController extends Controller
Video::OPTION_SIZE => "854", Video::OPTION_SIZE => "854",
Video::OPTION_FRAMERATE => "25", Video::OPTION_FRAMERATE => "25",
Video::OPTION_VCODEC => "libx264", Video::OPTION_VCODEC => "libx264",
Video::OPTION_ACODEC => "libfaac", Video::OPTION_ACODEC => "libmp3lame",
Subdef::OPTION_DEVICE => ["all"] Subdef::OPTION_DEVICE => ["all"]
], ],
"720P H264 1492 kbps ACC 128kbps" => [ "720P H264 1492 kbps MP3 128kbps" => [
Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOBITRATE => "128",
Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_AUDIOSAMPLERATE => "44100",
Video::OPTION_BITRATE => "1492", Video::OPTION_BITRATE => "1492",
@@ -406,10 +406,10 @@ class SubdefsController extends Controller
Video::OPTION_SIZE => "1280", Video::OPTION_SIZE => "1280",
Video::OPTION_FRAMERATE => "25", Video::OPTION_FRAMERATE => "25",
Video::OPTION_VCODEC => "libx264", Video::OPTION_VCODEC => "libx264",
Video::OPTION_ACODEC => "libfaac", Video::OPTION_ACODEC => "libmp3lame",
Subdef::OPTION_DEVICE => ["all"] Subdef::OPTION_DEVICE => ["all"]
], ],
"1080P H264 2420 kbps ACC 128kbps" => [ "1080P H264 2420 kbps MP3 128kbps" => [
Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOBITRATE => "128",
Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_AUDIOSAMPLERATE => "44100",
Video::OPTION_BITRATE => "2420", Video::OPTION_BITRATE => "2420",
@@ -417,11 +417,77 @@ class SubdefsController extends Controller
Video::OPTION_SIZE => "1920", Video::OPTION_SIZE => "1920",
Video::OPTION_FRAMERATE => "25", Video::OPTION_FRAMERATE => "25",
Video::OPTION_VCODEC => "libx264", Video::OPTION_VCODEC => "libx264",
Video::OPTION_ACODEC => "libfaac", Video::OPTION_ACODEC => "libmp3lame",
Subdef::OPTION_DEVICE => ["all"]
],
"144P H264 128 kbps AAC 128kbps" => [
Video::OPTION_AUDIOBITRATE => "128",
Video::OPTION_AUDIOSAMPLERATE => "44100",
Video::OPTION_BITRATE => "128",
Video::OPTION_GOPSIZE => "25",
Video::OPTION_SIZE => "256",
Video::OPTION_FRAMERATE => "25",
Video::OPTION_VCODEC => "libx264",
Video::OPTION_ACODEC => "libfdk_aac",
Subdef::OPTION_DEVICE => ["all"]
],
"240P H264 256 kbps AAC 128kbps" => [
Video::OPTION_AUDIOBITRATE => "128",
Video::OPTION_AUDIOSAMPLERATE => "44100",
Video::OPTION_BITRATE => "256",
Video::OPTION_GOPSIZE => "25",
Video::OPTION_SIZE => "426",
Video::OPTION_FRAMERATE => "25",
Video::OPTION_VCODEC => "libx264",
Video::OPTION_ACODEC => "libfdk_aac",
Subdef::OPTION_DEVICE => ["all"]
],
"360P H264 576 kbps AAC 128kbps" => [
Video::OPTION_AUDIOBITRATE => "128",
Video::OPTION_AUDIOSAMPLERATE => "44100",
Video::OPTION_BITRATE => "576",
Video::OPTION_GOPSIZE => "25",
Video::OPTION_SIZE => "480",
Video::OPTION_FRAMERATE => "25",
Video::OPTION_VCODEC => "libtheora",
Video::OPTION_ACODEC => "libfdk_aac",
Subdef::OPTION_DEVICE => ["all"]
],
"480P H264 750 kbps AAC 128kbps" => [
Video::OPTION_AUDIOBITRATE => "128",
Video::OPTION_AUDIOSAMPLERATE => "44100",
Video::OPTION_BITRATE => "750",
Video::OPTION_GOPSIZE => "25",
Video::OPTION_SIZE => "854",
Video::OPTION_FRAMERATE => "25",
Video::OPTION_VCODEC => "libx264",
Video::OPTION_ACODEC => "libfdk_aac",
Subdef::OPTION_DEVICE => ["all"]
],
"720P H264 1492 kbps AAC 128kbps" => [
Video::OPTION_AUDIOBITRATE => "128",
Video::OPTION_AUDIOSAMPLERATE => "44100",
Video::OPTION_BITRATE => "1492",
Video::OPTION_GOPSIZE => "25",
Video::OPTION_SIZE => "1280",
Video::OPTION_FRAMERATE => "25",
Video::OPTION_VCODEC => "libx264",
Video::OPTION_ACODEC => "libfdk_aac",
Subdef::OPTION_DEVICE => ["all"]
],
"1080P H264 2420 kbps AAC 128kbps" => [
Video::OPTION_AUDIOBITRATE => "128",
Video::OPTION_AUDIOSAMPLERATE => "44100",
Video::OPTION_BITRATE => "2420",
Video::OPTION_GOPSIZE => "25",
Video::OPTION_SIZE => "1920",
Video::OPTION_FRAMERATE => "25",
Video::OPTION_VCODEC => "libx264",
Video::OPTION_ACODEC => "libfdk_aac",
Subdef::OPTION_DEVICE => ["all"] Subdef::OPTION_DEVICE => ["all"]
], ],
"video codec libvpx" => null, "video codec libvpx" => null,
"144P webm 128 kbps ACC 128kbps" => [ "144P webm 128 kbps MP3 128kbps" => [
Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOBITRATE => "128",
Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_AUDIOSAMPLERATE => "44100",
Video::OPTION_BITRATE => "128", Video::OPTION_BITRATE => "128",
@@ -429,10 +495,10 @@ class SubdefsController extends Controller
Video::OPTION_SIZE => "256", Video::OPTION_SIZE => "256",
Video::OPTION_FRAMERATE => "25", Video::OPTION_FRAMERATE => "25",
Video::OPTION_VCODEC => "libvpx", Video::OPTION_VCODEC => "libvpx",
Video::OPTION_ACODEC => "libfaac", Video::OPTION_ACODEC => "libmp3lame",
Subdef::OPTION_DEVICE => ["all"] Subdef::OPTION_DEVICE => ["all"]
], ],
"240P webm 256 kbps ACC 128kbps" => [ "240P webm 256 kbps MP3 128kbps" => [
Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOBITRATE => "128",
Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_AUDIOSAMPLERATE => "44100",
Video::OPTION_BITRATE => "256", Video::OPTION_BITRATE => "256",
@@ -440,10 +506,10 @@ class SubdefsController extends Controller
Video::OPTION_SIZE => "426", Video::OPTION_SIZE => "426",
Video::OPTION_FRAMERATE => "25", Video::OPTION_FRAMERATE => "25",
Video::OPTION_VCODEC => "libvpx", Video::OPTION_VCODEC => "libvpx",
Video::OPTION_ACODEC => "libfaac", Video::OPTION_ACODEC => "libmp3lame",
Subdef::OPTION_DEVICE => ["all"] Subdef::OPTION_DEVICE => ["all"]
], ],
"360P webm 576 kbps ACC 128kbps" => [ "360P webm 576 kbps MP3 128kbps" => [
Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOBITRATE => "128",
Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_AUDIOSAMPLERATE => "44100",
Video::OPTION_BITRATE => "576", Video::OPTION_BITRATE => "576",
@@ -451,10 +517,10 @@ class SubdefsController extends Controller
Video::OPTION_SIZE => "480", Video::OPTION_SIZE => "480",
Video::OPTION_FRAMERATE => "25", Video::OPTION_FRAMERATE => "25",
Video::OPTION_VCODEC => "libvpx", Video::OPTION_VCODEC => "libvpx",
Video::OPTION_ACODEC => "libfaac", Video::OPTION_ACODEC => "libmp3lame",
Subdef::OPTION_DEVICE => ["all"] Subdef::OPTION_DEVICE => ["all"]
], ],
"480P webm 750 kbps ACC 128kbps" => [ "480P webm 750 kbps MP3 128kbps" => [
Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOBITRATE => "128",
Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_AUDIOSAMPLERATE => "44100",
Video::OPTION_BITRATE => "750", Video::OPTION_BITRATE => "750",
@@ -462,10 +528,10 @@ class SubdefsController extends Controller
Video::OPTION_SIZE => "854", Video::OPTION_SIZE => "854",
Video::OPTION_FRAMERATE => "25", Video::OPTION_FRAMERATE => "25",
Video::OPTION_VCODEC => "libvpx", Video::OPTION_VCODEC => "libvpx",
Video::OPTION_ACODEC => "libfaac", Video::OPTION_ACODEC => "libmp3lame",
Subdef::OPTION_DEVICE => ["all"] Subdef::OPTION_DEVICE => ["all"]
], ],
"720P webm 1492 kbps ACC 128kbps" => [ "720P webm 1492 kbps MP3 128kbps" => [
Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOBITRATE => "128",
Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_AUDIOSAMPLERATE => "44100",
Video::OPTION_BITRATE => "1492", Video::OPTION_BITRATE => "1492",
@@ -473,10 +539,10 @@ class SubdefsController extends Controller
Video::OPTION_SIZE => "1280", Video::OPTION_SIZE => "1280",
Video::OPTION_FRAMERATE => "25", Video::OPTION_FRAMERATE => "25",
Video::OPTION_VCODEC => "libvpx", Video::OPTION_VCODEC => "libvpx",
Video::OPTION_ACODEC => "libfaac", Video::OPTION_ACODEC => "libmp3lame",
Subdef::OPTION_DEVICE => ["all"] Subdef::OPTION_DEVICE => ["all"]
], ],
"1080P webm 2420 kbps ACC 128kbps" => [ "1080P webm 2420 kbps MP3 128kbps" => [
Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOBITRATE => "128",
Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_AUDIOSAMPLERATE => "44100",
Video::OPTION_BITRATE => "2420", Video::OPTION_BITRATE => "2420",
@@ -484,7 +550,73 @@ class SubdefsController extends Controller
Video::OPTION_SIZE => "1920", Video::OPTION_SIZE => "1920",
Video::OPTION_FRAMERATE => "25", Video::OPTION_FRAMERATE => "25",
Video::OPTION_VCODEC => "libvpx", Video::OPTION_VCODEC => "libvpx",
Video::OPTION_ACODEC => "libfaac", Video::OPTION_ACODEC => "libmp3lame",
Subdef::OPTION_DEVICE => ["all"]
],
"144P webm 128 kbps AAC 128kbps" => [
Video::OPTION_AUDIOBITRATE => "128",
Video::OPTION_AUDIOSAMPLERATE => "44100",
Video::OPTION_BITRATE => "128",
Video::OPTION_GOPSIZE => "25",
Video::OPTION_SIZE => "256",
Video::OPTION_FRAMERATE => "25",
Video::OPTION_VCODEC => "libvpx",
Video::OPTION_ACODEC => "libfdk_aac",
Subdef::OPTION_DEVICE => ["all"]
],
"240P webm 256 kbps AAC 128kbps" => [
Video::OPTION_AUDIOBITRATE => "128",
Video::OPTION_AUDIOSAMPLERATE => "44100",
Video::OPTION_BITRATE => "256",
Video::OPTION_GOPSIZE => "25",
Video::OPTION_SIZE => "426",
Video::OPTION_FRAMERATE => "25",
Video::OPTION_VCODEC => "libvpx",
Video::OPTION_ACODEC => "libfdk_aac",
Subdef::OPTION_DEVICE => ["all"]
],
"360P webm 576 kbps AAC 128kbps" => [
Video::OPTION_AUDIOBITRATE => "128",
Video::OPTION_AUDIOSAMPLERATE => "44100",
Video::OPTION_BITRATE => "576",
Video::OPTION_GOPSIZE => "25",
Video::OPTION_SIZE => "480",
Video::OPTION_FRAMERATE => "25",
Video::OPTION_VCODEC => "libvpx",
Video::OPTION_ACODEC => "libfdk_aac",
Subdef::OPTION_DEVICE => ["all"]
],
"480P webm 750 kbps AAC 128kbps" => [
Video::OPTION_AUDIOBITRATE => "128",
Video::OPTION_AUDIOSAMPLERATE => "44100",
Video::OPTION_BITRATE => "750",
Video::OPTION_GOPSIZE => "25",
Video::OPTION_SIZE => "854",
Video::OPTION_FRAMERATE => "25",
Video::OPTION_VCODEC => "libvpx",
Video::OPTION_ACODEC => "libfdk_aac",
Subdef::OPTION_DEVICE => ["all"]
],
"720P webm 1492 kbps AAC 128kbps" => [
Video::OPTION_AUDIOBITRATE => "128",
Video::OPTION_AUDIOSAMPLERATE => "44100",
Video::OPTION_BITRATE => "1492",
Video::OPTION_GOPSIZE => "25",
Video::OPTION_SIZE => "1280",
Video::OPTION_FRAMERATE => "25",
Video::OPTION_VCODEC => "libvpx",
Video::OPTION_ACODEC => "libfdk_aac",
Subdef::OPTION_DEVICE => ["all"]
],
"1080P webm 2420 kbps AAC 128kbps" => [
Video::OPTION_AUDIOBITRATE => "128",
Video::OPTION_AUDIOSAMPLERATE => "44100",
Video::OPTION_BITRATE => "2420",
Video::OPTION_GOPSIZE => "25",
Video::OPTION_SIZE => "1920",
Video::OPTION_FRAMERATE => "25",
Video::OPTION_VCODEC => "libvpx",
Video::OPTION_ACODEC => "libfdk_aac",
Subdef::OPTION_DEVICE => ["all"] Subdef::OPTION_DEVICE => ["all"]
], ],
], ],

View File

@@ -193,7 +193,7 @@ class PushController extends Controller
'Validation from %user%', [ 'Validation from %user%', [
'%user%' => $this->getAuthenticatedUser()->getDisplayName(), '%user%' => $this->getAuthenticatedUser()->getDisplayName(),
])); ]));
$validation_description = $request->request->get('validation_description'); $validation_description = $request->request->get('message');
$participants = $request->request->get('participants'); $participants = $request->request->get('participants');

View File

@@ -16,7 +16,7 @@ class Version
/** /**
* @var string * @var string
*/ */
private $number = '4.1.0-alpha.18a'; private $number = '4.1.0-alpha.19a';
/** /**
* @var string * @var string

View File

@@ -140,6 +140,7 @@ class LegacyRecordRepository implements RecordRepository
's.rid_parent IN (:storyIds)', 's.rid_parent IN (:storyIds)',
'r.parent_record_id = 0' 'r.parent_record_id = 0'
) )
->orderBy('s.ord', 'ASC')
->setParameter('storyIds', $storyIds, Connection::PARAM_INT_ARRAY) ->setParameter('storyIds', $storyIds, Connection::PARAM_INT_ARRAY)
; ;

View File

@@ -33,7 +33,7 @@ class Video extends Audio
$this->registerOption(new OptionType\Range($this->translator->trans('Frame Rate'), self::OPTION_FRAMERATE, 1, 200, 20)); $this->registerOption(new OptionType\Range($this->translator->trans('Frame Rate'), self::OPTION_FRAMERATE, 1, 200, 20));
$this->registerOption(new OptionType\Enum($this->translator->trans('Video Codec'), self::OPTION_VCODEC, ['libx264', 'libvpx', 'libtheora'], 'libx264')); $this->registerOption(new OptionType\Enum($this->translator->trans('Video Codec'), self::OPTION_VCODEC, ['libx264', 'libvpx', 'libtheora'], 'libx264'));
$this->unregisterOption(self::OPTION_ACODEC); $this->unregisterOption(self::OPTION_ACODEC);
$this->registerOption(new OptionType\Enum($this->translator->trans('Audio Codec'), self::OPTION_ACODEC, ['libfaac', 'libvo_aacenc', 'libmp3lame', 'libvorbis'], 'libfaac')); $this->registerOption(new OptionType\Enum($this->translator->trans('Audio Codec'), self::OPTION_ACODEC, ['libfaac', 'libvo_aacenc', 'libmp3lame', 'libvorbis', 'libfdk_aac'], 'libmp3lame'));
} }
public function getType() public function getType()

View File

@@ -0,0 +1,69 @@
<?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;
class patch_410alpha19a implements patchInterface
{
/** @var string */
private $release = '4.1.0-alpha.19a';
/** @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)
{
// remove all and last in default query
$sql = "UPDATE UserSettings SET value = '' WHERE name = 'start_page_query' AND lower(trim(value)) in ('all','last')";
$stmt = $appbox->get_connection()->prepare($sql);
$stmt->execute();
$stmt->closeCursor();
return true;
}
}

View File

@@ -65,7 +65,7 @@
"normalize-css": "^2.1.0", "normalize-css": "^2.1.0",
"npm": "^6.0.0", "npm": "^6.0.0",
"npm-modernizr": "^2.8.3", "npm-modernizr": "^2.8.3",
"phraseanet-production-client": "0.34.80-d", "phraseanet-production-client": "^0.34.86-d",
"requirejs": "^2.3.5", "requirejs": "^2.3.5",
"tinymce": "^4.0.28", "tinymce": "^4.0.28",
"underscore": "^1.8.3", "underscore": "^1.8.3",

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -1,13 +1,3 @@
@font-face {
font-family: 'icomoon';
src: url('fonts/icomoon.eot?81kpnc');
src: url('fonts/icomoon.eot?81kpnc#iefix') format('embedded-opentype'),
url('fonts/icomoon.ttf?81kpnc') format('truetype'),
url('fonts/icomoon.woff?81kpnc') format('woff'),
url('fonts/icomoon.svg?81kpnc#icomoon') format('svg');
font-weight: normal;
font-style: normal;
}
[class^="icon-"], [class*=" icon-"] { [class^="icon-"], [class*=" icon-"] {
/* use !important to prevent issues with browser extensions that change fonts */ /* use !important to prevent issues with browser extensions that change fonts */

View File

@@ -1,30 +1,34 @@
$iconsPath: '../../../assets/common/images/icons/'; $iconsPath: '../../../assets/common/images/icons/';
$feedbackColor : #8bc34a;
ul.image_set{ $basketColor : #2196f3 ;
padding:0; ul.image_set {
margin:0; padding: 0;
border:none; margin: 0;
width:100%; border: none;
border:none; width: 100%;
border: none;
list-style-type: none; list-style-type: none;
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
} }
li.image_box a img{
position:relative; li.image_box a img {
border:none; position: relative;
width: auto!important; border: none;
height: 100% !important; width: auto !important;
height: 100% !important;
top: 0 !important; top: 0 !important;
object-fit: contain; object-fit: contain;
} }
li.image_box a{
padding:0; li.image_box a {
text-shadow:0; padding: 0;
margin:0; text-shadow: 0;
margin: 0;
width: 100%; width: 100%;
} }
li.image_box{
li.image_box {
width: 18%; width: 18%;
position: relative; position: relative;
margin: 0 2.5% 15px 0; margin: 0 2.5% 15px 0;
@@ -38,19 +42,20 @@ li.image_box{
} }
.thumb_wrapper { .thumb_wrapper {
background: #ededed; background: #ededed;
width: 100%!important; width: 100% !important;
height: 160px!important; height: 160px !important;
@media screen and (max-width: 767px) { @media screen and (max-width: 767px) {
height: 130px !important; height: 130px !important;
} }
} }
} }
@media screen and (max-width: 767px) { @media screen and (max-width: 767px) {
li.image_box{ li.image_box {
width: 32%; width: 32%;
margin: 0 2% 15px 0; margin: 0 2% 15px 0;
&:nth-child(5n) { &:nth-child(5n) {
margin-right: 2% ; margin-right: 2%;
} }
&:nth-child(3n) { &:nth-child(3n) {
margin-right: 0; margin-right: 0;
@@ -58,35 +63,37 @@ li.image_box{
} }
} }
a.no.active_choice{ a.no.active_choice {
background-color:red; background-color: red;
color: #fff; color: #fff;
} }
a.active_choice{
a.active_choice {
background-color: #53b401; background-color: #53b401;
color: #fff; color: #fff;
} }
.valid_choice{ .valid_choice {
position:absolute; position: absolute;
bottom:0; bottom: 0;
right:0; right: 0;
width:16px; width: 16px;
height:16px; height: 16px;
z-index:2; z-index: 2;
} }
.valid_choice.agree{ .valid_choice.agree {
background: #7ed321; background: #7ed321;
border-top-left-radius: 100px; border-top-left-radius: 100px;
} }
.valid_choice.disagree{
.valid_choice.disagree {
background: #d0021b; background: #d0021b;
border-top-left-radius: 100px; border-top-left-radius: 100px;
} }
.thumb_wrapper { .thumb_wrapper {
text-align:center; text-align: center;
} }
@media screen and (orientation: landscape) { @media screen and (orientation: landscape) {
@@ -108,3 +115,207 @@ a.active_choice{
.ui-footer .ui-title, .ui-header .ui-title { .ui-footer .ui-title, .ui-header .ui-title {
font-size: 18px; font-size: 18px;
} }
.ui-listview .ui-li-has-thumb .ui-li-thumb, .ui-listview .ui-li-has-thumb > .ui-btn > img:first-child, .ui-listview .ui-li-has-thumb > img:first-child {
top: 50%;
transform: translateY(-50%);
}
/*user status*/
.menu-bar-item {
background: #f0f0f0;
padding: 12px 15px;
text-align: left;
position: relative;
.icomoon {
font-size: 17px;
position: absolute;
left: 23px;
top: 50%;
transform: translateY(-50%);
}
.ui-link {
color: #4f4f4f !important;
text-decoration: none !important;
.text {
padding-left: 31px;
color: #4f4f4f !important;
text-decoration: none !important;
font-weight: 700;
font-size: 13px;
}
}
}
/*new design of lightbox*/
/*main nav */
#lightbox-menu {
li {
margin-bottom: 30px;
.ui-li-count {
border-radius: 3px !important;
border-top-left-radius: 0 !important;
border-bottom-left-radius: 0 !important;
border: 0;
color: #fff;
text-shadow: none;
padding: 18px 23px;
top: 0;
right: 0;
margin: 0;
font-size: 22px;
min-width: 25px;
background: $feedbackColor;
}
&.ui-first-child {
margin-top: 15px;
}
&.ui-last-child {
a {
&:before {
background: $basketColor;
}
&:hover, &:active, &:focus {
color: $basketColor;
}
}
.ui-li-count {
background: $basketColor;
}
}
}
a {
padding: 22px 25px;
font-size: 20px;
border-radius: 3px !important;
box-shadow: 0 0 6px 0 rgba(0, 0, 0, 0.19);
background-color: #eeeeee;
&:hover, &:active, &:focus {
color: $feedbackColor;
}
&:after {
content: none !important;
}
&:before {
content: "";
position: absolute;
display: block;
width: 100%;
height: 4px;
bottom: 0;
background: $feedbackColor;
left: 0;
border-radius: 3px;
}
}
}
.lightbox-bottom-btn {
margin-top: 50px;
.ui-btn {
font-size: 15px;
}
}
#validation, #baskets {
.ui-content {
padding-left: 0;
padding-right: 0;
}
}
.basket-title {
background: $feedbackColor;
padding: 12px 30px;
font-size: 17px;
margin: 0;
text-shadow: none;
color: #fff;
font-weight: 700;
#baskets & {
background: $basketColor;
}
span {
float: right;
}
}
.feed-list {
li {
height: 71px;
padding-left: 109px!important;
padding-right: 80px!important;
border-color: #d4d4d4!important;
text-overflow: inherit!important;
white-space: inherit!important;
}
.lightbox-img {
width: 90px;
height: 90px;
background-color: #ededed;
position: absolute;
left: 0;
top: 0;
display: flex;
flex-wrap: wrap;
img {
display: flex;
align-items: center;
width: 90px;
max-width: 100%;
max-height: 100%;
object-fit: contain;
}
}
h3 {
display: flex!important;
align-items: center;
height: 71px;
margin: 0!important;
font-size: 15px;
font-weight: bold!important;
text-overflow: inherit!important;
white-space: inherit!important;
a {
position: relative;
color: #313131!important;
width: 100%;
padding-right: 18px;
&:after {
content: "\e96c";
font-family: icomoon;
position: absolute;
right: 0;
font-size: 20px;
line-height: 1;
top: 50%;
transform: translateY(-50%);
}
}
}
span {
font-size: 17px;
color: #fff!important;
display: inline-block;
text-shadow: none!important;
top: 0;
width: 52px;
right: 0;
line-height: 25px;
padding: 31px 0px;
margin: 0;
border-radius: 0;
&.validation {
background: $feedbackColor!important;
}
&.baskets {
background: $basketColor!important;
}
}
}
.lightbox-msg {
font-size: 14px;
color: #313131;
padding: 6px 0 6px 30px;
}

View File

@@ -0,0 +1,17 @@
{% set configuration = app['conf'].get(['registry', 'custom-links']) %}
{% if app.getAuthenticator().isAuthenticated() %}
<div class="menu-bar-item">
{% if app.getAuthenticatedUser().isGuest %}
<span class="icomoon icon-agree">&#xe950;</span>
<span class="text">{{ 'Guest' | trans }}</span>
{% else %}
<a target="_blank" href="{{ path('account') }}"
title="{{ 'login:: Mon compte' | trans }}">
<span class="icomoon icon-agree">&#xe950;</span>
<span class="text">{{ app.getAuthenticatedUser().getDisplayName() }}</span>
</a>
{% endif %}
</div>
{% endif %}

View File

@@ -26,7 +26,7 @@
#content { #content {
position: fixed; position: fixed;
top:50px; top:90px;
bottom: 0; bottom: 0;
right: 0; right: 0;
left: 0; left: 0;
@@ -40,17 +40,19 @@
{% block content %} {% block content %}
{% set record = basket_element.getRecord(app) %} {% set record = basket_element.getRecord(app) %}
<div data-role="page" id="page"> <div data-role="page" id="page">
<div data-role="header"> <div data-role="header">
<a href="{{ path('lightbox_validation', { 'basket' : basket_element.getBasket().getId() }) }}" <a href="{{ path('lightbox_validation', { 'basket' : basket_element.getBasket().getId() }) }}"
data-icon="arrow-l">{{ 'Back' | trans }}</a> data-icon="arrow-l">{{ 'Back' | trans }}</a>
<h1>{{basket_element.getOrd()}} - {{record.get_title()}}</h1> <h1>{{basket_element.getOrd()}} - {{record.get_title()}}</h1>
<a rel="external" href="{{ path('lightbox') }}" data-icon="home" data-iconpos="notext" data-direction="reverse" <a rel="external" href="{{ path('lightbox') }}" data-icon="home" data-iconpos="notext" data-direction="reverse"
class="ui-btn-right jqm-home">{{ 'Home' | trans }}</a> class="ui-btn-right jqm-home">{{ 'Home' | trans }}</a>
</div> </div>
<div id="content" data-role="content"> <div class="lightbox-user-info">
<div class="nav_button"> {% include 'common/menubar.html.twig' %}
</div>
<div id="content" data-role="content">
<div class="nav_button">
{% if prevId != NULL %} {% if prevId != NULL %}
<a data-ajax="false" id="left-btn" <a data-ajax="false" id="left-btn"
href="{{ path('lightbox_ajax_load_basketelement', { 'sselcont_id' : prevId }) }}" href="{{ path('lightbox_ajax_load_basketelement', { 'sselcont_id' : prevId }) }}"
@@ -62,31 +64,31 @@
class="ui-btn ui-shadow ui-corner-all ui-icon-carat-r ui-btn-icon-notext">Right</a> class="ui-btn ui-shadow ui-corner-all ui-icon-carat-r ui-btn-icon-notext">Right</a>
{% endif %} {% endif %}
<div style="clear: both;"></div> <div style="clear: both;"></div>
</div> </div>
<div class="center-image">{{ thumbnail.format100percent(record.get_preview()) }}</div> <div class="center-image">{{ thumbnail.format100percent(record.get_preview()) }}</div>
{% if basket_element.getBasket().getValidation() %} {% if basket_element.getBasket().getValidation() %}
{% if basket_element.getBasket().getValidation().getParticipant(app.getAuthenticatedUser()).getCanAgree() %} {% if basket_element.getBasket().getValidation().getParticipant(app.getAuthenticatedUser()).getCanAgree() %}
<fieldset data-role="controlgroup" data-type="horizontal" style="text-align:center;"> <fieldset data-role="controlgroup" data-type="horizontal" style="text-align:center;">
<input onclick="window.location.reload();" {% if basket_element.getUserValidationDatas(app.getAuthenticatedUser()).getAgreement() == true%}checked="checked"{% endif %} type="radio" name="radio-view" id="radio-view-yes_{{basket_element.getId()}}" value="yes" /> <input {% if basket_element.getUserValidationDatas(app.getAuthenticatedUser()).getAgreement() == true%}checked="checked"{% endif %} type="radio" name="radio-view" id="radio-view-yes_{{basket_element.getId()}}" value="yes" />
<label class="agreement_radio" style="width:110px;text-align:center;" <label class="agreement_radio" style="width:110px;text-align:center;"
for="radio-view-yes_{{ basket_element.getId() }}">{{ 'validation:: OUI' | trans }}</label> for="radio-view-yes_{{ basket_element.getId() }}">{{ 'validation:: OUI' | trans }}</label>
<input onclick="window.location.reload();" {% if basket_element.getUserValidationDatas(app.getAuthenticatedUser()).getAgreement() == false and basket_element.getUserValidationDatas(app.getAuthenticatedUser()).getAgreement() is not null %}checked="checked"{% endif %} type="radio" name="radio-view" id="radio-view-no_{{basket_element.getId()}}" value="no" /> <input {% if basket_element.getUserValidationDatas(app.getAuthenticatedUser()).getAgreement() == false and basket_element.getUserValidationDatas(app.getAuthenticatedUser()).getAgreement() is not null %}checked="checked"{% endif %} type="radio" name="radio-view" id="radio-view-no_{{basket_element.getId()}}" value="no" />
<label class="agreement_radio" style="width:110px;text-align:center;" <label class="agreement_radio" style="width:110px;text-align:center;"
for="radio-view-no_{{ basket_element.getId() }}">{{ 'validation:: NON' | trans }}</label> for="radio-view-no_{{ basket_element.getId() }}">{{ 'validation:: NON' | trans }}</label>
</fieldset> </fieldset>
{% endif %} {% endif %}
<div style="text-align:center;margin:0 0 1em 0"> <div style="text-align:center;margin:0 0 1em 0">
<a href="{{ path('lightbox_ajax_note_form', { 'sselcont_id' : basket_element.getId() }) }}" data-role="button" data-inline="true" data-rel="dialog" data-transition="slidedown"> <a href="{{ path('lightbox_ajax_note_form', { 'sselcont_id' : basket_element.getId() }) }}" data-role="button" data-inline="true" data-rel="dialog" data-transition="slidedown">
{{ 'validation:: editer ma note' | trans }} {{ 'validation:: editer ma note' | trans }}
</a> </a>
</div> </div>
<div> <div>
<ul data-role="listview" class="lightbox-list-view" id="notes_{{basket_element.getId()}}"> <ul data-role="listview" class="lightbox-list-view" id="notes_{{basket_element.getId()}}">
{% include 'lightbox/sc_note.html.twig' %} {% include 'lightbox/sc_note.html.twig' %}
</ul> </ul>
</div> </div>
{% endif %} {% endif %}
</div> </div>
<div data-role="footer"> <div data-role="footer">
</div> </div>

View File

@@ -17,7 +17,7 @@
#content { #content {
position: fixed; position: fixed;
top:50px; top:90px;
bottom: 0; bottom: 0;
right: 0; right: 0;
left: 0; left: 0;
@@ -36,9 +36,12 @@
<h1>{{feed_element.getOrd()}} - {{record.get_title()}}</h1> <h1>{{feed_element.getOrd()}} - {{record.get_title()}}</h1>
<a rel="external" href="{{ path('lightbox') }}" data-icon="home" data-iconpos="notext" data-direction="reverse" class="ui-btn-right jqm-home">Home</a> <a rel="external" href="{{ path('lightbox') }}" data-icon="home" data-iconpos="notext" data-direction="reverse" class="ui-btn-right jqm-home">Home</a>
</div> </div>
<div class="lightbox-user-info">
{% include 'common/menubar.html.twig' %}
</div>
<div id="content" data-role="content"> <div id="content" data-role="content">
{{ thumbnail.format100percent(record.get_preview()) }} {{ thumbnail.format100percent(record.get_preview()) }}
</div> </div>
<div data-role="footer"> <div data-role="footer">
</div> </div>
{% endblock %} {% endblock %}

View File

@@ -40,18 +40,21 @@
<h1>{{module_name}}</h1> <h1>{{module_name}}</h1>
<a href="#about" class="ui-btn-right">{{ 'a propos' | trans }}</a> <a href="#about" class="ui-btn-right">{{ 'a propos' | trans }}</a>
</div> </div>
<div class="lightbox-user-info">
{% include 'common/menubar.html.twig' %}
</div>
<div data-role="content"> <div data-role="content">
<ul data-role="listview" style="width:100%;margin: 0;"> <ul id="lightbox-menu" data-role="listview" style="width:100%;margin: 0;">
<li> <li class="lightbox-item">
<a href="#validation">{{ 'Validations' | trans }}</a> <a href="#validation">{{ 'Validations' | trans }}</a>
<span class="ui-li-count">{{_self.valid_baskets_length(baskets_collection)}}</span> <span class="ui-li-count">{{_self.valid_baskets_length(baskets_collection)}}</span>
</li> </li>
<li> <li class="lightbox-item">
<a href="#baskets">{{ 'Paniers' | trans }}</a> <a href="#baskets">{{ 'Paniers' | trans }}</a>
<span class="ui-li-count">{{_self.baskets_length(baskets_collection)}}</span> <span class="ui-li-count">{{_self.baskets_length(baskets_collection)}}</span>
</li> </li>
</ul> </ul>
<div style="margin:2em 0 0 0"> <div class="lightbox-bottom-btn">
<a href="{{ path ('logout') }}" data-role="button" rel="external">{{ 'Deconnexion' | trans }}</a> <a href="{{ path ('logout') }}" data-role="button" rel="external">{{ 'Deconnexion' | trans }}</a>
</div> </div>
</div> </div>
@@ -65,6 +68,9 @@
<a href="#home" data-rel="back" data-icon="arrow-l">{{ 'Back' | trans }}</a> <a href="#home" data-rel="back" data-icon="arrow-l">{{ 'Back' | trans }}</a>
<h1>{{ 'a propos' | trans }}</h1> <h1>{{ 'a propos' | trans }}</h1>
</div> </div>
<div class="lightbox-user-info">
{% include 'common/menubar.html.twig' %}
</div>
<div data-role="content"> <div data-role="content">
<p>Phraseanet Version {{ app['phraseanet.version'].getName() }} - {{ app['phraseanet.version'].getNumber() }}</p> <p>Phraseanet Version {{ app['phraseanet.version'].getName() }} - {{ app['phraseanet.version'].getNumber() }}</p>
<p> <p>
@@ -83,27 +89,38 @@
<div id="validation" data-role="page"> <div id="validation" data-role="page">
<div data-role="header"> <div data-role="header">
<a rel="external" href="#home" data-icon="arrow-l">{{ 'Back' | trans }}</a> <a rel="external" href="#home" data-icon="arrow-l">{{ 'Back' | trans }}</a>
<h1>{{ 'Validations' | trans }}</h1> <h1>{{ module_name }}</h1>
</div> </div>
<div class="lightbox-user-info">
{% include 'common/menubar.html.twig' %}
</div>
<div data-role="content"> <div data-role="content">
<p> <p class="basket-title">
{{ 'Voici vos validations en cours' | trans }} {{ 'Validations' | trans }}
</p> <span>{{_self.valid_baskets_length(baskets_collection)}}</span>
<ul data-role="listview" style="width:100%;margin: 0;"> </p>
{% for basket in baskets_collection %} <p class="lightbox-msg">
{% if basket.getValidation() %} {{ 'Voici vos validations en cours' | trans }}
{% set basket_length = basket.getElements().count() %} </p>
<li> <div class="feed-list">
{% if basket.getElements().first() %} <ul data-role="listview" style="width:100%;margin: 0;">
<img src="{{ basket.getElements().first().getRecord(app).get_thumbnail.get_url()}}" /> {% for basket in baskets_collection | sort | reverse%}
{% endif %} {% if basket.getValidation() %}
<h3><a href="{{ path('lightbox_validation', { 'basket' : basket.getId() }) }}">{{basket.getName()}}</a></h3> {% set basket_length = basket.getElements().count() %}
<p>{{ basket.getDescription() }}</p> <li>
<span class="ui-li-count">{{ basket_length }}</span> {% if basket.getElements().first() %}
</li> <div class="lightbox-img">
{% endif %} <img src="{{ basket.getElements().first().getRecord(app).get_thumbnail.get_url()}}" />
{% endfor %} </div>
</ul> {% endif %}
<h3><a href="{{ path('lightbox_validation', { 'basket' : basket.getId() }) }}">{{basket.getName()}}</a></h3>
{#<p>{{ basket.getDescription() }}</p>#}
<span class="ui-li-count validation">{{ basket_length }}</span>
</li>
{% endif %}
{% endfor %}
</ul>
</div>
</div> </div>
<div data-role="footer"> <div data-role="footer">
@@ -113,27 +130,38 @@
<div id="baskets" data-role="page"> <div id="baskets" data-role="page">
<div data-role="header"> <div data-role="header">
<a rel="external" href="#home" data-icon="arrow-l">{{ 'Back' | trans }}</a> <a rel="external" href="#home" data-icon="arrow-l">{{ 'Back' | trans }}</a>
<h1>{{ 'Paniers' | trans }}</h1> <h1>{{module_name}}</h1>
</div> </div>
<div class="lightbox-user-info">
{% include 'common/menubar.html.twig' %}
</div>
<div data-role="content"> <div data-role="content">
<p> <p class="basket-title">
{{ 'Paniers' | trans }}
<span>{{_self.baskets_length(baskets_collection)}}</span>
</p>
<p class="lightbox-msg">
{{ 'Voici vos paniers' | trans }} {{ 'Voici vos paniers' | trans }}
</p> </p>
<ul data-role="listview" style="width:100%;margin: 0;"> <div class="feed-list">
{% for basket in baskets_collection %} <ul data-role="listview" style="width:100%;margin: 0;">
{% if basket.getValidation() is empty %} {% for basket in baskets_collection | sort | reverse %}
{% set basket_length = basket.getElements().count() %} {% if basket.getValidation() is empty %}
<li> {% set basket_length = basket.getElements().count() %}
{% if basket.getElements().first() %} <li>
<img src="{{ basket.getElements().first().getRecord(app).get_thumbnail.get_url()}}" /> {% if basket.getElements().first() %}
{% endif %} <div class="lightbox-img">
<h3><a href="{{ path('lightbox_validation', { 'basket' : basket.getId() }) }}">{{ basket.getName() }}</a></h3> <img src="{{ basket.getElements().first().getRecord(app).get_thumbnail.get_url()}}" />
<p>{{ basket.getDescription() }}</p> </div>
<span class="ui-li-count">{{basket_length}}</span> {% endif %}
</li> <h3><a href="{{ path('lightbox_validation', { 'basket' : basket.getId() }) }}">{{ basket.getName() }}</a></h3>
{% endif %} {#<p>{{ basket.getDescription() }}</p>#}
{% endfor %} <span class="ui-li-count baskets">{{basket_length}}</span>
</ul> </li>
{% endif %}
{% endfor %}
</ul>
</div>
</div> </div>
<div data-role="footer"> <div data-role="footer">

View File

@@ -1,21 +1,19 @@
{% for validationDatas in basket_element.getValidationDatas() %} {% for validationDatas in basket_element.getValidationDatas() %}
<li> {% if basket_element.getBasket().getValidation().getParticipant(app.getAuthenticatedUser()).getCanSeeOthers() or validationDatas.getParticipant().getUser() == app.getAuthenticatedUser() %}
<li>
<div class="validate-icon"> <div class="validate-icon">
{% if basket_element.getBasket().getValidation().getParticipant(app.getAuthenticatedUser()).getCanSeeOthers() or validationDatas.getParticipant().getUser() == app.getAuthenticatedUser() %} {% if validationDatas.getAgreement() == true %}<span class="icomoon icon-agree">&#xe95f;</span>{% endif %}
{% if validationDatas.getAgreement() == true %}<span class="icomoon icon-agree">&#xe95f;</span>{% endif %}
{% if validationDatas.getAgreement() == false and validationDatas.getAgreement() is not null %}<span class="icomoon icon-disagree">&#xe971; {{ validationDatas.getAgreement() }}</span>{% endif %} {% if validationDatas.getAgreement() == false and validationDatas.getAgreement() is not null %}<span class="icomoon icon-disagree">&#xe971; {{ validationDatas.getAgreement() }}</span>{% endif %}
{% endif %}
</div> </div>
<div class="validate-info"> <div class="validate-info">
<h3> <h3>
{{ validationDatas.getParticipant().getUser().getDisplayName() }} {{ validationDatas.getParticipant().getUser().getDisplayName() }}
</h3> </h3>
{% if basket_element.getBasket().getValidation().getParticipant(app.getAuthenticatedUser()).getCanSeeOthers() or validationDatas.getParticipant().getUser() == app.getAuthenticatedUser() %} {% if validationDatas.getNote() != '' %}
{% if validationDatas.getNote() != '' %}
<p style="text-align:left;">{{ 'validation:: note' | trans }} : {{ validationDatas.getNote()|nl2br }} </p> <p style="text-align:left;">{{ 'validation:: note' | trans }} : {{ validationDatas.getNote()|nl2br }} </p>
{% endif %} {% endif %}
{% endif %}
</div> </div>
</li> </li>
{% endif %}
{% endfor %} {% endfor %}

View File

@@ -32,6 +32,9 @@
<h1>{{basket.getName()}}</h1> <h1>{{basket.getName()}}</h1>
<a rel="external" href="{{ path('lightbox') }}" data-icon="home" data-iconpos="notext" data-direction="reverse" class="ui-btn-right jqm-home">{{ 'Home' | trans }}</a> <a rel="external" href="{{ path('lightbox') }}" data-icon="home" data-iconpos="notext" data-direction="reverse" class="ui-btn-right jqm-home">{{ 'Home' | trans }}</a>
</div> </div>
<div class="lightbox-user-info">
{% include 'common/menubar.html.twig' %}
</div>
<div data-role="content"> <div data-role="content">
<input type="hidden" id="basket_validation_id" value="{{ basket.getId() }}"> <input type="hidden" id="basket_validation_id" value="{{ basket.getId() }}">
<p> <p>

View File

@@ -17,32 +17,31 @@
</div> </div>
<div class="chim-right"> <div class="chim-right">
{% for validationDatas in basket_element.getValidationDatas()%} {% for validationDatas in basket_element.getValidationDatas()%}
<div class="basket_report_user_wrapper ui-corner-all"> {% if basket_element.getBasket().getValidation().getParticipant(app.getAuthenticatedUser()).getCanSeeOthers() or validationDatas.getParticipant().getUser() == app.getAuthenticatedUser() %}
{% if validationDatas.getAgreement() == true %}
{% set imguser = '<span class="icomoon icon-agree">&#xe95f;</span>' %}
{% set styleuser = '' %}
{% elseif validationDatas.getAgreement() is null %}
{% set imguser = '&nbsp;' %}
{% set styleuser = 'margin-left:18px;' %}
{% else %}
{% set imguser = '<span class="icomoon icon-disagree">&#xe971;</span>' %}
{% set styleuser = '' %}
{% endif %}
<div class="validate-icon"> <div class="basket_report_user_wrapper ui-corner-all">
{% if basket_element.getBasket().getValidation().getParticipant(app.getAuthenticatedUser()).getCanSeeOthers() or validationDatas.getParticipant().getUser() == app.getAuthenticatedUser() %} {% if validationDatas.getAgreement() == true %}
{{imguser|raw}} {% set imguser = '<span class="icomoon icon-agree">&#xe95f;</span>' %}
{% endif %} {% set styleuser = '' %}
</div> {% elseif validationDatas.getAgreement() is null %}
<div class="validate-info"> {% set imguser = '&nbsp;' %}
<h3> {{validationDatas.getParticipant().getUser().getDisplayName()}}</h3> {% set styleuser = 'margin-left:18px;' %}
{% if validationDatas.getNote() != '' %} {% else %}
{% if basket_element.getBasket().getValidation().getParticipant(app.getAuthenticatedUser()).getCanSeeOthers() or validationDatas.getParticipant().getUser() == app.getAuthenticatedUser() %} {% set imguser = '<span class="icomoon icon-disagree">&#xe971;</span>' %}
<p> {{validationDatas.getNote()|nl2br}}</p> {% set styleuser = '' %}
{% endif %} {% endif %}
{% endif %}
<div class="validate-icon">
{{imguser|raw}}
</div>
<div class="validate-info">
<h3> {{validationDatas.getParticipant().getUser().getDisplayName()}}</h3>
{% if validationDatas.getNote() != '' %}
<p> {{validationDatas.getNote()|nl2br}}</p>
{% endif %}
</div>
</div> </div>
</div> {% endif %}
{% endfor %} {% endfor %}
</div> </div>
</div> </div>

View File

@@ -16,9 +16,10 @@
<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>
{% if not basket.isRead() %} {% if not basket.isRead() %}
<img src='/assets/common/images/icons/basket_push_unread.png' title=''/> <img src='/assets/common/images/icons/basket_feedback_unread.png' title=''/>
{% else %}
<img src='/assets/common/images/icons/basket_feedback_read.png' title=''/>
{% endif %} {% endif %}
<img src='/assets/common/images/icons/basket.png' title=''/>
{{basket.getName()|e}} {{basket.getName()|e}}
</span> </span>
</a> </a>
@@ -26,11 +27,9 @@
<table> <table>
<tr> <tr>
<td> <td>
<img <img title="{{ basket.getDescription()|e }}"
title="{{ basket.getDescription() }}" class="basket_title"
class="basketTips basket_title" src="/assets/common/images/icons/valid.png" />
src="/assets/common/images/icons/valid.png"
/>
</td> </td>
<td> <td>
<a class="contextMenuTrigger icon-display-grid" href="#"></a> <a class="contextMenuTrigger icon-display-grid" href="#"></a>

View File

@@ -218,8 +218,8 @@
</span> </span>
</td> </td>
<td class="options"> <td class="options">
<button class="select-all round-blue-border-btn" style="width: 128px; margin-right: 10px;">{{ 'Select all' | trans }}</button> <button class="select-all round-blue-border-btn" style="margin-right: 10px;">{{ 'Select all' | trans }}</button>
<button class="unselect-all round-blue-border-btn" style="width: 128px;">{{ 'Deselect all' | trans }}</button> <button class="unselect-all round-blue-border-btn">{{ 'Deselect all' | trans }}</button>
<button class="delete-selection btn btn-inverse">{{ 'prod:push: delete selection' | trans }}</button> <button class="delete-selection btn btn-inverse">{{ 'prod:push: delete selection' | trans }}</button>
</td> </td>
</tr> </tr>

View File

@@ -7565,10 +7565,10 @@ phantomjs-prebuilt@^2.1.3:
request-progress "^2.0.1" request-progress "^2.0.1"
which "^1.2.10" which "^1.2.10"
phraseanet-common@^0.4.1: phraseanet-common@^0.4.5-d:
version "0.4.2" version "0.4.5-d"
resolved "https://registry.yarnpkg.com/phraseanet-common/-/phraseanet-common-0.4.2.tgz#740de9bf254116adc506c9703015ab1533f89864" resolved "https://registry.yarnpkg.com/phraseanet-common/-/phraseanet-common-0.4.5-d.tgz#193da1ab062f98e99729b7f98a7bbe32c495c7f3"
integrity sha512-uyKULVCV9df161A970mWnZtdxAb/ZWCuUdnSTn0T9AGvwsWvKf2p6+pgEVtBQ81LIGn1m5UlhiF7dUlc6nT7iQ== integrity sha512-7mmPDg0pFnFYyY1eazmUcDa18SGXp90zEBYTNzVan6goPPBjUmA0YwzBiuvDnxlcwMX8x0kDIrOouOBfWG5E1w==
dependencies: dependencies:
es6-promise "^4.1.1" es6-promise "^4.1.1"
humane-js "^3.2.2" humane-js "^3.2.2"
@@ -7577,10 +7577,10 @@ phraseanet-common@^0.4.1:
js-cookie "^2.1.0" js-cookie "^2.1.0"
pym.js "^1.3.1" pym.js "^1.3.1"
phraseanet-production-client@0.34.80-d: phraseanet-production-client@^0.34.86-d:
version "0.34.80-d" version "0.34.86-d"
resolved "https://registry.yarnpkg.com/phraseanet-production-client/-/phraseanet-production-client-0.34.80-d.tgz#1e54bee4306ab11528377cb63c19d8c7491ef0f3" resolved "https://registry.yarnpkg.com/phraseanet-production-client/-/phraseanet-production-client-0.34.86-d.tgz#51e6c6fb17fcd2695cee90fb3d972c781057fd78"
integrity sha512-ilGs7ndDNztwlyeW9MA2TMiMhZC+P1/lNNeIsIuh+KuJH8M3Y3SWBcmsN2lqu5iM1Xg5FbWJ6iXcCSrLWHTqsw== integrity sha512-12o7pcRZAJ/5Ote4DbkaRxLz2GIZBUcZf53FB+GHVFxhds5ia6UNDCPhYP5vX4hhHtO/Y6Mj/BOlOjnoyi+k1g==
dependencies: dependencies:
"@mapbox/mapbox-gl-language" "^0.9.2" "@mapbox/mapbox-gl-language" "^0.9.2"
"@turf/turf" "^5.1.6" "@turf/turf" "^5.1.6"
@@ -7611,7 +7611,7 @@ phraseanet-production-client@0.34.80-d:
mapbox-gl-circle "^1.6.5" mapbox-gl-circle "^1.6.5"
mapbox.js "^2.4.0" mapbox.js "^2.4.0"
nouislider "^9.2.0" nouislider "^9.2.0"
phraseanet-common "^0.4.1" phraseanet-common "^0.4.5-d"
pym.js "^1.3.1" pym.js "^1.3.1"
rx "^4.1.0" rx "^4.1.0"
sprintf-js "^1.1.1" sprintf-js "^1.1.1"