From cea47e87258070178db982f9204778ccf6ba13cf Mon Sep 17 00:00:00 2001 From: Alexandre BRACH Date: Thu, 26 Sep 2019 16:52:20 +0200 Subject: [PATCH 01/61] kubernetes #comment remove unused server_name directive in nginx --- docker/nginx/nginx.conf.sample | 1 - 1 file changed, 1 deletion(-) diff --git a/docker/nginx/nginx.conf.sample b/docker/nginx/nginx.conf.sample index c1f0150c1e..0284f137d9 100644 --- a/docker/nginx/nginx.conf.sample +++ b/docker/nginx/nginx.conf.sample @@ -46,7 +46,6 @@ http { server { listen 80; - server_name localhost; error_log on; access_log on; root /var/alchemy/Phraseanet/www; From b7f5a4cf3c68fbcdcce2f6e620174940439688f3 Mon Sep 17 00:00:00 2001 From: Alexandre BRACH Date: Thu, 26 Sep 2019 17:39:00 +0200 Subject: [PATCH 02/61] kubernetes #comment Fix the owner of config to app at the fpm container startup --- docker/phraseanet/boot.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/docker/phraseanet/boot.sh b/docker/phraseanet/boot.sh index 4b2cf2baa2..e4e17aec7d 100755 --- a/docker/phraseanet/boot.sh +++ b/docker/phraseanet/boot.sh @@ -1,5 +1,6 @@ #!/bin/bash +chown -R app:app /var/alchemy/Phraseanet/config FILE=/var/alchemy/Phraseanet/config/configuration.yml if [ -f "$FILE" ]; then echo "$FILE exist, skip setup." From b66aae50470d3ae287bed3448009f07ea4bdaa07 Mon Sep 17 00:00:00 2001 From: Alexandre BRACH Date: Fri, 27 Sep 2019 14:31:17 +0200 Subject: [PATCH 03/61] kubernetes #comment Reconfigure nginx to serve log on stdout --- docker/nginx/boot.sh | 4 +- docker/nginx/nginx.conf.sample | 101 +++++++++------------------------ 2 files changed, 31 insertions(+), 74 deletions(-) diff --git a/docker/nginx/boot.sh b/docker/nginx/boot.sh index 49e6b8a3b7..2684d8c0f7 100755 --- a/docker/nginx/boot.sh +++ b/docker/nginx/boot.sh @@ -1,4 +1,6 @@ #!/bin/bash -cat nginx.conf.sample | sed "s/\$MAX_BODY_SIZE/$MAX_BODY_SIZE/g" > /etc/nginx/nginx.conf +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;" diff --git a/docker/nginx/nginx.conf.sample b/docker/nginx/nginx.conf.sample index 0284f137d9..ad015e7c5a 100644 --- a/docker/nginx/nginx.conf.sample +++ b/docker/nginx/nginx.conf.sample @@ -1,84 +1,39 @@ -user app; -worker_processes auto; - -#error_log /var/log/ngnix_error.log info; -error_log /dev/stdout info; - -pid /var/run/nginx.pid; -#daemon off; - -events { - worker_connections 1024; - multi_accept on; +upstream backend { + server phraseanet:9000; } -http { - include /etc/nginx/mime.types; - default_type application/octet-stream; - server_tokens off; +server { + listen 80; + root /var/alchemy/Phraseanet/www; - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; + index index.php; + client_max_body_size $MAX_BODY_SIZE; - access_log /dev/stdout main; - - sendfile on; - #tcp_nopush on; - - keepalive_timeout 65; - - #gzip on; - - reset_timedout_connection on; - - proxy_connect_timeout 300s; - proxy_send_timeout 300s; - proxy_read_timeout 300s; - fastcgi_send_timeout 300s; - fastcgi_read_timeout 300; - - resolver 127.0.0.11; - - upstream backend { - server phraseanet:9000; + location /api { + rewrite ^(.*)$ /api.php/$1 last; } - server { - listen 80; - error_log on; - access_log on; - root /var/alchemy/Phraseanet/www; + location / { + # First attempt to serve request as file, then + # as directory, then fall back to index.html + try_files $uri $uri/ @rewriteapp; + } - index index.php; - client_max_body_size $MAX_BODY_SIZE; + location @rewriteapp { + rewrite ^(.*)$ /index.php/$1 last; + } - location /api { - rewrite ^(.*)$ /api.php/$1 last; - } + # PHP scripts -> PHP-FPM server listening on 127.0.0.1:9000 + location ~ ^/(index|index_dev|api)\.php(/|$) { + fastcgi_pass backend; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include fastcgi_params; + } - location / { - # First attempt to serve request as file, then - # as directory, then fall back to index.html - try_files $uri $uri/ @rewriteapp; - } - - location @rewriteapp { - rewrite ^(.*)$ /index.php/$1 last; - } - - # PHP scripts -> PHP-FPM server listening on 127.0.0.1:9000 - location ~ ^/(index|index_dev|api)\.php(/|$) { - fastcgi_pass backend; - fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - include fastcgi_params; - } - - location ~ ^/(status|ping)$ { - fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - fastcgi_index index.php; - include fastcgi_params; - fastcgi_pass backend; - } + location ~ ^/(status|ping)$ { + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_index index.php; + include fastcgi_params; + fastcgi_pass backend; } } From b87ab0cd0809282abda1cda65d939c74c35e52c4 Mon Sep 17 00:00:00 2001 From: Alexandre BRACH Date: Fri, 27 Sep 2019 16:28:49 +0200 Subject: [PATCH 04/61] kubernetes #comment fpm stop on failure --- docker/phraseanet/boot.sh | 2 ++ docker/phraseanet/phraseanet-entrypoint.sh | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docker/phraseanet/boot.sh b/docker/phraseanet/boot.sh index e4e17aec7d..120f750684 100755 --- a/docker/phraseanet/boot.sh +++ b/docker/phraseanet/boot.sh @@ -1,5 +1,7 @@ #!/bin/bash +set -xe + chown -R app:app /var/alchemy/Phraseanet/config FILE=/var/alchemy/Phraseanet/config/configuration.yml if [ -f "$FILE" ]; then diff --git a/docker/phraseanet/phraseanet-entrypoint.sh b/docker/phraseanet/phraseanet-entrypoint.sh index de763cd13a..225b56a672 100755 --- a/docker/phraseanet/phraseanet-entrypoint.sh +++ b/docker/phraseanet/phraseanet-entrypoint.sh @@ -5,4 +5,4 @@ set -e envsubst < /php.ini.sample > /usr/local/etc/php/php.ini envsubst < /php-fpm.conf.sample > /usr/local/etc/php-fpm.conf -docker-php-entrypoint $@ +bash -e docker-php-entrypoint $@ From c85796fb29b38552b6897ae14cfadd993870d0c3 Mon Sep 17 00:00:00 2001 From: Alexandre BRACH Date: Fri, 27 Sep 2019 17:02:51 +0200 Subject: [PATCH 05/61] kubernetes #comment fix permissions on datas and thumbnails directory at startup --- docker/phraseanet/boot.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker/phraseanet/boot.sh b/docker/phraseanet/boot.sh index 120f750684..ede2f1db60 100755 --- a/docker/phraseanet/boot.sh +++ b/docker/phraseanet/boot.sh @@ -3,6 +3,8 @@ 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/www/thumbnails FILE=/var/alchemy/Phraseanet/config/configuration.yml if [ -f "$FILE" ]; then echo "$FILE exist, skip setup." From e0ee90e3af6b86d1f4e0b184ffc927c3257f24ba Mon Sep 17 00:00:00 2001 From: Harrys Ravalomanana Date: Tue, 1 Oct 2019 16:10:46 +0400 Subject: [PATCH 06/61] PHRAS-2761 #comment add status change to quarantine #time 8h --- templates/web/prod/upload/lazaret.html.twig | 33 ++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/templates/web/prod/upload/lazaret.html.twig b/templates/web/prod/upload/lazaret.html.twig index 29bad734c0..e68d4ee0f7 100644 --- a/templates/web/prod/upload/lazaret.html.twig +++ b/templates/web/prod/upload/lazaret.html.twig @@ -114,7 +114,7 @@ $('button.empty-lazaret', scope).bind('click', function(){ var that = $(this); - + if(!confirm("{{ "Empty quarantine will remove all items, are you sure you want to continue ?" | trans }}")) { return false; } @@ -344,6 +344,36 @@

