[skip ci]

PHRAS-3381_tx-as-classification-plan_MASTER
back controller for ok button
fix : PHRAS-3383
WIP
This commit is contained in:
jygaulier
2021-03-11 20:10:49 +01:00
parent 92df433af0
commit a76f64e892
10 changed files with 482 additions and 63 deletions

View File

@@ -540,7 +540,12 @@ const workzone = (services) => {
$('.bloc', cache).droppable({ $('.bloc', cache).droppable({
accept: function (elem) { accept: function (elem) {
return false; // return false;
let currentTab = $('#idFrameC .tabs').data('hash');
if(currentTab !== '#baskets_wrapper' && currentTab !== '#baskets') {
return false; // can't drop on baskets if the baskets tab is not front
}
if ($(elem).hasClass('grouping') && !$(elem).hasClass('SSTT')) { if ($(elem).hasClass('grouping') && !$(elem).hasClass('SSTT')) {
return true; return true;
} }
@@ -565,7 +570,12 @@ return false;
hoverClass: 'baskDrop', hoverClass: 'baskDrop',
tolerance: 'pointer', tolerance: 'pointer',
accept: function (elem) { accept: function (elem) {
//return false; // return false;
let currentTab = $('#idFrameC .tabs').data('hash');
if(currentTab !== '#baskets_wrapper' && currentTab !== '#baskets') {
return false; // can't drop on baskets if the baskets tab is not front
}
if ($(elem).hasClass('CHIM')) { if ($(elem).hasClass('CHIM')) {
if ($(elem).closest('.content').prev()[0] === $(this)[0]) { if ($(elem).closest('.content').prev()[0] === $(this)[0]) {
return false; return false;
@@ -615,7 +625,12 @@ return false;
hoverClass: 'baskDrop', hoverClass: 'baskDrop',
tolerance: 'pointer', tolerance: 'pointer',
accept: function (elem) { accept: function (elem) {
return false; // return false;
let currentTab = $('#idFrameC .tabs').data('hash');
if(currentTab !== '#baskets_wrapper') {
return false; // can't drop on baskets if the baskets tab is not front
}
if ($(elem).hasClass('CHIM')) { if ($(elem).hasClass('CHIM')) {
if ($(elem).closest('.content').prev()[0] === $(this)[0]) { if ($(elem).closest('.content').prev()[0] === $(this)[0]) {
return false; return false;
@@ -864,7 +879,12 @@ return false;
dest.droppable({ dest.droppable({
accept: function (elem) { accept: function (elem) {
return false; // return false;
let currentTab = $('#idFrameC .tabs').data('hash');
if(currentTab !== '#baskets_wrapper' && currentTab !== '#baskets') {
return false; // can't drop on baskets if the baskets tab is not front
}
if ($(elem).hasClass('CHIM')) { if ($(elem).hasClass('CHIM')) {
if ($(elem).closest('.content')[0] === $(this)[0]) { if ($(elem).closest('.content')[0] === $(this)[0]) {
return false; return false;

View File

@@ -26,6 +26,8 @@ use Alchemy\Phrasea\Twig\PhraseanetExtension;
use Alchemy\Phrasea\Vocabulary\ControlProvider\ControlProviderInterface; use Alchemy\Phrasea\Vocabulary\ControlProvider\ControlProviderInterface;
use Alchemy\Phrasea\WorkerManager\Event\RecordEditInWorkerEvent; use Alchemy\Phrasea\WorkerManager\Event\RecordEditInWorkerEvent;
use Alchemy\Phrasea\WorkerManager\Event\WorkerEvents; use Alchemy\Phrasea\WorkerManager\Event\WorkerEvents;
use stdClass;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
@@ -342,6 +344,29 @@ class EditController extends Controller
return $this->app->json(['success' => true]); return $this->app->json(['success' => true]);
} }
/**
* performs an editing using a similar json-body as api_v3:record:patch (except here we can work on a list of records)
*
* @param Request $request
* @return JsonResponse
*/
public function applyJSAction(Request $request): JsonResponse
{
// todo : by worker
// for now call record_adapter. no check, no acl, ...
/** @var stdClass $arg */
$arg = json_decode($request->getContent());
foreach($arg->records as $rec) {
$r = $this->getApplicationBox()->get_databox($rec->sbas_id)->get_record($rec->record_id);
$r->setMetadatasByActions($arg->actions);
}
return $this->app->json(['success' => true]);
}
/** /**
* @param int $preset_id * @param int $preset_id
* @return Preset * @return Preset
@@ -359,7 +384,7 @@ class EditController extends Controller
* route GET "../prod/records/edit/presets/{preset_id}" * route GET "../prod/records/edit/presets/{preset_id}"
* *
* @param int $preset_id * @param int $preset_id
* @return \Symfony\Component\HttpFoundation\JsonResponse * @return JsonResponse
*/ */
public function presetsLoadAction($preset_id) public function presetsLoadAction($preset_id)
{ {
@@ -381,7 +406,7 @@ class EditController extends Controller
* route GET "../prod/records/edit/presets" * route GET "../prod/records/edit/presets"
* *
* @param Request $request * @param Request $request
* @return \Symfony\Component\HttpFoundation\JsonResponse * @return JsonResponse
*/ */
public function presetsListAction(Request $request) public function presetsListAction(Request $request)
{ {
@@ -399,7 +424,7 @@ class EditController extends Controller
* route DELETE "../prod/records/edit/presets/{preset_id}" * route DELETE "../prod/records/edit/presets/{preset_id}"
* *
* @param int $preset_id * @param int $preset_id
* @return \Symfony\Component\HttpFoundation\JsonResponse * @return JsonResponse
*/ */
public function presetsDeleteAction($preset_id) public function presetsDeleteAction($preset_id)
{ {
@@ -421,7 +446,7 @@ class EditController extends Controller
* route POST "../prod/records/edit/presets" * route POST "../prod/records/edit/presets"
* *
* @param Request $request * @param Request $request
* @return \Symfony\Component\HttpFoundation\JsonResponse * @return JsonResponse
*/ */
public function presetsSaveAction(Request $request) public function presetsSaveAction(Request $request)
{ {

View File

@@ -30,15 +30,24 @@ class ThesaurusController extends Controller
{ {
$sbas_id = $request->get('sbas_id'); $sbas_id = $request->get('sbas_id');
$tx_term_id = $request->get('tx_term_id'); $tx_term_id = $request->get('tx_term_id');
$records = RecordsRequest::fromRequest($this->app, $request, RecordsRequest::FLATTEN_YES_PRESERVE_STORIES, [ACL::CANMODIFRECORD]); $records = RecordsRequest::fromRequest($this->app, $request, RecordsRequest::FLATTEN_YES_PRESERVE_STORIES, [ACL::CANMODIFRECORD]);
// array of sbid/rid. too bad we cannot array_map on arraycollection
$recRefs = [];
foreach($records as $r) {
$recRefs[] = [
'sbas_id'=>$r->getDataboxId(),
'record_id'=>$r->getRecordId()
];
}
// twig parameters // twig parameters
$twp = [ $twp = [
'error' => null, 'error' => null,
'dlg_level' => $request->get('dlg_level'), 'dlg_level' => $request->get('dlg_level'),
// 'fields' => [], // fields the can receive the value // 'lst' => $records->serializedList(),
// 'fvalue' => 'Europe', 'records' => $recRefs,
'lst' => $records->serializedList(),
'received_cnt' => $records->received()->count(), 'received_cnt' => $records->received()->count(),
'rejected_cnt' => $records->rejected()->count(), 'rejected_cnt' => $records->rejected()->count(),
'up_paths' => [], 'up_paths' => [],

View File

@@ -12,9 +12,9 @@
namespace Alchemy\Phrasea\ControllerProvider\Prod; namespace Alchemy\Phrasea\ControllerProvider\Prod;
use Alchemy\Phrasea\Application as PhraseaApplication; use Alchemy\Phrasea\Application as PhraseaApplication;
use Alchemy\Phrasea\Core\LazyLocator;
use Alchemy\Phrasea\Controller\Prod\EditController; use Alchemy\Phrasea\Controller\Prod\EditController;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait; use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Alchemy\Phrasea\Core\LazyLocator;
use Silex\Application; use Silex\Application;
use Silex\ControllerProviderInterface; use Silex\ControllerProviderInterface;
use Silex\ServiceProviderInterface; use Silex\ServiceProviderInterface;
@@ -54,6 +54,11 @@ class Edit implements ControllerProviderInterface, ServiceProviderInterface
$controllers->get('/vocabulary/{vocabulary}/', 'controller.prod.edit:searchVocabularyAction'); $controllers->get('/vocabulary/{vocabulary}/', 'controller.prod.edit:searchVocabularyAction');
/** @uses \Alchemy\Phrasea\Controller\Prod\EditController::applyJSAction */
$controllers
->post('/applyjs/', 'controller.prod.edit:applyJSAction')
->bind('prod_edit_applyJSAction');
$controllers->post('/apply/', 'controller.prod.edit:applyAction'); $controllers->post('/apply/', 'controller.prod.edit:applyAction');
$controllers->get('/presets/{preset_id}', 'controller.prod.edit:presetsLoadAction'); $controllers->get('/presets/{preset_id}', 'controller.prod.edit:presetsLoadAction');

View File

@@ -42,11 +42,6 @@ class Thesaurus implements ControllerProviderInterface, ServiceProviderInterface
public function connect(Application $app) public function connect(Application $app)
{ {
$controllers = $this->createAuthenticatedCollection($app); $controllers = $this->createAuthenticatedCollection($app);
// $firewall = $this->getFirewall($app);
// $controllers->before(function () use ($firewall) {
// $firewall->requireRight(\ACL::CANMODIFRECORD);
// });
/** @uses ThesaurusController::dropRecordsAction() */ /** @uses ThesaurusController::dropRecordsAction() */
$controllers->get('/droprecords', 'controller.prod.thesaurus:dropRecordsAction'); $controllers->get('/droprecords', 'controller.prod.thesaurus:dropRecordsAction');

View File

@@ -32,11 +32,8 @@ use Alchemy\Phrasea\Model\Entities\User;
use Alchemy\Phrasea\Model\RecordInterface; use Alchemy\Phrasea\Model\RecordInterface;
use Alchemy\Phrasea\Model\Serializer\CaptionSerializer; use Alchemy\Phrasea\Model\Serializer\CaptionSerializer;
use Alchemy\Phrasea\Record\RecordReference; use Alchemy\Phrasea\Record\RecordReference;
use Alchemy\Phrasea\SearchEngine\Elastic\Indexer\Record\Hydrator\GpsPosition;
use Alchemy\Phrasea\SearchEngine\SearchEngineInterface;
use Alchemy\Phrasea\SearchEngine\SearchEngineOptions;
use Alchemy\Phrasea\WorkerManager\Event\WorkerEvents;
use Alchemy\Phrasea\WorkerManager\Event\RecordsWriteMetaEvent; use Alchemy\Phrasea\WorkerManager\Event\RecordsWriteMetaEvent;
use Alchemy\Phrasea\WorkerManager\Event\WorkerEvents;
use Doctrine\DBAL\Connection; use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DBALException; use Doctrine\DBAL\DBALException;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
@@ -1128,6 +1125,351 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
return $this; return $this;
} }
public function setMetadatasByActions(stdClass $actions)
{
// WIP crashes when trying to access an undefined stdClass property ? should return null ?
// $this->apply_body($actions);
return $this;
}
/*
* =============================================================================
* the following methods allows editing by the json api-v3:record:post format
*
*/
/**
* @param stdClass $b
* @param record_adapter $record
* @throws Exception
*/
private function apply_body(stdClass $b)
{
// do metadatas ops
if (is_array($b->metadatas)) {
$this->do_metadatas($b->metadatas);
}
// do sb ops
if (is_array($b->status)) {
$this->do_status($b->status);
}
if(!is_null($b->base_id)) {
$this->do_collection($b->base_id);
}
}
/**
* @param $base_id
*/
private function do_collection($base_id)
{
$this->move_to_collection(collection::getByCollectionId($this->app, $this->getDatabox(), $base_id));
}
//////////////////////////////////
/// TODO : keep multi-values uniques !
/// it should be done in record_adapter
//////////////////////////////////
/**
* @param $metadatas
* @throws Exception
*/
private function do_metadatas($metadatas)
{
/** @var databox_field[] $struct */
$struct = $this->getDatabox()->get_meta_structure();
$structByKey = [];
$allStructFields = [];
foreach ($struct as $f) {
$allStructFields[$f->get_id()] = $f;
$structByKey[$f->get_id()] = &$allStructFields[$f->get_id()];
$structByKey[$f->get_name()] = &$allStructFields[$f->get_id()];
}
$metadatas_ops = [];
foreach ($metadatas as $_m) {
// sanity
if($_m->meta_struct_id && $_m->field_name) { // WIP crashes if meta_struct_id is undefined
throw new Exception("define meta_struct_id OR field_name, not both.");
}
// select fields that match meta_struct_id or field_name (can be arrays)
$fields_list = null; // to filter caption_fields from record, default all
$struct_fields = []; // struct fields that match meta_struct_id or field_name
$field_keys = $_m->meta_struct_id ? $_m->meta_struct_id : $_m->field_name; // can be null if none defined (=match all)
if($field_keys !== null) {
if (!is_array($field_keys)) {
$field_keys = [$field_keys];
}
$fields_list = [];
foreach ($field_keys as $k) {
if(array_key_exists($k, $structByKey)) {
$fields_list[] = $structByKey[$k]->get_name();
$struct_fields[$structByKey[$k]->get_id()] = $structByKey[$k];
}
else {
throw new Exception(sprintf("unknown field (%s).", $k));
}
}
}
else {
// no meta_struct_id, no field_name --> match all struct fields !
$struct_fields = $allStructFields;
}
$caption_fields = $this->get_caption()->get_fields($fields_list, true);
$meta_id = is_null($_m->meta_id) ? null : (int)($_m->meta_id);
if(!($match_method = (string)($_m->match_method))) {
$match_method = 'ignore_case';
}
if(!in_array($match_method, ['strict', 'ignore_case', 'regexp'])) {
throw new Exception(sprintf("bad match_method (%s).", $match_method));
}
$values = [];
if(is_array($_m->value)) {
foreach ($_m->value as $v) {
if(($v = trim((string)$v)) !== '') {
$values[] = $v;
}
}
}
else {
if(($v = trim((string)($_m->value))) !== '') {
$values[] = $v;
}
}
if(!($action = (string)($_m->action))) {
$action = 'set';
}
switch ($_m->action) {
case 'set':
$ops = $this->metadata_set($struct_fields, $caption_fields, $meta_id, $values);
break;
case 'add':
$ops = $this->metadata_add($struct_fields, $values);
break;
case 'delete':
$ops = $this->metadata_replace($caption_fields, $meta_id, $match_method, $values, null);
break;
case 'replace':
if (!is_string($_m->replace_with) && !is_null($_m->replace_with)) {
throw new Exception("bad \"replace_with\" for action \"replace\".");
}
$ops = $this->metadata_replace($caption_fields, $meta_id, $match_method, $values, $_m->replace_with);
break;
default:
throw new Exception(sprintf("bad action (%s).", $action));
}
$metadatas_ops = array_merge($metadatas_ops, $ops);
}
$this->set_metadatas($metadatas_ops, true);
// order to write meta in file
$this->app['dispatcher']->dispatch(WorkerEvents::RECORDS_WRITE_META,
new RecordsWriteMetaEvent([$this->getRecordId()], $this->getDataboxId()));
}
/**
* @param $statuses
* @return array
* @throws Exception
*/
private function do_status($statuses)
{
$datas = strrev($this->getStatus());
foreach ($statuses as $status) {
$n = (int)($status->bit);
$value = (int)($status->state);
if ($n > 31 || $n < 4) {
throw new Exception(sprintf("Invalid status bit number (%s).", $n));
}
if ($value < 0 || $value > 1) {
throw new Exception(sprintf("Invalid status bit state (%s) for bit (%s).", $value, $n));
}
$datas = substr($datas, 0, ($n)) . $value . substr($datas, ($n + 1));
}
$this->setStatus(strrev($datas));
}
private function match($pattern, $method, $value)
{
switch ($method) {
case 'strict':
return $value === $pattern;
case 'ignore_case':
return strtolower($value) === strtolower($pattern);
case 'regexp':
return preg_match($pattern, $value) == 1;
}
return false;
}
/**
* @param databox_field[] $struct_fields struct-fields (from struct) matching meta_struct_id or field_name
* @param caption_field[] $caption_fields caption-fields (from record) matching meta_struct_id or field_name (or all if not set)
* @param int|null $meta_id
* @param string[] $values
*
* @return array ops to execute
* @throws Exception
*/
private function metadata_set(array $struct_fields, $caption_fields, $meta_id, $values): array
{
$ops = [];
// if one field was multi-valued and no meta_id was set, we must delete all values
foreach ($caption_fields as $cf) {
foreach ($cf->get_values() as $field_value) {
if (is_null($meta_id) || $field_value->getId() === (int)$meta_id) {
$ops[] = [
'meta_struct_id' => $cf->get_meta_struct_id(),
'meta_id' => $field_value->getId(),
'value' => ''
];
}
}
}
// now set values to matching struct_fields
foreach ($struct_fields as $sf) {
if($sf->is_multi()) {
// add the non-null value(s)
foreach ($values as $value) {
if ($value) {
$ops[] = [
'meta_struct_id' => $sf->get_id(),
'meta_id' => $meta_id, // can be null
'value' => $value
];
}
}
}
else {
// mono-valued
if(count($values) > 1) {
throw new Exception(sprintf("setting mono-valued (%s) requires only one value.", $sf->get_name()));
}
if( ($value = $values[0]) ) {
$ops[] = [
'meta_struct_id' => $sf->get_id(),
'meta_id' => $meta_id, // probably null,
'value' => $value
];
}
}
}
return $ops;
}
/**
* @param databox_field[] $struct_fields struct-fields (from struct) matching meta_struct_id or field_name
* @param string[] $values
*
* @return array ops to execute
* @throws Exception
*/
private function metadata_add($struct_fields, $values)
{
$ops = [];
// now set values to matching struct_fields
foreach ($struct_fields as $sf) {
if(!$sf->is_multi()) {
throw new Exception(sprintf("can't \"add\" to mono-valued (%s).", $sf->get_name()));
}
foreach ($values as $value) {
$ops[] = [
'meta_struct_id' => $sf->get_id(),
'meta_id' => null,
'value' => $value
];
}
}
return $ops;
}
/**
* @param caption_field[] $caption_fields caption-fields (from record) matching meta_struct_id or field_name (or all if not set)
* @param int|null $meta_id
* @param string $match_method "strict" | "ignore_case" | "regexp"
* @param string[] $values
* @param string|null $replace_with
*
* @return array ops to execute
*/
private function metadata_replace($caption_fields, $meta_id, $match_method, $values, $replace_with)
{
$ops = [];
$replace_with = trim((string)$replace_with);
foreach ($caption_fields as $cf) {
// match all ?
if(is_null($meta_id) && count($values) == 0) {
foreach ($cf->get_values() as $field_value) {
$ops[] = [
'meta_struct_id' => $cf->get_meta_struct_id(),
'meta_id' => $field_value->getId(),
'value' => $replace_with
];
}
}
// match by meta-id ?
if (!is_null($meta_id)) {
foreach ($cf->get_values() as $field_value) {
if ($field_value->getId() === $meta_id) {
$ops[] = [
'meta_struct_id' => $cf->get_meta_struct_id(),
'meta_id' => $field_value->getId(),
'value' => $replace_with
];
}
}
}
// match by value(s) ?
foreach ($values as $value) {
foreach ($cf->get_values() as $field_value) {
$rw = $replace_with;
if($match_method=='regexp' && $rw != '') {
$rw = preg_replace($value, $rw, $field_value->getValue());
}
if ($this->match($value, $match_method, $field_value->getValue())) {
$ops[] = [
'meta_struct_id' => $cf->get_meta_struct_id(),
'meta_id' => $field_value->getId(),
'value' => $rw
];
}
}
}
}
return $ops;
}
/*
*
* END editing by the json api-v3:record:post format
* =============================================================================
*/
/** /**
* @return record_adapter * @return record_adapter
*/ */

View File

@@ -1,3 +1,6 @@
<h3 style="color: red">POC/Experimental. The OK button will <u>NOT</u> edit records.</h3>
{% if error %} {% if error %}
{{ error }} {{ error }}
@@ -11,7 +14,7 @@
<form id="DroppedOnTH_form"> <form id="DroppedOnTH_form">
<table> <table>
<tr> <tr>
<th>svalue</th> <th>value</th>
<th><span class="fieldSelected" style="display: none">operation</span></th> <th><span class="fieldSelected" style="display: none">operation</span></th>
<th>to field</th> <th>to field</th>
</tr> </tr>
@@ -43,7 +46,9 @@
<option class="mono" value="set">set to</option> <option class="mono" value="set">set to</option>
<option class="multi" value="add">add to</option> <option class="multi" value="add">add to</option>
<option class="multi" value="replace">replace all</option> <option class="multi" value="replace">replace all</option>
<option class="mono multi" value="remove">remove from</option> {# do NOT mix the following 2 options as one #}
<option class="mono" value="delete">delete</option>
<option class="multi" value="delete">remove from</option>
</select> </select>
</td> </td>
<td> <td>
@@ -88,14 +93,30 @@
$(' .fieldSelect').filter(function () { return $(this).prop('selectedIndex')>0;}).each(function () { $(' .fieldSelect').filter(function () { return $(this).prop('selectedIndex')>0;}).each(function () {
let n = $(this).data('n'); let n = $(this).data('n');
data.push({ data.push({
'field': $(this).val(), 'field_name': $(this).val(),
'op' : $(' .actionSelect._'+n, $container).val(), 'action' : $(' .actionSelect._'+n, $container).val(),
'value': $(' .synonym._'+n, $container).val() 'value' : $(' .synonym._'+n, $container).val()
}); });
}); });
data = {
'records': {{ records|json_encode|raw }},
'actions': {
'metadatas': data
}
};
console.log(data); console.log(data);
// $( this ).dialog( "close" ); $.ajax({
url: "{{ path('prod_edit_applyJSAction') }}",
type: "POST",
contentType: "application/json",
data: JSON.stringify(data),
success: function (data, textStatus) {
console.log(data);
}
},
);
} }
}, },
{ {
@@ -115,18 +136,13 @@
let select = $(this); let select = $(this);
let n = select.data('n'); let n = select.data('n');
if( $('option:eq(' + select.prop('selectedIndex') + ')', select).data('multi') ) { // show only possible actions, depending on field is mono/multi
// this select is on a multi-valued field let actionSelect = $(' .actionSelect._'+n, $container);
$(' .actionSelect._'+n+' OPTION.mono', $container).hide(); let multi = !!$('option:eq(' + select.prop('selectedIndex') + ')', select).data('multi');
$(' .actionSelect._'+n+' OPTION.multi', $container).show(); $(' OPTION.mono', actionSelect).toggle(!multi);
$(' .actionSelect._'+n).prop('selectedIndex', 1); // add $(' OPTION.multi', actionSelect).toggle(multi);
} // set default action
else { actionSelect.prop('selectedIndex', multi ? 1 : 0); // 1=add : 0=set
// this select is on a mono-valued field
$(' .actionSelect._'+n+' OPTION.multi', $container).hide();
$(' .actionSelect._'+n+' OPTION.mono', $container).show();
$(' .actionSelect._'+n).prop('selectedIndex', 0); // set
}
// if at least one destination field is set, show some elements // if at least one destination field is set, show some elements
let oneFieldSet = false; let oneFieldSet = false;

View File

@@ -145,6 +145,7 @@
{% endif %} {% endif %}
</div> </div>
{% if basket.getValidation() %}
<script type="text/javascript"> <script type="text/javascript">
$( ".update-feed-validation" ).on( "submit", function( event ) { $( ".update-feed-validation" ).on( "submit", function( event ) {
@@ -197,5 +198,6 @@
</script> </script>
{% endif %}

View File

@@ -184,6 +184,7 @@
{% include 'prod/tab_headers.html.twig' %} {% include 'prod/tab_headers.html.twig' %}
{% import 'prod/WorkZone/Macros.html.twig' as WorkZoneMacros %} {% import 'prod/WorkZone/Macros.html.twig' as WorkZoneMacros %}
{% set expose_activate = app['conf'].get(['phraseanet-service', 'expose-service', 'activated']) %} {% set expose_activate = app['conf'].get(['phraseanet-service', 'expose-service', 'activated']) %}
{% if expose_activate == 'true' %} {% if expose_activate == 'true' %}
{% block tab_headers_wrapper %} {% block tab_headers_wrapper %}
@@ -268,6 +269,7 @@
</div> </div>
{% include 'prod/tab_thesaurus.html.twig' with {has_access_to_module: app.getAclForUser(app.getAuthenticatedUser()).has_access_to_module('thesaurus')} %} {% include 'prod/tab_thesaurus.html.twig' with {has_access_to_module: app.getAclForUser(app.getAuthenticatedUser()).has_access_to_module('thesaurus')} %}
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% if plugins.workzone is not empty %} {% if plugins.workzone is not empty %}
<div id="plugins" class="PNB {{ plugins.workzone|length > 1 ? 'multiple-plugin' : 'single-plugin' }}" style="top:52px;"> <div id="plugins" class="PNB {{ plugins.workzone|length > 1 ? 'multiple-plugin' : 'single-plugin' }}" style="top:52px;">

View File

@@ -17,7 +17,10 @@
</li> </li>
{% endif %} {% endif %}
<li class="ui-corner-top baskets"> <li class="ui-corner-top baskets">
<a href="#baskets_wrapper" class="WZbasketTab WZtabs"> {% set expose_activate = app['conf'].get(['phraseanet-service', 'expose-service', 'activated']) %}
{% set hash = expose_activate ? '#baskets_wrapper' : '#baskets' %}
<a href="{{ hash }}" class="WZbasketTab WZtabs">
<img src="/assets/common/images/icons/workzone32.png" title="{{ 'phraseanet:: baskets' | trans }}"/> <img src="/assets/common/images/icons/workzone32.png" title="{{ 'phraseanet:: baskets' | trans }}"/>
<div id="basket_menu_trigger">&#9660;</div> <div id="basket_menu_trigger">&#9660;</div>
</a> </a>