Refactor record property (status, type)

update property route

Fixed status

Conflicts:

	lib/Alchemy/Phrasea/Controller/Prod/Record/Property.php
This commit is contained in:
Nicolas Le Goff
2012-10-03 17:18:42 +02:00
parent df62a30452
commit 8710e0f3cb
8 changed files with 407 additions and 63 deletions

View File

@@ -14,6 +14,7 @@ rewrite ^/developers/.*$ /index.php last;
rewrite ^/permalink/.*$ /index.php last;
rewrite ^/datafiles/.*$ /index.php last;
rewrite ^/prod/records/edit/.*$ /index.php last;
rewrite ^/prod/records/property/.*$ /index.php last;
rewrite ^/prod/records/movecollection/.*$ /index.php last;
rewrite ^/prod/records/delete/.*$ /index.php last;
rewrite ^/prod/order/.*$ /index.php last;

View File

@@ -44,6 +44,7 @@ use Alchemy\Phrasea\Controller\Prod\Order;
use Alchemy\Phrasea\Controller\Prod\Printer;
use Alchemy\Phrasea\Controller\Prod\Push;
use Alchemy\Phrasea\Controller\Prod\Query;
use Alchemy\Phrasea\Controller\Prod\Record\Property;
use Alchemy\Phrasea\Controller\Prod\Root as Prod;
use Alchemy\Phrasea\Controller\Prod\Story;
use Alchemy\Phrasea\Controller\Prod\Tools;
@@ -135,6 +136,7 @@ return call_user_func(function($environment = null) {
$app->mount('/prod/lists', new UsrLists());
$app->mount('/prod/MustacheLoader', new MustacheLoader());
$app->mount('/prod/records/edit', new Edit());
$app->mount('/prod/records/property', new Property());
$app->mount('/prod/records/movecollection', new MoveCollection());
$app->mount('/prod/bridge/', new Bridge());
$app->mount('/prod/push/', new Push());

View File

@@ -0,0 +1,205 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2012 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\Controller\Prod\Record;
use Alchemy\Phrasea\Controller\RecordsRequest;
use Silex\Application;
use Silex\ControllerProviderInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
/**
*
* @license http://opensource.org/licenses/gpl-3.0 GPLv3
* @link www.phraseanet.com
*/
class Property implements ControllerProviderInterface
{
/**
* {@inheritDoc}
*/
public function connect(Application $app)
{
$controllers = $app['controllers_factory'];
$controllers->before(function(Request $request) use ($app) {
$response = $app['firewall']->requireNotGuest();
if ($response instanceof Response) {
return $response;
}
});
$controllers->get('/', $this->call('displayProperty'))
->bind('display_property');
$controllers->post('/status/', $this->call('changeStatus'))
->bind('change_status');
return $controllers;
}
/**
* Display property
*
* @param Application $app
* @param Request $request
* @return Response
*/
public function displayProperty(Application $app, Request $request)
{
if (!$request->isXmlHttpRequest()) {
$app->abort(400);
}
$records = RecordsRequest::fromRequest($app, $request, false, array('chgstatus'));
$databoxStatus = \databox_status::getDisplayStatus($app);
$statusBit = $recordsType = $nRec = $toRemove = array();
foreach ($records as $key => $record) {
if (!$app['phraseanet.user']->ACL()->has_hd_grant($record) ||
!$app['phraseanet.user']->ACL()->has_preview_grant($record)) {
try {
$conn = $record->get_databox()->get_connection();
$sql = sprintf('SELECT record_id FROM record WHERE ((status ^ %s) & %s) = 0 AND record_id = :record_id', $app['phraseanet.user']->ACL()->get_mask_xor($record->get_base_id()), $app['phraseanet.user']->ACL()->get_mask_and($record->get_base_id()));
$stmt = $conn->prepare($sql);
$stmt->execute(array(':record_id' => $record->get_record_id()));
if (0 === $stmt->rowCount()) {
$toRemove[] = $key;
}
$stmt->closeCursor();
unset($stmt);
} catch (Exception $e) {
$toRemove[] = $key;
}
}
}
foreach ($toRemove as $key) {
$records->remove($key);
}
foreach ($records as $record) {
$sbasId = $record->get_databox()->get_sbas_id();
if (!isset($nRec[$sbasId])) {
$nRec[$sbasId] = array('stories' => 0, 'records' => 0);
}
$nRec[$sbasId]['records']++;
if ($record->is_grouping()) {
$nRec[$sbasId]['stories']++;
}
if (!isset($recordsType[$sbasId])) {
$recordsType[$sbasId] = array();
}
if (!isset($recordsType[$sbasId][$record->get_type()])) {
$recordsType[$sbasId][$record->get_type()] = array();
}
$recordsType[$sbasId][$record->get_type()] = $record;
if (!isset($statusBit[$sbasId])) {
$statusBit[$sbasId] = isset($databoxStatus[$sbasId]) ? $databoxStatus[$sbasId] : array();
foreach (array_keys($statusBit[$sbasId]) as $bit) {
$statusBit[$sbasId][$bit]['nset'] = 0;
}
}
$status = strrev($record->get_status());
foreach (array_keys($statusBit[$sbasId]) as $bit) {
$statusBit[$sbasId][$bit]["nset"] += substr($status, $bit, 1) !== "0" ? 1 : 0;
}
}
foreach ($records->databoxes() as $databox) {
$sbasId = $databox->get_sbas_id();
foreach ($statusBit[$sbasId] as $bit => $values) {
$statusBit[$sbasId][$bit]["status"] = $values["nset"] == 0 ? 0 : ($values["nset"] == $nRec[$sbasId]['records'] ? 1 : 2);
}
}
return $app['twig']->render('prod/actions/Property/index.html.twig', array(
'records' => $records,
'statusBit' => $statusBit,
'recordsType' => $recordsType,
'nRec' => $nRec
));
}
public function changeStatus(Application $app, Request $request)
{
$applyStatusToChildren = $request->request->get('apply_to_children', array());
$records = RecordsRequest::fromRequest($app, $request, false, array('chgstatus'));
$updated = array();
$postStatus = $request->request->get('status');
foreach ($records as $record) {
$sbasId = $record->get_databox()->get_sbas_id();
//update record
$updated[$record->get_serialize_key()] = $this->updateRecordStatus($record, $postStatus);
//update children if current record is a story
if (isset($applyStatusToChildren[$sbasId]) && $record->is_grouping()) {
foreach ($record->get_children() as $child) {
$updated[$record->get_serialize_key()] = $this->updateRecordStatus($child, $postStatus);
}
}
}
return $app->json(array('success' => true, 'updated' => $updated), 201);
}
private function updateRecordStatus(\record_adapter $record, Array $postStatus)
{
$sbasId = $record->get_databox()->get_sbas_id();
if (isset($postStatus[$sbasId]) && is_array($postStatus[$sbasId])) {
$postStatus = $postStatus[$sbasId];
$currentStatus = strrev($record->get_status());
$newStatus = '';
foreach (range(0, 63) as $i) {
$newStatus .= isset($postStatus[$i]) ? ($postStatus[$i] ? '1' : '0') : $currentStatus[$i];
}
$record->set_binary_status(strrev($newStatus));
return array(
'current_status' => $currentStatus,
'new_status' => $newStatus
);
}
}
/**
* Prefix the method to call with the controller class name
*
* @param string $method The method to call
* @return string
*/
private function call($method)
{
return sprintf('%s::%s', __CLASS__, $method);
}
}

View File

@@ -1,4 +1,4 @@
<?php
<?php //
use Alchemy\Phrasea\Application;

View File

@@ -1298,7 +1298,7 @@ class record_adapter implements record_Interface, cache_cacheableInterface
$stmt->closeCursor();
try {
$sphinx = sphinxrt::get_instance();
$sphinx = sphinxrt::get_instance($this->app['phraseanet.registry']);
$sbas_params = phrasea::sbas_params($this->app);
$sbas_id = $this->get_sbas_id();

View File

@@ -0,0 +1,148 @@
{% set nbReceivedDocuments = records.received().count() %}
{% set nbEditableDocuments = records.count() %}
<div id='tabs-records-property'>
<ul>
<li><a href="#property-statut">{% trans 'Records Statut' %}</a></li>
<li><a href="#property-type">{% trans 'Records type' %}</a></li>
</ul>
<div id='property-statut'>
<p class="header" style='text-align:center;'>
<h4>
{% trans %}
You have selected one document.
{% plural nbReceivedDocuments %}
You have selected {{ nbReceivedDocuments }} documents.
{% endtrans %}
{% if nbEditableDocuments < nbReceivedDocuments %}
{% trans %}
Only one document is editable.
{% plural nbEditableDocuments %}
Only {{ nbEditableDocuments }} documents are editable.
{% endtrans %}
{% endif %}
</h4>
</p>
<form style='padding:15px;' name="change-records-status" action="/prod/records/property/status/" method="POST">
<input name="lst" type="hidden" value="{{ records.serializedList() }}"/>
{% for databox in records.databoxes() %}
{% set sbasId = databox.get_sbas_id() %}
{% set nbItems = attribute(nRec, sbasId) %}
{% set nbRecords = nbItems['records'] %}
{% set nbStories = nbItems['stories'] %}
<table style='width:auto;margin:0 auto'>
<thead>
<tr>
<th colspan="6">
{{ databox.get_viewname()|title }}
</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="6" style='font-size:11px;'>
{% if nbRecords == 0 and nbStories > 0 %}
<i>({% trans %}Status edition of stories{% endtrans %})</i>
{% elseif nbRecords > 0 and nbStories == 0 %}
<i>({% trans %}Status edition of documents{% endtrans %})</i>
{% endif %}
</td>
</tr>
{% set databoxStatus = attribute(statusBit, sbasId) %}
{% for bit,values in databoxStatus %}
{% set inverse = 0 %}
{% if values["status"] == "2" %}
{% set inverse = 2 %}
{% elseif values["status"] == "0" %}
{% set inverse = 1 %}
{% endif %}
<tr>
<td colspan="6">
<h6>{{ values['name']|title }}</h6>
</td>
</tr>
<tr>
<td style='text-align:right'>
{% if values['img_off'] is not empty %}
<label for="status-radio-{{ sbasId ~ "-" ~ bit ~ '-off'}}">
<img src="{{ values['img_off'] }}" width="16" height="16" />
</label>
{% endif %}
</td>
<td style='text-align:right'>
<label for="status-radio-{{ sbasId ~ "-" ~ bit ~ '-off'}}">
{{ values['labeloff']|default('off') }}
</label>
</td>
<td style='text-align:right'>
<input id="status-radio-{{ sbasId ~ "-" ~ bit ~ '-off'}}" type="radio" name="status[{{ sbasId }}][{{ bit }}]" value="0" {% if inverse == 1 %}checked="checked"{% endif %}/>
</td>
<td style='text-align:left'>
<input id="status-radio-{{ sbasId ~ "-" ~ bit ~ '-on'}}" type="radio" name="status[{{ sbasId }}][{{ bit }}]" value="1" {% if inverse == 0 %}checked="checked"{% endif %}/>
</td>
<td style='text-align:left'>
<label for="status-radio-{{ sbasId ~ "-" ~ bit ~ '-on'}}">
{{ values['labelon']|default('on') }}
</label>
</td>
<td style='text-align:left'>
{% if values['img_on'] is not empty %}
<label for="status-radio-{{ sbasId ~ "-" ~ bit ~ '-on'}}">
<img src="{{ values['img_on'] }}" width="16" height="16" />
</label>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
{% if nbStories > 0 %}
<tr>
<td colspan="6"><input type="checkbox" name="apply_to_children[{{ sbasId }}]"/></td>
</tr>
{% endif %}
</tfoot>
</table>
{% endfor %}
<div class="form-actions">
<button type="button" class="btn btn-primary submiter">{% trans "Apply changes" %}</button>
<button type="button" class="btn">{% trans "Cancel" %}</button>
</div>
</form>
</div>
<div id='property-type'>TODO</div>
</div>
<script type="text/javascript">
$(document).ready(function(){
$("#tabs-records-property").tabs();
var $dialog = p4.Dialog.get(1);
var $dialogBox = $dialog.getDomElement();
var form = $("form[name=change-records-status]", $dialogBox);
var button = $(".submiter", form);
button.bind("click", function(){
$.ajax({
type: form.attr("method"),
url: form.attr("action"),
data: form.serializeArray(),
dataType: 'json',
beforeSend:function(){
button.attr("disabled", true);
//@todo add loader
},
success: function(data){
$dialog.Close(1);
},
complete: function(){
button.attr("disabled", false);
}
});
});
});
</script>

View File

@@ -16,6 +16,7 @@
RewriteRule ^developers/.*$ /index.php [L]
RewriteRule ^login/.*$ /index.php [L]
RewriteRule ^prod/records/edit/.*$ /index.php [L]
RewriteRule ^prod/records/property/.*$ /index.php [L]
RewriteRule ^prod/records/movecollection/.*$ /index.php [L]
RewriteRule ^prod/records/delete/.*$ /index.php [L]
RewriteRule ^prod/order/.*$ /index.php [L]

View File

@@ -1703,29 +1703,29 @@ function chgCollThis(datas)
});
}
function chgStatusThis(url)
{
url = "docfunction.php?"+url;
$('#MODALDL').attr('src','about:blank');
$('#MODALDL').attr('src',url);
var t = (bodySize.y - 400) / 2;
var l = (bodySize.x - 550) / 2;
$('#MODALDL').css({
'display': 'block',
'opacity': 0,
'width': '550px',
'position': 'absolute',
'top': t,
'left': l,
'height': '400px'
}).fadeTo(500, 1);
showOverlay(2);
$('#tooltip').hide();
}
//function chgStatusThis(url)
//{
// url = "docfunction.php?"+url;
// $('#MODALDL').attr('src','about:blank');
// $('#MODALDL').attr('src',url);
//
//
// var t = (bodySize.y - 400) / 2;
// var l = (bodySize.x - 550) / 2;
//
// $('#MODALDL').css({
// 'display': 'block',
// 'opacity': 0,
// 'width': '550px',
// 'position': 'absolute',
// 'top': t,
// 'left': l,
// 'height': '400px'
// }).fadeTo(500, 1);
//
// showOverlay(2);
// $('#tooltip').hide();
//}
function pushThis(sstt_id, lst, story)
@@ -2152,52 +2152,39 @@ function activeIcons()
});
$('.TOOL_chgstatus_btn').live('click', function(){
var value="";
if($(this).hasClass('results_window'))
{
if(p4.Results.Selection.length() > 0)
value = "lst=" + p4.Results.Selection.serialize();
}
else
{
if($(this).hasClass('basket_window'))
{
if(p4.WorkZone.Selection.length() > 0)
value = "lst=" + p4.WorkZone.Selection.serialize();
else
value = "SSTTID=" + $('.SSTT.active').attr('id').split('_').slice(1,2).pop();
var params = {};
var $this = $(this);
console.log(p4.Results.Selection.length());
if ($this.hasClass('results_window')) {
if (p4.Results.Selection.length() > 0) {
params.lst = p4.Results.Selection.serialize();
}
else
{
if($(this).hasClass('basket_element'))
{
value = "SSTTID=" + $('.SSTT.active').attr('id').split('_').slice(1,2).pop();
} else {
if ($this.hasClass('basket_window')) {
if (p4.WorkZone.Selection.length() > 0) {
params.lst = p4.WorkZone.Selection.serialize();
} else {
params.ssel = $('.SSTT.active').attr('id').split('_').slice(1,2).pop();
}
else
{
if($(this).hasClass('story_window'))
{
if(p4.WorkZone.Selection.length() > 0)
{
value = "lst=" + p4.WorkZone.Selection.serialize();
}
else
{
value = "story=" + $('.SSTT.active').attr('id').split('_').slice(1,2).pop();
} else {
if ($this.hasClass('basket_element')) {
params.ssel = $('.SSTT.active').attr('id').split('_').slice(1,2).pop();
} else {
if ($this.hasClass('story_window')) {
if (p4.WorkZone.Selection.length() > 0) {
params.lst = p4.WorkZone.Selection.serialize();
} else {
params.story = $('.SSTT.active').attr('id').split('_').slice(1,2).pop();
}
}
}
}
}
if(value !== '')
{
chgStatusThis(value);
}
else
{
if (false === $.isEmptyObject(params)) {
var dialog = p4.Dialog.Create();
dialog.load('/prod/records/property/', 'GET', params);
} else {
alert(language.nodocselected);
}
});