{{ border_checker_from_fqcn(check.getCheckClassname()).getMessage(app['translator']) }}

{% endfor %} + +
+ {% set collection = file.getCollection(app) %} +
+
{{ 'upload:: Status :' | trans }} :
+ + + {% for bit, status in collection.get_databox().getStatusStructure() %} + + + + + {% endfor %} + +
+ {% if status['img_off'] is not empty %} + + {% endif %} + {{ status['labels_off_i18n'][app['locale']]|default('off') }} + + + + {{ status['labels_on_i18n'][app['locale']]|default('on') }} + {% if status['img_on'] is not empty %} + + {% endif %} +
+
+
+
{% endif %} + {% endmacro %} From 6660c7fe32ca9b6b32ded2679e6c55f358a82c3f Mon Sep 17 00:00:00 2001 From: Alexandre BRACH Date: Thu, 3 Oct 2019 16:40:02 +0200 Subject: [PATCH 07/61] kubernetes #comment tmp owner is root at fpm startup --- docker/phraseanet/boot.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/docker/phraseanet/boot.sh b/docker/phraseanet/boot.sh index ede2f1db60..444b63a64c 100755 --- a/docker/phraseanet/boot.sh +++ b/docker/phraseanet/boot.sh @@ -4,6 +4,7 @@ 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 From 9fdd704d5a2d518392746cfb65c23a700004a09f Mon Sep 17 00:00:00 2001 From: Alexandre BRACH Date: Fri, 4 Oct 2019 09:06:14 +0200 Subject: [PATCH 08/61] kubernetes #comment create needed directory for worker --- Dockerfile | 24 ++++++++++++------------ docker/phraseanet/worker-boot.sh | 1 + 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/Dockerfile b/Dockerfile index 7ff718ab2c..00ef2acfdc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -86,6 +86,18 @@ COPY grammar /var/alchemy/grammar COPY templates-profiler /var/alchemy/templates-profiler COPY templates /var/alchemy/templates COPY tests /var/alchemy/tests +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 FROM php:7.0-fpm-stretch as phraseanet-fpm @@ -136,18 +148,6 @@ RUN mkdir /entrypoint /var/alchemy \ COPY --from=builder --chown=app /var/alchemy /var/alchemy/Phraseanet ADD ./docker/phraseanet/ / -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 WORKDIR /var/alchemy/Phraseanet ENTRYPOINT ["/phraseanet-entrypoint.sh"] CMD ["/boot.sh"] diff --git a/docker/phraseanet/worker-boot.sh b/docker/phraseanet/worker-boot.sh index 1b972c6cdb..4c1b76b02f 100755 --- a/docker/phraseanet/worker-boot.sh +++ b/docker/phraseanet/worker-boot.sh @@ -1,3 +1,4 @@ #!/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' From 9b25efdc6701763c0534dd393c1d705dff38fdba Mon Sep 17 00:00:00 2001 From: Alexandre BRACH Date: Fri, 4 Oct 2019 15:56:38 +0200 Subject: [PATCH 09/61] kubernetes #comment add global nginx configuration --- docker/nginx/etc/nginx/nginx.conf | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100755 docker/nginx/etc/nginx/nginx.conf diff --git a/docker/nginx/etc/nginx/nginx.conf b/docker/nginx/etc/nginx/nginx.conf new file mode 100755 index 0000000000..71a94ee98f --- /dev/null +++ b/docker/nginx/etc/nginx/nginx.conf @@ -0,0 +1,31 @@ + +user app; +worker_processes 1; + +error_log /var/log/ngnix_error.log info; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + #tcp_nopush on; + + keepalive_timeout 65; + + #gzip on; + + include /etc/nginx/conf.d/*.conf; + +} From ce67d5f62d2521cb7b3ac49f2112f8a21c46257f Mon Sep 17 00:00:00 2001 From: Harrys Ravalomanana Date: Tue, 8 Oct 2019 16:40:07 +0400 Subject: [PATCH 10/61] PHRAS-2785 #comment Port41 of PHRAS-2758 #time 1h --- .../SearchEngine/Elastic/Search/FacetsResponse.php | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/Alchemy/Phrasea/SearchEngine/Elastic/Search/FacetsResponse.php b/lib/Alchemy/Phrasea/SearchEngine/Elastic/Search/FacetsResponse.php index 55503d50d6..42c5a63e25 100644 --- a/lib/Alchemy/Phrasea/SearchEngine/Elastic/Search/FacetsResponse.php +++ b/lib/Alchemy/Phrasea/SearchEngine/Elastic/Search/FacetsResponse.php @@ -46,22 +46,23 @@ class FacetsResponse if (!isset($bucket['key']) || !isset($bucket['doc_count'])) { $this->throwAggregationResponseError(); } + $key = array_key_exists('key_as_string', $bucket) ? $bucket['key_as_string'] : $bucket['key']; if($tf) { // the field is one of the hardcoded tech fields $value = [ - 'value' => $valueFormatter($bucket['key']), - 'raw_value' => $bucket['key'], + 'value' => $valueFormatter($key), + 'raw_value' => $key, 'count' => $bucket['doc_count'], - 'query' => sprintf($tf['query'], $this->escaper->escapeWord($bucket['key'])) + 'query' => sprintf($tf['query'], $this->escaper->escapeWord($key)) ]; } else { // the field is a normal field $value = [ - 'value' => $bucket['key'], - 'raw_value' => $bucket['key'], + 'value' => $key, + 'raw_value' => $key, 'count' => $bucket['doc_count'], - 'query' => sprintf('field.%s:%s', $this->escaper->escapeWord($name), $this->escaper->escapeWord($bucket['key'])) + 'query' => sprintf('field.%s:%s', $this->escaper->escapeWord($name), $this->escaper->escapeWord($key)) ]; } From 5f1f8b3b438459a60f0f5e3c4ec4c24c465f3e69 Mon Sep 17 00:00:00 2001 From: Alexandre BRACH Date: Fri, 18 Oct 2019 16:09:08 +0200 Subject: [PATCH 11/61] kubernetes #comment add composer in the fpm/worker images --- Dockerfile | 5 +++++ README.md | 14 ++++++-------- build.sh | 11 +++++++++++ 3 files changed, 22 insertions(+), 8 deletions(-) create mode 100755 build.sh diff --git a/Dockerfile b/Dockerfile index 00ef2acfdc..ca4e87b204 100644 --- a/Dockerfile +++ b/Dockerfile @@ -141,6 +141,11 @@ RUN apt-get update \ && docker-php-source delete \ && rm -rf /var/lib/apt/lists/* +RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \ + && 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');" + RUN mkdir /entrypoint /var/alchemy \ && useradd -u 1000 app \ && mkdir -p /home/app/.composer \ diff --git a/README.md b/README.md index 9fb4237d25..fb4b34870d 100644 --- a/README.md +++ b/README.md @@ -63,14 +63,12 @@ The docker distribution come with 3 differents containers : ## How to build -The three images can be built respectively with these commands : +You can build all the images with the following command at the root directory : - # nginx server - docker build --target phraseanet-nginx -t local/phraseanet-nginx . + ./build - # php-fpm application - docker build --target phraseanet-fpm -t local/phraseanet-fpm . - - # worker - docker build --target phraseanet-worker -t local/phraseanet-worker . +It will build and tag the following images : + local/phraseanet-worker: + local/phraseanet-fpm: + local/phraseanet-nginx: diff --git a/build.sh b/build.sh new file mode 100755 index 0000000000..0f983ccac4 --- /dev/null +++ b/build.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +# 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 . + From ccef7b11dc722757ba8300edf3070caea28bbd98 Mon Sep 17 00:00:00 2001 From: Alexandre BRACH Date: Fri, 18 Oct 2019 16:45:57 +0200 Subject: [PATCH 12/61] kubernetes #comment add yarn in the fpm/worker images --- Dockerfile | 12 ++++++++++++ yarn.lock | 8 ++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index ca4e87b204..c40dfc4347 100644 --- a/Dockerfile +++ b/Dockerfile @@ -146,6 +146,18 @@ RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \ && 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 \ diff --git a/yarn.lock b/yarn.lock index 4cfedda66c..0e79ed1adf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5283,10 +5283,14 @@ jquery-simplecolorpicker@^0.3.1: resolved "https://registry.yarnpkg.com/jquery-simplecolorpicker/-/jquery-simplecolorpicker-0.3.1.tgz#4f6befd380ab05470f585d5482e5180556e460eb" integrity sha1-T2vv04CrBUcPWF1UguUYBVbkYOs= -"jquery-treeview@git+https://github.com/alchemy-fr/jquery-treeview.git", "jquery-treeview@git+https://github.com/alchemy-fr/jquery-treeview.git#1e9e5a49d2875b878801e904cd08c2d25e85af1e": +"jquery-treeview@git+https://github.com/alchemy-fr/jquery-treeview.git#1e9e5a49d2875b878801e904cd08c2d25e85af1e": + version "1.4.2" + resolved "git+https://github.com/alchemy-fr/jquery-treeview.git#1e9e5a49d2875b878801e904cd08c2d25e85af1e" + +"jquery-treeview@https://github.com/alchemy-fr/jquery-treeview.git": version "1.4.2" uid "1e9e5a49d2875b878801e904cd08c2d25e85af1e" - resolved "git+https://github.com/alchemy-fr/jquery-treeview.git#1e9e5a49d2875b878801e904cd08c2d25e85af1e" + resolved "https://github.com/alchemy-fr/jquery-treeview.git#1e9e5a49d2875b878801e904cd08c2d25e85af1e" jquery-ui-datepicker-with-i18n@^1.10.4: version "1.10.4" From b22793f21a009b1e35a6c9892871a2314bf27e20 Mon Sep 17 00:00:00 2001 From: Moctar Date: Thu, 24 Oct 2019 18:06:50 +0200 Subject: [PATCH 13/61] add missing cache directory --- cache/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 cache/.gitkeep diff --git a/cache/.gitkeep b/cache/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 From df86aac2bad178171f7820d1dce36afcdd013232 Mon Sep 17 00:00:00 2001 From: Harrys Ravalomanana Date: Tue, 29 Oct 2019 16:48:14 +0400 Subject: [PATCH 14/61] PHRAS-2766 #comment port 41 Add status change capabilities to quarantine #time 3h --- .../Controller/Prod/LazaretController.php | 73 ++- .../ControllerProvider/Prod/Lazaret.php | 5 + .../Phrasea/Model/Entities/LazaretFile.php | 29 ++ .../Model/Manipulator/LazaretManipulator.php | 2 + package.json | 2 +- .../common/images/icons/icon-right-arrow.svg | 31 ++ templates/web/prod/upload/lazaret.html.twig | 459 ++++++++++++------ 7 files changed, 461 insertions(+), 140 deletions(-) create mode 100644 resources/www/common/images/icons/icon-right-arrow.svg diff --git a/lib/Alchemy/Phrasea/Controller/Prod/LazaretController.php b/lib/Alchemy/Phrasea/Controller/Prod/LazaretController.php index afb91cb23e..7fcddb0b28 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/LazaretController.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/LazaretController.php @@ -70,7 +70,7 @@ class LazaretController extends Controller public function getElement($file_id) { $ret = ['success' => false, 'message' => '', 'result' => []]; - + /* @var LazaretFile $lazaretFile */ $lazaretFile = $this->getLazaretFileRepository()->find($file_id); @@ -126,6 +126,16 @@ class LazaretController extends Controller $ret = $lazaretManipulator->add($file_id, $keepAttributes, $attributesToKeep); + try{ + // get the new record + $record = \Collection::getByBaseId($this->app, $request->request->get('bas_id'))->get_databox()->get_record($ret['result']['record_id']); + $postStatus = (array) $request->request->get('status'); + // update status + $this->updateRecordStatus($record, $postStatus); + }catch(\Exception $e){ + $ret['message'] = $this->app->trans('An error occured when wanting to change status!'); + } + return $this->app->json($ret); } @@ -216,6 +226,7 @@ class LazaretController extends Controller return $this->app->json($ret); } + $postStatus = (array) $request->request->get('status'); $path = $this->app['tmp.lazaret.path'] . '/'; $lazaretFileName = $path .$lazaretFile->getFilename(); @@ -233,6 +244,9 @@ class LazaretController extends Controller '' ); + // update status + $this->updateRecordStatus($record, $postStatus); + //Delete lazaret file $manager = $this->getEntityManager(); $manager->remove($lazaretFile); @@ -278,6 +292,35 @@ class LazaretController extends Controller ); } + /** + * @param Request $request + * @param $databox_id + * @param $record_id + * @return \Symfony\Component\HttpFoundation\JsonResponse + */ + public function getDestinationStatus(Request $request, $databox_id, $record_id) + { + if (!$request->isXmlHttpRequest()) { + $this->app->abort(400); + } + $record = new \record_adapter($this->app, (int) $databox_id, (int) $record_id); + $databox = $this->findDataboxById($databox_id); + $statusStructure = $databox->getStatusStructure(); + $recordsStatuses = []; + foreach ($statusStructure as $status) { + // make the key as a string for the json usage in javascript + $bit = "'".$status['bit']."'"; + if (!isset($recordsStatuses[$bit])) { + $recordsStatuses[$bit] = $status; + } + $statusSet = \databox_status::bitIsSet($record->getStatusBitField(), $status['bit']); + if (!isset($recordsStatuses[$bit]['flag'])) { + $recordsStatuses[$bit]['flag'] = (int) $statusSet; + } + } + return $this->app->json(['status' => $recordsStatuses]); + } + /** * @return LazaretFileRepository */ @@ -293,4 +336,32 @@ class LazaretController extends Controller { return $this->app['border-manager']; } + + /** + * Set new status to selected record + * + * @param \record_adapter $record + * @param array $postStatus + * @return array|null + */ + private function updateRecordStatus(\record_adapter $record, array $postStatus) + { + $sbasId = $record->getDataboxId(); + if (isset($postStatus[$sbasId]) && is_array($postStatus[$sbasId])) { + $postStatus = $postStatus[$sbasId]; + $currentStatus = strrev($record->getStatus()); + $newStatus = ''; + foreach (range(0, 31) as $i) { + $newStatus .= isset($postStatus[$i]) ? ($postStatus[$i] ? '1' : '0') : $currentStatus[$i]; + } + $record->setStatus(strrev($newStatus)); + $this->getDataboxLogger($record->getDatabox()) + ->log($record, \Session_Logger::EVENT_STATUS, '', ''); + return [ + 'current_status' => $currentStatus, + 'new_status' => $newStatus, + ]; + } + return null; + } } diff --git a/lib/Alchemy/Phrasea/ControllerProvider/Prod/Lazaret.php b/lib/Alchemy/Phrasea/ControllerProvider/Prod/Lazaret.php index 16081d7f14..53c2804fce 100644 --- a/lib/Alchemy/Phrasea/ControllerProvider/Prod/Lazaret.php +++ b/lib/Alchemy/Phrasea/ControllerProvider/Prod/Lazaret.php @@ -82,6 +82,11 @@ class Lazaret implements ControllerProviderInterface, ServiceProviderInterface ->assert('file_id', '\d+') ->bind('lazaret_thumbnail'); + $controllers->get('/{databox_id}/{record_id}/status', 'controller.prod.lazaret:getDestinationStatus') + ->assert('databox_id', '\d+') + ->assert('record_id', '\d+') + ->bind('lazaret_destination_status'); + return $controllers; } } diff --git a/lib/Alchemy/Phrasea/Model/Entities/LazaretFile.php b/lib/Alchemy/Phrasea/Model/Entities/LazaretFile.php index 9355acc471..221027e28e 100644 --- a/lib/Alchemy/Phrasea/Model/Entities/LazaretFile.php +++ b/lib/Alchemy/Phrasea/Model/Entities/LazaretFile.php @@ -12,6 +12,7 @@ namespace Alchemy\Phrasea\Model\Entities; use Alchemy\Phrasea\Application; +use Alchemy\Phrasea\Border\Attribute\AttributeInterface; use Doctrine\ORM\Mapping as ORM; use Gedmo\Mapping\Annotation as Gedmo; use \record_adapter; @@ -474,4 +475,32 @@ class LazaretFile return $merged; } + /** + * @param Application $app + * @return array|null + */ + public function getStatus(Application $app) + { + /**@var LazaretAttribute $atribute*/ + foreach ($this->attributes as $atribute) { + if ($atribute->getName() == AttributeInterface::NAME_STATUS) { + $databox = $this->getCollection($app)->get_databox(); + $statusStructure = $databox->getStatusStructure(); + $recordsStatuses = []; + foreach ($statusStructure as $status) { + $bit = $status['bit']; + if (!isset($recordsStatuses[$bit])) { + $recordsStatuses[$bit] = $status; + } + $statusSet = \databox_status::bitIsSet(bindec($atribute->getValue()), $bit); + if (!isset($recordsStatuses[$bit]['flag'])) { + $recordsStatuses[$bit]['flag'] = (int) $statusSet; + } + } + return $recordsStatuses; + } + } + return null; + } + } diff --git a/lib/Alchemy/Phrasea/Model/Manipulator/LazaretManipulator.php b/lib/Alchemy/Phrasea/Model/Manipulator/LazaretManipulator.php index fff97be4bd..3c86fe91e3 100644 --- a/lib/Alchemy/Phrasea/Model/Manipulator/LazaretManipulator.php +++ b/lib/Alchemy/Phrasea/Model/Manipulator/LazaretManipulator.php @@ -226,6 +226,8 @@ class LazaretManipulator $this->entityManager->remove($lazaretFile); $this->entityManager->flush(); + $ret['result']['record_id'] = $record->getRecordId(); + $ret['success'] = true; } catch (\Exception $e) { $ret['message'] = $this->app->trans('An error occured'); diff --git a/package.json b/package.json index 84823d0938..aabd465c41 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "normalize-css": "^2.1.0", "npm": "^6.0.0", "npm-modernizr": "^2.8.3", - "phraseanet-production-client": "0.34.72-d", + "phraseanet-production-client": "0.34.74-d", "requirejs": "^2.3.5", "tinymce": "^4.0.28", "underscore": "^1.8.3", diff --git a/resources/www/common/images/icons/icon-right-arrow.svg b/resources/www/common/images/icons/icon-right-arrow.svg new file mode 100644 index 0000000000..c3fabe9a03 --- /dev/null +++ b/resources/www/common/images/icons/icon-right-arrow.svg @@ -0,0 +1,31 @@ + + + + 5609DDD5-6B9C-411B-B926-EEA284949013 + Created with sketchtool. + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/templates/web/prod/upload/lazaret.html.twig b/templates/web/prod/upload/lazaret.html.twig index e68d4ee0f7..b79d30ba65 100644 --- a/templates/web/prod/upload/lazaret.html.twig +++ b/templates/web/prod/upload/lazaret.html.twig @@ -35,7 +35,7 @@
    {% for file in lazaretFiles %}
  • - {{ _self.lazaretElement(app, file) }} + {{ _self.lazaretElement(app, file) }}
  • {% endfor %}
@@ -48,56 +48,56 @@ - {% macro lazaretElement(app, file) %} {% import "common/thumbnail.html.twig" as thumb %} {% set records = file.getRecordsToSubstitute(app, true) %}
+
{{ "Last uploaded version" | trans }}
    -
  • +
  • @@ -344,34 +425,63 @@

    {{ border_checker_from_fqcn(check.getCheckClassname()).getMessage(app['translator']) }}

    {% endfor %}
    +
    + {% set collection = file.getCollection(app) %} + + + +
    +
    + Reset status +
    {{ 'upload:: Status :' | trans }}
    +